From 7b93688ad7150a111556e40f34964abeebada98d Mon Sep 17 00:00:00 2001 From: rainy liu Date: Sat, 29 Jun 2024 19:01:40 +0800 Subject: [PATCH] fix --- ffigen.yaml | 2 + lib/opencv_dart.dart | 1 + lib/src/dnn/dnn_async.dart | 13 +- lib/src/features2d/features2d.dart | 99 ++++-- lib/src/objdetect/objdetect_async.dart | 54 ++-- src/features2d/features2d.cpp | 55 +--- src/features2d/utils.hpp | 61 ++++ test/features2d/features2d_async_test.dart | 356 +++++++++++++++++++++ test/{ => features2d}/features2d_test.dart | 0 9 files changed, 542 insertions(+), 99 deletions(-) create mode 100644 src/features2d/utils.hpp create mode 100644 test/features2d/features2d_async_test.dart rename test/{ => features2d}/features2d_test.dart (100%) diff --git a/ffigen.yaml b/ffigen.yaml index 50fd55c4..50e74e63 100644 --- a/ffigen.yaml +++ b/ffigen.yaml @@ -30,6 +30,7 @@ headers: - src/extra/img_hash.h - src/extra/wechat_qrcode.h - src/features2d/features2d.h + - src/features2d/features2d_async.h - src/gapi/gapi.h - src/highgui/highgui.h - src/imgcodecs/imgcodecs.h @@ -62,6 +63,7 @@ headers: - src/extra/img_hash.h - src/extra/wechat_qrcode.h - src/features2d/features2d.h + - src/features2d/features2d_async.h - src/gapi/gapi.h - src/highgui/highgui.h - src/imgcodecs/imgcodecs.h diff --git a/lib/opencv_dart.dart b/lib/opencv_dart.dart index 55230e0c..12133f60 100644 --- a/lib/opencv_dart.dart +++ b/lib/opencv_dart.dart @@ -30,6 +30,7 @@ export 'src/core/vec.dart'; export 'src/dnn/dnn.dart'; export 'src/dnn/dnn_async.dart'; export 'src/features2d/features2d.dart'; +export 'src/features2d/features2d_async.dart'; export 'src/highgui/highgui.dart'; export 'src/imgcodecs/imgcodecs.dart'; export 'src/imgcodecs/imgcodecs_async.dart'; diff --git a/lib/src/dnn/dnn_async.dart b/lib/src/dnn/dnn_async.dart index a8d6c008..46c5014a 100644 --- a/lib/src/dnn/dnn_async.dart +++ b/lib/src/dnn/dnn_async.dart @@ -2,8 +2,8 @@ library cv; import 'dart:ffi' as ffi; import 'dart:typed_data'; + import 'package:ffi/ffi.dart'; -import './dnn.dart'; import '../core/base.dart'; import '../core/mat.dart'; @@ -13,6 +13,7 @@ import '../core/scalar.dart'; import '../core/size.dart'; import '../core/vec.dart'; import '../opencv.g.dart' as cvg; +import './dnn.dart'; extension LayerAsync on Layer { Future get nameAsync async { @@ -93,8 +94,11 @@ extension NetAsync on Net { return rval; } - static Future fromBytesAsync(String framework, Uint8List bufferModel, - {Uint8List? bufferConfig}) async { + static Future fromBytesAsync( + String framework, + Uint8List bufferModel, { + Uint8List? bufferConfig, + }) async { bufferConfig ??= Uint8List(0); final cFramework = framework.toNativeUtf8().cast(); final bufM = VecUChar.fromList(bufferModel); @@ -302,7 +306,8 @@ extension NetAsync on Net { final rval = cvRunAsync2<(VecFloat, VecInt)>( (callback) => CFFI.Net_GetInputDetails_Async(ref, callback), (c, sc, zp) => c.complete( - (VecFloat.fromPointer(sc.cast()), VecInt.fromPointer(zp.cast()))), + (VecFloat.fromPointer(sc.cast()), VecInt.fromPointer(zp.cast())), + ), ); return rval; } diff --git a/lib/src/features2d/features2d.dart b/lib/src/features2d/features2d.dart index e0262c16..bb16c71e 100644 --- a/lib/src/features2d/features2d.dart +++ b/lib/src/features2d/features2d.dart @@ -22,6 +22,7 @@ class AKAZE extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory AKAZE.fromPointer(cvg.AKAZEPtr ptr, [bool attach = true]) => AKAZE._(ptr, attach); /// returns a new AKAZE algorithm /// @@ -50,7 +51,9 @@ class AKAZE extends CvStruct { (VecKeyPoint ret, Mat desc) detectAndCompute(Mat src, Mat mask) { final desc = Mat.empty(); final ret = calloc(); - cvRun(() => CFFI.AKAZE_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret)); + cvRun( + () => CFFI.AKAZE_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret), + ); return (VecKeyPoint.fromPointer(ret), desc); } @@ -75,6 +78,8 @@ class AgastFeatureDetector extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory AgastFeatureDetector.fromPointer(cvg.AgastFeatureDetectorPtr ptr, [bool attach = true]) => + AgastFeatureDetector._(ptr, attach); /// returns a new AgastFeatureDetector algorithm /// @@ -96,8 +101,9 @@ class AgastFeatureDetector extends CvStruct { return VecKeyPoint.fromPointer(ret); } - static final finalizer = - OcvFinalizer(CFFI.addresses.AgastFeatureDetector_Close); + static final finalizer = OcvFinalizer( + CFFI.addresses.AgastFeatureDetector_Close, + ); void dispose() { finalizer.detach(this); @@ -118,6 +124,7 @@ class BRISK extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory BRISK.fromPointer(cvg.BRISKPtr ptr, [bool attach = true]) => BRISK._(ptr, attach); /// returns a new BRISK algorithm /// @@ -146,7 +153,9 @@ class BRISK extends CvStruct { (VecKeyPoint, Mat) detectAndCompute(Mat src, Mat mask) { final desc = Mat.empty(); final ret = calloc(); - cvRun(() => CFFI.BRISK_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret)); + cvRun( + () => CFFI.BRISK_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret), + ); return (VecKeyPoint.fromPointer(ret), desc); } @@ -185,6 +194,8 @@ class FastFeatureDetector extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory FastFeatureDetector.fromPointer(cvg.FastFeatureDetectorPtr ptr, [bool attach = true]) => + FastFeatureDetector._(ptr, attach); /// returns a new FastFeatureDetector algorithm /// @@ -227,7 +238,9 @@ class FastFeatureDetector extends CvStruct { return VecKeyPoint.fromPointer(ret); } - static final finalizer = OcvFinalizer(CFFI.addresses.FastFeatureDetector_Close); + static final finalizer = OcvFinalizer( + CFFI.addresses.FastFeatureDetector_Close, + ); void dispose() { finalizer.detach(this); @@ -248,6 +261,8 @@ class GFTTDetector extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory GFTTDetector.fromPointer(cvg.GFTTDetectorPtr ptr, [bool attach = true]) => + GFTTDetector._(ptr, attach); /// returns a new GFTTDetector algorithm /// @@ -290,6 +305,7 @@ class KAZE extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory KAZE.fromPointer(cvg.KAZEPtr ptr, [bool attach = true]) => KAZE._(ptr, attach); /// returns a new KAZE algorithm /// @@ -318,7 +334,9 @@ class KAZE extends CvStruct { (VecKeyPoint, Mat) detectAndCompute(Mat src, Mat mask) { final desc = Mat.empty(); final ret = calloc(); - cvRun(() => CFFI.KAZE_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret)); + cvRun( + () => CFFI.KAZE_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret), + ); return (VecKeyPoint.fromPointer(ret), desc); } @@ -343,6 +361,7 @@ class MSER extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory MSER.fromPointer(cvg.MSERPtr ptr, [bool attach = true]) => MSER._(ptr, attach); /// returns a new MSER algorithm /// @@ -393,6 +412,7 @@ class ORB extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory ORB.fromPointer(cvg.ORBPtr ptr, [bool attach = true]) => ORB._(ptr, attach); /// returns a new ORB algorithm /// @@ -454,7 +474,9 @@ class ORB extends CvStruct { (VecKeyPoint, Mat) detectAndCompute(Mat src, Mat mask) { final desc = Mat.empty(); final ret = calloc(); - cvRun(() => CFFI.ORB_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret)); + cvRun( + () => CFFI.ORB_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret), + ); return (VecKeyPoint.fromPointer(ret), desc); } @@ -473,8 +495,10 @@ class ORB extends CvStruct { } class SimpleBlobDetectorParams extends CvStruct { - SimpleBlobDetectorParams._(ffi.Pointer ptr, [bool attach = true]) - : super.fromPointer(ptr) { + SimpleBlobDetectorParams._( + ffi.Pointer ptr, [ + bool attach = true, + ]) : super.fromPointer(ptr) { if (attach) { finalizer.attach(this, ptr.cast(), detach: this); } @@ -510,7 +534,9 @@ class SimpleBlobDetectorParams extends CvStruct { final p = calloc(); if (blobColor != null) p.ref.blobColor = blobColor; if (filterByArea != null) p.ref.filterByArea = filterByArea; - if (filterByCircularity != null) p.ref.filterByCircularity = filterByCircularity; + if (filterByCircularity != null) { + p.ref.filterByCircularity = filterByCircularity; + } if (filterByColor != null) p.ref.filterByColor = filterByColor; if (filterByConvexity != null) p.ref.filterByConvexity = filterByConvexity; if (filterByInertia != null) p.ref.filterByInertia = filterByInertia; @@ -522,7 +548,9 @@ class SimpleBlobDetectorParams extends CvStruct { if (minArea != null) p.ref.minArea = minArea; if (minCircularity != null) p.ref.minCircularity = minCircularity; if (minConvexity != null) p.ref.minConvexity = minConvexity; - if (minDistBetweenBlobs != null) p.ref.minDistBetweenBlobs = minDistBetweenBlobs; + if (minDistBetweenBlobs != null) { + p.ref.minDistBetweenBlobs = minDistBetweenBlobs; + } if (minInertiaRatio != null) p.ref.minInertiaRatio = minInertiaRatio; if (minRepeatability != null) p.ref.minRepeatability = minRepeatability; if (minThreshold != null) p.ref.minThreshold = minThreshold; @@ -691,6 +719,9 @@ class SimpleBlobDetector extends CvStruct { } } + factory SimpleBlobDetector.fromPointer(cvg.SimpleBlobDetectorPtr ptr, [bool attach = true]) => + SimpleBlobDetector._(ptr, attach); + /// returns a new SimpleBlobDetector algorithm /// /// For further details, please see: @@ -717,7 +748,9 @@ class SimpleBlobDetector extends CvStruct { return VecKeyPoint.fromPointer(ret); } - static final finalizer = OcvFinalizer(CFFI.addresses.SimpleBlobDetector_Close); + static final finalizer = OcvFinalizer( + CFFI.addresses.SimpleBlobDetector_Close, + ); void dispose() { finalizer.detach(this); @@ -738,6 +771,7 @@ class BFMatcher extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory BFMatcher.fromPointer(cvg.BFMatcherPtr ptr, [bool attach = true]) => BFMatcher._(ptr, attach); /// returns a new BFMatcher algorithm /// @@ -796,6 +830,8 @@ class FlannBasedMatcher extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory FlannBasedMatcher.fromPointer(cvg.FlannBasedMatcherPtr ptr, [bool attach = true]) => + FlannBasedMatcher._(ptr, attach); /// returns a new FlannBasedMatcher algorithm /// @@ -813,11 +849,15 @@ class FlannBasedMatcher extends CvStruct { /// https://docs.opencv.org/master/db/d39/classcv_1_1DescriptorMatcher.html#aa880f9353cdf185ccf3013e08210483a VecVecDMatch knnMatch(Mat query, Mat train, int k) { final ret = calloc(); - cvRun(() => CFFI.FlannBasedMatcher_KnnMatch(ptr.ref, query.ref, train.ref, k, ret)); + cvRun( + () => CFFI.FlannBasedMatcher_KnnMatch(ptr.ref, query.ref, train.ref, k, ret), + ); return VecVecDMatch.fromPointer(ret); } - static final finalizer = OcvFinalizer(CFFI.addresses.FlannBasedMatcher_Close); + static final finalizer = OcvFinalizer( + CFFI.addresses.FlannBasedMatcher_Close, + ); void dispose() { finalizer.detach(this); @@ -848,8 +888,22 @@ enum DrawMatchesFlag { final int value; } -void drawKeyPoints(Mat src, VecKeyPoint keypoints, Mat dst, Scalar color, DrawMatchesFlag flag) { - cvRun(() => CFFI.DrawKeyPoints(src.ref, keypoints.ref, dst.ref, color.ref, flag.value)); +void drawKeyPoints( + Mat src, + VecKeyPoint keypoints, + Mat dst, + Scalar color, + DrawMatchesFlag flag, +) { + cvRun( + () => CFFI.DrawKeyPoints( + src.ref, + keypoints.ref, + dst.ref, + color.ref, + flag.value, + ), + ); } /// SIFT is a wrapper around the cv::SIFT. @@ -859,6 +913,7 @@ class SIFT extends CvStruct { finalizer.attach(this, ptr.cast(), detach: this); } } + factory SIFT.fromPointer(cvg.SIFTPtr ptr, [bool attach = true]) => SIFT._(ptr, attach); /// returns a new SIFT algorithm /// @@ -887,7 +942,9 @@ class SIFT extends CvStruct { (VecKeyPoint, Mat) detectAndCompute(Mat src, Mat mask) { final desc = Mat.empty(); final ret = calloc(); - cvRun(() => CFFI.SIFT_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret)); + cvRun( + () => CFFI.SIFT_DetectAndCompute(ptr.ref, src.ref, mask.ref, desc.ref, ret), + ); return (VecKeyPoint.fromPointer(ret), desc); } @@ -905,10 +962,10 @@ class SIFT extends CvStruct { cvg.SIFT get ref => ptr.ref; } -// DrawMatches draws matches on combined train and querry images. -// -// For further details, please see: -// https://docs.opencv.org/master/d4/d5d/group__features2d__draw.html#gad8f463ccaf0dc6f61083abd8717c261a +/// DrawMatches draws matches on combined train and querry images. +/// +/// For further details, please see: +/// https://docs.opencv.org/master/d4/d5d/group__features2d__draw.html#gad8f463ccaf0dc6f61083abd8717c261a void drawMatches( InputArray img1, VecKeyPoint keypoints1, diff --git a/lib/src/objdetect/objdetect_async.dart b/lib/src/objdetect/objdetect_async.dart index 203e7ff8..f3978f34 100644 --- a/lib/src/objdetect/objdetect_async.dart +++ b/lib/src/objdetect/objdetect_async.dart @@ -16,8 +16,9 @@ import './objdetect.dart'; extension CascadeClassifierAsync on CascadeClassifier { static Future emptyNewAsync() async => cvRunAsync( - (callback) => CFFI.CascadeClassifier_New_Async(callback), - (c, p) => c.complete(CascadeClassifier.fromPointer(p.cast()))); + CFFI.CascadeClassifier_New_Async, + (c, p) => c.complete(CascadeClassifier.fromPointer(p.cast())), + ); static Future fromFileAsync(String filename) async { final cp = filename.toNativeUtf8().cast(); @@ -167,8 +168,9 @@ extension CascadeClassifierAsync on CascadeClassifier { extension HOGDescriptorAsync on HOGDescriptor { static Future emptyNewAsync() async => cvRunAsync( - (callback) => CFFI.HOGDescriptor_New_Async(callback), - (c, p) => c.complete(HOGDescriptor.fromPointer(p.cast()))); + CFFI.HOGDescriptor_New_Async, + (c, p) => c.complete(HOGDescriptor.fromPointer(p.cast())), + ); static Future fromFileAsync(String filename) async { final cp = filename.toNativeUtf8().cast(); @@ -391,8 +393,9 @@ Future groupRectanglesAsync( extension QRCodeDetectorAsync on QRCodeDetector { static Future emptyNewAsync() async => cvRunAsync( - (callback) => CFFI.QRCodeDetector_New_Async(callback), - (c, p) => c.complete(QRCodeDetector.fromPointer(p.cast()))); + CFFI.QRCodeDetector_New_Async, + (c, p) => c.complete(QRCodeDetector.fromPointer(p.cast())), + ); Future<(String rval, Mat straightQRcode)> decodeCurvedAsync( InputArray img, @@ -551,8 +554,9 @@ extension QRCodeDetectorAsync on QRCodeDetector { extension FaceDetectorYNAsync on FaceDetectorYN { static Future emptyNewAsync() async => cvRunAsync( - (callback) => CFFI.CascadeClassifier_New_Async(callback), - (c, p) => c.complete(CascadeClassifier.fromPointer(p.cast()))); + CFFI.CascadeClassifier_New_Async, + (c, p) => c.complete(CascadeClassifier.fromPointer(p.cast())), + ); static Future fromFileAsync( String model, @@ -567,8 +571,17 @@ extension FaceDetectorYNAsync on FaceDetectorYN { final cModel = model.toNativeUtf8().cast(); final cConfig = config.toNativeUtf8().cast(); final rval = await cvRunAsync( - (callback) => CFFI.FaceDetectorYN_New_Async(cModel, cConfig, inputSize.cvd.ref, scoreThreshold, - nmsThreshold, topK, backendId, targetId, callback), (c, p) { + (callback) => CFFI.FaceDetectorYN_New_Async( + cModel, + cConfig, + inputSize.cvd.ref, + scoreThreshold, + nmsThreshold, + topK, + backendId, + targetId, + callback, + ), (c, p) { return c.complete(FaceDetectorYN.fromPointer(p.cast())); }); calloc.free(cModel); @@ -591,16 +604,17 @@ extension FaceDetectorYNAsync on FaceDetectorYN { final rval = await cvRunAsync( (callback) => CFFI.FaceDetectorYN_NewFromBuffer_Async( - cFramework, - VecUChar.fromList(bufferModel).ref, - VecUChar.fromList(bufferConfig).ref, - inputSize.cvd.ref, - scoreThreshold, - nmsThreshold, - topK, - backendId, - targetId, - callback), (c, p) { + cFramework, + VecUChar.fromList(bufferModel).ref, + VecUChar.fromList(bufferConfig).ref, + inputSize.cvd.ref, + scoreThreshold, + nmsThreshold, + topK, + backendId, + targetId, + callback, + ), (c, p) { return c.complete(FaceDetectorYN.fromPointer(p.cast())); }); calloc.free(cFramework); diff --git a/src/features2d/features2d.cpp b/src/features2d/features2d.cpp index 769021fe..d1ce63fb 100644 --- a/src/features2d/features2d.cpp +++ b/src/features2d/features2d.cpp @@ -7,6 +7,7 @@ */ #include "features2d.h" +#include "utils.hpp" CvStatus *AKAZE_Create(AKAZE *rval) { @@ -227,60 +228,6 @@ CvStatus *ORB_DetectAndCompute(ORB o, Mat src, Mat mask, Mat desc, VecKeyPoint * END_WRAP } -cv::SimpleBlobDetector::Params ConvertCParamsToCPPParams(SimpleBlobDetectorParams params) -{ - cv::SimpleBlobDetector::Params converted; - - converted.blobColor = params.blobColor; - converted.filterByArea = params.filterByArea; - converted.filterByCircularity = params.filterByCircularity; - converted.filterByColor = params.filterByColor; - converted.filterByConvexity = params.filterByConvexity; - converted.filterByInertia = params.filterByInertia; - converted.maxArea = params.maxArea; - converted.maxCircularity = params.maxCircularity; - converted.maxConvexity = params.maxConvexity; - converted.maxInertiaRatio = params.maxInertiaRatio; - converted.maxThreshold = params.maxThreshold; - converted.minArea = params.minArea; - converted.minCircularity = params.minCircularity; - converted.minConvexity = params.minConvexity; - converted.minDistBetweenBlobs = params.minDistBetweenBlobs; - converted.minInertiaRatio = params.minInertiaRatio; - converted.minRepeatability = params.minRepeatability; - converted.minThreshold = params.minThreshold; - converted.thresholdStep = params.thresholdStep; - - return converted; -} - -SimpleBlobDetectorParams ConvertCPPParamsToCParams(cv::SimpleBlobDetector::Params params) -{ - SimpleBlobDetectorParams converted; - - converted.blobColor = params.blobColor; - converted.filterByArea = params.filterByArea; - converted.filterByCircularity = params.filterByCircularity; - converted.filterByColor = params.filterByColor; - converted.filterByConvexity = params.filterByConvexity; - converted.filterByInertia = params.filterByInertia; - converted.maxArea = params.maxArea; - converted.maxCircularity = params.maxCircularity; - converted.maxConvexity = params.maxConvexity; - converted.maxInertiaRatio = params.maxInertiaRatio; - converted.maxThreshold = params.maxThreshold; - converted.minArea = params.minArea; - converted.minCircularity = params.minCircularity; - converted.minConvexity = params.minConvexity; - converted.minDistBetweenBlobs = params.minDistBetweenBlobs; - converted.minInertiaRatio = params.minInertiaRatio; - converted.minRepeatability = params.minRepeatability; - converted.minThreshold = params.minThreshold; - converted.thresholdStep = params.thresholdStep; - - return converted; -} - CvStatus *SimpleBlobDetector_Create(SimpleBlobDetector *rval) { BEGIN_WRAP diff --git a/src/features2d/utils.hpp b/src/features2d/utils.hpp new file mode 100644 index 00000000..6110cfeb --- /dev/null +++ b/src/features2d/utils.hpp @@ -0,0 +1,61 @@ +#ifndef CVD_FEATURES2D_UTILS_H +#define CVD_FEATURES2D_UTILS_H + +#include "features2d/features2d.h" +#include + +inline cv::SimpleBlobDetector::Params ConvertCParamsToCPPParams(SimpleBlobDetectorParams params) +{ + cv::SimpleBlobDetector::Params converted; + + converted.blobColor = params.blobColor; + converted.filterByArea = params.filterByArea; + converted.filterByCircularity = params.filterByCircularity; + converted.filterByColor = params.filterByColor; + converted.filterByConvexity = params.filterByConvexity; + converted.filterByInertia = params.filterByInertia; + converted.maxArea = params.maxArea; + converted.maxCircularity = params.maxCircularity; + converted.maxConvexity = params.maxConvexity; + converted.maxInertiaRatio = params.maxInertiaRatio; + converted.maxThreshold = params.maxThreshold; + converted.minArea = params.minArea; + converted.minCircularity = params.minCircularity; + converted.minConvexity = params.minConvexity; + converted.minDistBetweenBlobs = params.minDistBetweenBlobs; + converted.minInertiaRatio = params.minInertiaRatio; + converted.minRepeatability = params.minRepeatability; + converted.minThreshold = params.minThreshold; + converted.thresholdStep = params.thresholdStep; + + return converted; +} + +inline SimpleBlobDetectorParams ConvertCPPParamsToCParams(cv::SimpleBlobDetector::Params params) +{ + SimpleBlobDetectorParams converted; + + converted.blobColor = params.blobColor; + converted.filterByArea = params.filterByArea; + converted.filterByCircularity = params.filterByCircularity; + converted.filterByColor = params.filterByColor; + converted.filterByConvexity = params.filterByConvexity; + converted.filterByInertia = params.filterByInertia; + converted.maxArea = params.maxArea; + converted.maxCircularity = params.maxCircularity; + converted.maxConvexity = params.maxConvexity; + converted.maxInertiaRatio = params.maxInertiaRatio; + converted.maxThreshold = params.maxThreshold; + converted.minArea = params.minArea; + converted.minCircularity = params.minCircularity; + converted.minConvexity = params.minConvexity; + converted.minDistBetweenBlobs = params.minDistBetweenBlobs; + converted.minInertiaRatio = params.minInertiaRatio; + converted.minRepeatability = params.minRepeatability; + converted.minThreshold = params.minThreshold; + converted.thresholdStep = params.thresholdStep; + + return converted; +} + +#endif // CVD_FEATURES2D_UTILS_H diff --git a/test/features2d/features2d_async_test.dart b/test/features2d/features2d_async_test.dart new file mode 100644 index 00000000..54bb750a --- /dev/null +++ b/test/features2d/features2d_async_test.dart @@ -0,0 +1,356 @@ +import 'package:opencv_dart/opencv_dart.dart' as cv; +import 'package:test/test.dart'; + +void main() async { + test('cv.AKAZEAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final ak = await cv.AKAZEAsync.emptyAsync(); + final kp = await ak.detectAsync(img); + expect(kp.length, greaterThan(512)); + + final mask = cv.Mat.empty(); + final (kp2, desc) = await ak.detectAndComputeAsync(img, mask); + expect(kp2.length, greaterThan(512)); + expect(desc.isEmpty, false); + + ak.dispose(); + }); + + test('cv.AgastFeatureDetectorAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final ad = await cv.AgastFeatureDetectorAsync.emptyAsync(); + final kp = await ad.detectAsync(img); + expect(kp.length, greaterThan(2800)); + + ad.dispose(); + }); + + test('cv.BRISKAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final br = await cv.BRISKAsync.emptyAsync(); + final kp = await br.detectAsync(img); + expect(kp.length, greaterThan(512)); + + final mask = cv.Mat.empty(); + final (kp2, desc) = await br.detectAndComputeAsync(img, mask); + expect(kp2.length, greaterThan(512)); + expect(desc.isEmpty, false); + + br.dispose(); + }); + + test('cv.FastFeatureDetectorAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final fd = await cv.FastFeatureDetectorAsync.emptyAsync(); + final kp = await fd.detectAsync(img); + expect(kp.length, greaterThan(2690)); + + final fd1 = await cv.FastFeatureDetectorAsync.createAsync(); + final kp1 = await fd1.detectAsync(img); + expect(kp1.length, greaterThan(2690)); + + fd.dispose(); + }); + + test('cv.GFTTDetectorAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final gf = await cv.GFTTDetectorAsync.emptyAsync(); + final kp = await gf.detectAsync(img); + expect(kp.length, greaterThan(512)); + + gf.dispose(); + }); + + test('cv.KAZEAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final ka = await cv.KAZEAsync.emptyAsync(); + final kp = await ka.detectAsync(img); + expect(kp.length, greaterThan(0)); + + final mask = cv.Mat.empty(); + final (kp2, desc) = await ka.detectAndComputeAsync(img, mask); + expect(kp2.length, greaterThan(0)); + expect(desc.isEmpty, false); + + ka.dispose(); + }); + + test('cv.MSERAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final gf = await cv.MSERAsync.emptyAsync(); + final kp = await gf.detectAsync(img); + expect(kp.length, greaterThan(0)); + + gf.dispose(); + }); + + test('cv.ORBAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final ka = await cv.ORBAsync.emptyAsync(); + final kp = await ka.detectAsync(img); + expect(kp.length, 500); + + final orb = await cv.ORBAsync.createAsync(); + final kp1 = await orb.detectAsync(img); + expect(kp1.length, 500); + + final mask = cv.Mat.empty(); + final (kp2, desc) = await ka.detectAndComputeAsync(img, mask); + expect(kp2.length, 500); + expect(desc.isEmpty, false); + + orb.dispose(); + }); + + test('cv.SimpleBlobDetectorAsync', () async { + final img = await cv.imreadAsync("test/images/lenna.png", flags: cv.IMREAD_COLOR); + expect(img.isEmpty, false); + + final detector = await cv.SimpleBlobDetectorAsync.emptyAsync(); + final kp = await detector.detectAsync(img); + expect(kp.length, 1); + + final params = cv.SimpleBlobDetectorParams( + blobColor: 200, + filterByArea: false, + filterByCircularity: true, + filterByConvexity: false, + filterByInertia: false, + filterByColor: false, + maxArea: 1000, + maxInertiaRatio: 0.97, + maxThreshold: 241, + maxCircularity: 0.99, + maxConvexity: 0.98, + minArea: 230, + minCircularity: 0.9, + minConvexity: 0.89, + minDistBetweenBlobs: 15.5, + minInertiaRatio: 0.8, + minRepeatability: 5, + minThreshold: 200, + thresholdStep: 2.0, + ); + + final params1 = cv.SimpleBlobDetectorParams.fromNative(params.ref); + expect(params1, params); + + expect(params.blobColor, 200); + params.blobColor = 201; + final blobColor = params.blobColor; + expect(blobColor, 201); + + expect(params.filterByArea, false); + params.filterByArea = true; + final filterByArea = params.filterByArea; + expect(filterByArea, true); + + expect(params.filterByCircularity, true); + params.filterByCircularity = false; + final filterByCircularity = params.filterByCircularity; + expect(filterByCircularity, false); + + expect(params.filterByColor, false); + params.filterByColor = true; + final filterByColor = params.filterByColor; + expect(filterByColor, true); + + expect(params.filterByConvexity, false); + params.filterByConvexity = true; + final filterByConvexity = params.filterByConvexity; + expect(filterByConvexity, true); + + expect(params.filterByInertia, false); + params.filterByInertia = true; + final filterByInertia = params.filterByInertia; + expect(filterByInertia, true); + + expect(params.maxArea, 1000); + params.maxArea = 2000; + final maxArea = params.maxArea; + expect(maxArea, 2000); + + expect(params.maxCircularity, closeTo(0.99, 1e-4)); + params.maxCircularity = 0.98; + final maxCircularity = params.maxCircularity; + expect(maxCircularity, closeTo(0.98, 1e-4)); + + expect(params.maxConvexity, closeTo(0.98, 1e-4)); + params.maxConvexity = 0.99; + final maxConvexity = params.maxConvexity; + expect(maxConvexity, closeTo(0.99, 1e-4)); + + expect(params.maxInertiaRatio, closeTo(0.97, 1e-4)); + params.maxInertiaRatio = 0.99; + final maxInertiaRatio = params.maxInertiaRatio; + expect(maxInertiaRatio, closeTo(0.99, 1e-4)); + + expect(params.maxThreshold, 241); + params.maxThreshold = 255; + final maxThreshold = params.maxThreshold; + expect(maxThreshold, 255); + + expect(params.minArea, 230); + params.minArea = 10; + final minArea = params.minArea; + expect(minArea, 10); + + expect(params.minCircularity, closeTo(0.9, 1e-4)); + params.minCircularity = 0.8; + final minCircularity = params.minCircularity; + expect(minCircularity, closeTo(0.8, 1e-4)); + + expect(params.minConvexity, closeTo(0.89, 1e-4)); + params.minConvexity = 0.8; + final minConvexity = params.minConvexity; + expect(minConvexity, closeTo(0.8, 1e-4)); + + expect(params.minDistBetweenBlobs, closeTo(15.5, 1e-4)); + params.minDistBetweenBlobs = 10; + final minDistBetweenBlobs = params.minDistBetweenBlobs; + expect(minDistBetweenBlobs, closeTo(10, 1e-4)); + + expect(params.minInertiaRatio, closeTo(0.8, 1e-4)); + params.minInertiaRatio = 0.7; + final minInertiaRatio = params.minInertiaRatio; + expect(minInertiaRatio, closeTo(0.7, 1e-4)); + + expect(params.minRepeatability, 5); + params.minRepeatability = 10; + final minRepeatability = params.minRepeatability; + expect(minRepeatability, 10); + + expect(params.minThreshold, 200); + params.minThreshold = 100; + final minThreshold = params.minThreshold; + expect(minThreshold, 100); + + expect(params.thresholdStep, closeTo(2.0, 1e-4)); + params.thresholdStep = 1.0; + final thresholdStep = params.thresholdStep; + expect(thresholdStep, closeTo(1.0, 1e-4)); + + final detector1 = await cv.SimpleBlobDetectorAsync.createAsync(params); + final kp1 = await detector1.detectAsync(img); + expect(kp1.length, 0); + + detector1.dispose(); + params.dispose(); + }); + + test('cv.BFMatcherAsync', () async { + final desc1 = await cv.imreadAsync( + "test/images/sift_descriptor.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(desc1.isEmpty, false); + final desc2 = await cv.imreadAsync( + "test/images/sift_descriptor.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(desc2.isEmpty, false); + + final matcher = await cv.BFMatcherAsync.emptyAsync(); + final dmatches = await matcher.knnMatchAsync(desc1, desc2, 2); + expect(dmatches.length, greaterThan(0)); + + final matcher1 = await cv.BFMatcherAsync.createAsync(); + final dmatches1 = await matcher1.knnMatchAsync(desc1, desc2, 2); + expect(dmatches1.length, greaterThan(0)); + + final matches = await matcher.matchAsync(desc1, desc2); + expect(matches.length, greaterThan(0)); + + matcher.dispose(); + }); + + test('cv.FlannBasedMatcherAsync', () async { + final desc1 = await cv.imreadAsync( + "test/images/sift_descriptor.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(desc1.isEmpty, false); + final desc2 = await cv.imreadAsync( + "test/images/sift_descriptor.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(desc2.isEmpty, false); + + final desc11 = desc1.convertTo(cv.MatType.CV_32FC1); + final desc21 = desc2.convertTo(cv.MatType.CV_32FC1); + + final matcher = await cv.FlannBasedMatcherAsync.emptyAsync(); + final dmatches = await matcher.knnMatchAsync(desc11, desc21, 2); + expect(dmatches.length, greaterThan(0)); + + matcher.dispose(); + }); + + test('cv.SIFTAsync', () async { + final img = await cv.imreadAsync( + "test/images/lenna.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(img.isEmpty, false); + + final si = await cv.SIFTAsync.emptyAsync(); + final kp = await si.detectAsync(img); + expect(kp.length, greaterThan(0)); + + final mask = cv.Mat.empty(); + final (kp2, desc) = await si.detectAndComputeAsync(img, mask); + expect(kp2.length, greaterThan(0)); + expect(desc.isEmpty, false); + + si.dispose(); + }); + + test('cv.drawMatchesAsync', () async { + final query = await cv.imreadAsync("test/images/box.png", flags: cv.IMREAD_GRAYSCALE); + final train = await cv.imreadAsync( + "test/images/box_in_scene.png", + flags: cv.IMREAD_GRAYSCALE, + ); + expect(query.isEmpty, false); + expect(train.isEmpty, false); + + final m1 = cv.Mat.empty(), m2 = cv.Mat.empty(); + final (kp1, des1) = await (await cv.SIFTAsync.emptyAsync()).detectAndComputeAsync(query, m1); + final (kp2, des2) = await (await cv.SIFTAsync.emptyAsync()).detectAndComputeAsync(train, m2); + + final bf = await cv.BFMatcherAsync.emptyAsync(); + final dmatches = await bf.knnMatchAsync(des1, des2, 2); + expect(dmatches.length, greaterThan(0)); + + final out = cv.Mat.empty(); + await cv.drawMatchesAsync( + query, + kp1, + train, + kp2, + dmatches.first, + out, + matchColor: cv.Scalar.red, + singlePointColor: cv.Scalar.green, + ); + expect(out.cols, query.cols + train.cols); + + bf.dispose(); + }); +} diff --git a/test/features2d_test.dart b/test/features2d/features2d_test.dart similarity index 100% rename from test/features2d_test.dart rename to test/features2d/features2d_test.dart