From ca77b8f69c728494b8399327a8b0924b69817455 Mon Sep 17 00:00:00 2001 From: Peri Telemachou Date: Tue, 24 Oct 2023 22:32:05 +1100 Subject: [PATCH] Add separate "Compute" bindings for detection algorithms (#1117) features2d, contrib/xfeatures2d: Implement Compute bindings for AKAZE, BRISK, KAZE, ORB, SIFT and SURF --- contrib/xfeatures2d.cpp | 24 +++++++ contrib/xfeatures2d.go | 25 +++++++ contrib/xfeatures2d.h | 1 + contrib/xfeatures2d_test.go | 34 ++++++--- features2d.cpp | 120 ++++++++++++++++++++++++++++++++ features2d.go | 135 ++++++++++++++++++++++++++++++++++++ features2d.h | 5 ++ features2d_test.go | 82 ++++++++++++++++------ 8 files changed, 397 insertions(+), 29 deletions(-) diff --git a/contrib/xfeatures2d.cpp b/contrib/xfeatures2d.cpp index acc8eb96..0fb7f4dd 100644 --- a/contrib/xfeatures2d.cpp +++ b/contrib/xfeatures2d.cpp @@ -30,6 +30,30 @@ struct KeyPoints SURF_Detect(SURF d, Mat src) { return ret; } +struct KeyPoints SURF_Compute(SURF d, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*d)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints SURF_DetectAndCompute(SURF d, Mat src, Mat mask, Mat desc) { std::vector detected; (*d)->detectAndCompute(*src, *mask, detected, *desc); diff --git a/contrib/xfeatures2d.go b/contrib/xfeatures2d.go index 79ce4173..2d2d5889 100644 --- a/contrib/xfeatures2d.go +++ b/contrib/xfeatures2d.go @@ -54,6 +54,31 @@ func (d *SURF) Detect(src gocv.Mat) []gocv.KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using SURF. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (d *SURF) Compute(src gocv.Mat, mask gocv.Mat, kps []gocv.KeyPoint) ([]gocv.KeyPoint, gocv.Mat) { + desc := gocv.NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + ret := C.SURF_Compute((C.SURF)(d.p), C.Mat(src.Ptr()), cKeyPoints, C.Mat(desc.Ptr())) + + return getKeyPoints(ret), desc +} + // DetectAndCompute detects and computes keypoints in an image using SURF. // // For further details, please see: diff --git a/contrib/xfeatures2d.h b/contrib/xfeatures2d.h index 62e81586..177d354e 100644 --- a/contrib/xfeatures2d.h +++ b/contrib/xfeatures2d.h @@ -21,6 +21,7 @@ SURF SURF_Create(); SURF SURF_CreateWithParams(double hessianThreshold, int nOctaves, int nOctaveLayers, bool extended, bool upright); void SURF_Close(SURF f); struct KeyPoints SURF_Detect(SURF f, Mat src); +struct KeyPoints SURF_Compute(SURF f, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints SURF_DetectAndCompute(SURF f, Mat src, Mat mask, Mat desc); BriefDescriptorExtractor BriefDescriptorExtractor_Create(); BriefDescriptorExtractor BriefDescriptorExtractor_CreateWithParams(int bytes, bool useOrientation); diff --git a/contrib/xfeatures2d_test.go b/contrib/xfeatures2d_test.go index 18aeef87..3486af3f 100644 --- a/contrib/xfeatures2d_test.go +++ b/contrib/xfeatures2d_test.go @@ -33,12 +33,21 @@ func TestSURF(t *testing.T) { mask := gocv.NewMat() defer mask.Close() - kp2, desc := si.DetectAndCompute(img, mask) - if len(kp2) == 512 { - t.Errorf("Invalid KeyPoint array in SURF DetectAndCompute: %d", len(kp2)) + kpc, desc := si.Compute(img, mask, kp) + defer desc.Close() + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in SURF Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in SURF Compute") + } + + kpdc, desc2 := si.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in SURF DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in SURF DetectAndCompute") } } @@ -69,12 +78,21 @@ func TestSURFWithParams(t *testing.T) { mask := gocv.NewMat() defer mask.Close() - kp2, desc := si.DetectAndCompute(img, mask) - if len(kp2) == 512 { - t.Errorf("Invalid KeyPoint array in SURF DetectAndCompute: %d", len(kp2)) + kpc, desc := si.Compute(img, mask, kp) + defer desc.Close() + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in SURF Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in SURF Compute") + } + + kpdc, desc2 := si.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in SURF DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in SURF DetectAndCompute") } } diff --git a/features2d.cpp b/features2d.cpp index 0ccce5f8..e27bd1d3 100644 --- a/features2d.cpp +++ b/features2d.cpp @@ -26,6 +26,30 @@ struct KeyPoints AKAZE_Detect(AKAZE a, Mat src) { return ret; } +struct KeyPoints AKAZE_Compute(AKAZE a, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*a)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints AKAZE_DetectAndCompute(AKAZE a, Mat src, Mat mask, Mat desc) { std::vector detected; (*a)->detectAndCompute(*src, *mask, detected, *desc); @@ -95,6 +119,30 @@ struct KeyPoints BRISK_Detect(BRISK b, Mat src) { return ret; } +struct KeyPoints BRISK_Compute(BRISK b, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*b)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints BRISK_DetectAndCompute(BRISK b, Mat src, Mat mask, Mat desc) { std::vector detected; (*b)->detectAndCompute(*src, *mask, detected, *desc); @@ -164,6 +212,30 @@ struct KeyPoints KAZE_Detect(KAZE a, Mat src) { return ret; } +struct KeyPoints KAZE_Compute(KAZE a, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*a)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints KAZE_DetectAndCompute(KAZE a, Mat src, Mat mask, Mat desc) { std::vector detected; (*a)->detectAndCompute(*src, *mask, detected, *desc); @@ -265,6 +337,30 @@ struct KeyPoints ORB_Detect(ORB o, Mat src) { return ret; } +struct KeyPoints ORB_Compute(ORB o, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*o)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints ORB_DetectAndCompute(ORB o, Mat src, Mat mask, Mat desc) { std::vector detected; (*o)->detectAndCompute(*src, *mask, detected, *desc); @@ -515,6 +611,30 @@ struct KeyPoints SIFT_Detect(SIFT d, Mat src) { return ret; } +struct KeyPoints SIFT_Compute(SIFT d, Mat src, struct KeyPoints kp, Mat desc) { + std::vector computed; + for (size_t i = 0; i < kp.length; i++) { + cv::KeyPoint k = cv::KeyPoint(kp.keypoints[i].x, kp.keypoints[i].y, + kp.keypoints[i].size, kp.keypoints[i].angle, kp.keypoints[i].response, + kp.keypoints[i].octave, kp.keypoints[i].classID); + computed.push_back(k); + } + + (*d)->compute(*src, computed, *desc); + + KeyPoint* kps = new KeyPoint[computed.size()]; + + for (size_t i = 0; i < computed.size(); ++i) { + KeyPoint k = {computed[i].pt.x, computed[i].pt.y, computed[i].size, computed[i].angle, + computed[i].response, computed[i].octave, computed[i].class_id + }; + kps[i] = k; + } + + KeyPoints ret = {kps, (int)computed.size()}; + return ret; +} + struct KeyPoints SIFT_DetectAndCompute(SIFT d, Mat src, Mat mask, Mat desc) { std::vector detected; (*d)->detectAndCompute(*src, *mask, detected, *desc); diff --git a/features2d.go b/features2d.go index f47e088a..2f33400a 100644 --- a/features2d.go +++ b/features2d.go @@ -43,6 +43,33 @@ func (a *AKAZE) Detect(src Mat) []KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using AKAZE. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (a *AKAZE) Compute(src Mat, mask Mat, kps []KeyPoint) ([]KeyPoint, Mat) { + desc := NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + + ret := C.AKAZE_Compute((C.AKAZE)(a.p), src.p, cKeyPoints, desc.p) + defer C.KeyPoints_Close(ret) + + return getKeyPoints(ret), desc +} + // DetectAndCompute keypoints and compute in an image using AKAZE. // // For further details, please see: @@ -119,6 +146,33 @@ func (b *BRISK) Detect(src Mat) []KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using BRISK. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (b *BRISK) Compute(src Mat, mask Mat, kps []KeyPoint) ([]KeyPoint, Mat) { + desc := NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + + ret := C.BRISK_Compute((C.BRISK)(b.p), src.p, cKeyPoints, desc.p) + defer C.KeyPoints_Close(ret) + + return getKeyPoints(ret), desc +} + // DetectAndCompute keypoints and compute in an image using BRISK. // // For further details, please see: @@ -250,6 +304,33 @@ func (a *KAZE) Detect(src Mat) []KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using KAZE. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (a *KAZE) Compute(src Mat, mask Mat, kps []KeyPoint) ([]KeyPoint, Mat) { + desc := NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + + ret := C.KAZE_Compute((C.KAZE)(a.p), src.p, cKeyPoints, desc.p) + defer C.KeyPoints_Close(ret) + + return getKeyPoints(ret), desc +} + // DetectAndCompute keypoints and compute in an image using KAZE. // // For further details, please see: @@ -351,6 +432,33 @@ func (o *ORB) Detect(src Mat) []KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using ORB. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (o *ORB) Compute(src Mat, mask Mat, kps []KeyPoint) ([]KeyPoint, Mat) { + desc := NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + + ret := C.ORB_Compute((C.ORB)(o.p), src.p, cKeyPoints, desc.p) + defer C.KeyPoints_Close(ret) + + return getKeyPoints(ret), desc +} + // DetectAndCompute detects keypoints and computes from an image using ORB. // // For further details, please see: @@ -823,6 +931,33 @@ func (d *SIFT) Detect(src Mat) []KeyPoint { return getKeyPoints(ret) } +// Compute keypoints in an image using SIFT. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d0/d13/classcv_1_1Feature2D.html#ab3cce8d56f4fc5e1d530b5931e1e8dc0 +func (d *SIFT) Compute(src Mat, mask Mat, kps []KeyPoint) ([]KeyPoint, Mat) { + desc := NewMat() + kp2arr := make([]C.struct_KeyPoint, len(kps)) + for i, kp := range kps { + kp2arr[i].x = C.double(kp.X) + kp2arr[i].y = C.double(kp.Y) + kp2arr[i].size = C.double(kp.Size) + kp2arr[i].angle = C.double(kp.Angle) + kp2arr[i].response = C.double(kp.Response) + kp2arr[i].octave = C.int(kp.Octave) + kp2arr[i].classID = C.int(kp.ClassID) + } + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&kp2arr[0]), + length: (C.int)(len(kps)), + } + + ret := C.SIFT_Compute((C.SIFT)(d.p), src.p, cKeyPoints, desc.p) + defer C.KeyPoints_Close(ret) + + return getKeyPoints(ret), desc +} + // DetectAndCompute detects and computes keypoints in an image using SIFT. // // For further details, please see: diff --git a/features2d.h b/features2d.h index 4042a0e3..c941f505 100644 --- a/features2d.h +++ b/features2d.h @@ -39,6 +39,7 @@ typedef void* SIFT; AKAZE AKAZE_Create(); void AKAZE_Close(AKAZE a); struct KeyPoints AKAZE_Detect(AKAZE a, Mat src); +struct KeyPoints AKAZE_Compute(AKAZE a, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints AKAZE_DetectAndCompute(AKAZE a, Mat src, Mat mask, Mat desc); AgastFeatureDetector AgastFeatureDetector_Create(); @@ -48,6 +49,7 @@ struct KeyPoints AgastFeatureDetector_Detect(AgastFeatureDetector a, Mat src); BRISK BRISK_Create(); void BRISK_Close(BRISK b); struct KeyPoints BRISK_Detect(BRISK b, Mat src); +struct KeyPoints BRISK_Compute(BRISK b, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints BRISK_DetectAndCompute(BRISK b, Mat src, Mat mask, Mat desc); FastFeatureDetector FastFeatureDetector_Create(); @@ -62,6 +64,7 @@ struct KeyPoints GFTTDetector_Detect(GFTTDetector a, Mat src); KAZE KAZE_Create(); void KAZE_Close(KAZE a); struct KeyPoints KAZE_Detect(KAZE a, Mat src); +struct KeyPoints KAZE_Compute(KAZE a, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints KAZE_DetectAndCompute(KAZE a, Mat src, Mat mask, Mat desc); MSER MSER_Create(); @@ -72,6 +75,7 @@ ORB ORB_Create(); ORB ORB_CreateWithParams(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize, int fastThreshold); void ORB_Close(ORB o); struct KeyPoints ORB_Detect(ORB o, Mat src); +struct KeyPoints ORB_Compute(ORB o, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints ORB_DetectAndCompute(ORB o, Mat src, Mat mask, Mat desc); SimpleBlobDetector SimpleBlobDetector_Create(); @@ -95,6 +99,7 @@ void DrawKeyPoints(Mat src, struct KeyPoints kp, Mat dst, const Scalar s, int fl SIFT SIFT_Create(); void SIFT_Close(SIFT f); struct KeyPoints SIFT_Detect(SIFT f, Mat src); +struct KeyPoints SIFT_Compute(SIFT f, Mat src, struct KeyPoints kp, Mat desc); struct KeyPoints SIFT_DetectAndCompute(SIFT f, Mat src, Mat mask, Mat desc); void DrawMatches(Mat img1, struct KeyPoints kp1, Mat img2, struct KeyPoints kp2, struct DMatches matches1to2, Mat outImg, const Scalar matchesColor, const Scalar pointColor, struct ByteArray matchesMask, int flags); diff --git a/features2d_test.go b/features2d_test.go index cc8e8d69..9b07e9fe 100644 --- a/features2d_test.go +++ b/features2d_test.go @@ -26,13 +26,21 @@ func TestAKAZE(t *testing.T) { mask := NewMat() defer mask.Close() - kp2, desc := ak.DetectAndCompute(img, mask) + kpc, desc := ak.Compute(img, mask, kp) defer desc.Close() - if len(kp2) < 512 { - t.Errorf("Invalid KeyPoint array in AKAZE DetectAndCompute: %d", len(kp2)) + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in AKAZE Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in AKAZE Compute") + } + + kpdc, desc2 := ak.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in AKAZE DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in AKAZE DetectAndCompute") } } @@ -77,14 +85,22 @@ func TestBRISK(t *testing.T) { mask := NewMat() defer mask.Close() - kp2, desc := br.DetectAndCompute(img, mask) + kpc, desc := br.Compute(img, mask, kp) defer desc.Close() - if len(kp2) != 1105 { - t.Errorf("Invalid KeyPoint array in BRISK DetectAndCompute: %d", len(kp2)) + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in BRISK Compute: %d", len(kpc)) } - if desc.Empty() { - t.Error("Invalid Mat desc in AKAZE DetectAndCompute") + t.Error("Invalid Mat desc in BRISK Compute") + } + + kpdc, desc2 := br.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in BRISK DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { + t.Error("Invalid Mat desc in BRISK DetectAndCompute") } } @@ -166,13 +182,21 @@ func TestKAZE(t *testing.T) { mask := NewMat() defer mask.Close() - kp2, desc := k.DetectAndCompute(img, mask) + kpc, desc := k.Compute(img, mask, kp) defer desc.Close() - if len(kp2) < 512 { - t.Errorf("Invalid KeyPoint array in KAZE DetectAndCompute: %d", len(kp2)) + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in KAZE Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in KAZE Compute") + } + + kpdc, desc2 := k.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in KAZE DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in KAZE DetectAndCompute") } } @@ -217,13 +241,21 @@ func TestORB(t *testing.T) { mask := NewMat() defer mask.Close() - kp2, desc := od.DetectAndCompute(img, mask) + kpc, desc := od.Compute(img, mask, kp) defer desc.Close() - if len(kp2) != 500 { - t.Errorf("Invalid KeyPoint array in ORB DetectAndCompute: %d", len(kp2)) + if len(kpc) < 500 { + t.Errorf("Invalid KeyPoint array in ORB Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in ORB Compute") + } + + kpdc, desc2 := od.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 500 { + t.Errorf("Invalid KeyPoint array in ORB DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in ORB DetectAndCompute") } } @@ -581,13 +613,21 @@ func TestSIFT(t *testing.T) { mask := NewMat() defer mask.Close() - kp2, desc := si.DetectAndCompute(img, mask) + kpc, desc := si.Compute(img, mask, kp) defer desc.Close() - if len(kp2) == 512 { - t.Errorf("Invalid KeyPoint array in SIFT DetectAndCompute: %d", len(kp2)) + if len(kpc) < 512 { + t.Errorf("Invalid KeyPoint array in SIFT Compute: %d", len(kpc)) } - if desc.Empty() { + t.Error("Invalid Mat desc in SIFT Compute") + } + + kpdc, desc2 := si.DetectAndCompute(img, mask) + defer desc2.Close() + if len(kpdc) < 512 { + t.Errorf("Invalid KeyPoint array in SIFT DetectAndCompute: %d", len(kpdc)) + } + if desc2.Empty() { t.Error("Invalid Mat desc in SIFT DetectAndCompute") } }