From 95d643cf0cf761f77bdbf8b13212211d47be6300 Mon Sep 17 00:00:00 2001 From: John Brandt Date: Sun, 14 Jan 2024 14:26:24 -0700 Subject: [PATCH] add beblid descriptor extractor --- contrib/xfeatures2d.cpp | 23 ++++++++++++++++ contrib/xfeatures2d.go | 55 +++++++++++++++++++++++++++++++++++++ contrib/xfeatures2d.h | 6 ++++ contrib/xfeatures2d_test.go | 30 ++++++++++++++++++++ 4 files changed, 114 insertions(+) diff --git a/contrib/xfeatures2d.cpp b/contrib/xfeatures2d.cpp index d1f3c179..fdf46759 100644 --- a/contrib/xfeatures2d.cpp +++ b/contrib/xfeatures2d.cpp @@ -43,3 +43,26 @@ struct KeyPoints SURF_DetectAndCompute(SURF d, Mat src, Mat mask, Mat desc) { KeyPoints ret = {kps, (int)detected.size()}; return ret; } + +BeblidDescriptorExtractor BeblidDescriptorExtractor_Create(float scaleFactor, int size) { + return new cv::Ptr(cv::xfeatures2d::BEBLID::create(scaleFactor, size)); +} + +void BeblidDescriptorExtractor_Close(BeblidDescriptorExtractor b) { + delete b; +} + +void BeblidDescriptorExtractor_Compute(BeblidDescriptorExtractor b, Mat src, struct KeyPoints kp, Mat desc) { + std::vector keypts; + keypts.reserve(kp.length); + cv::KeyPoint keypt; + + for (int i = 0; i < kp.length; ++i) { + keypt = 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); + keypts.push_back(keypt); + } + + (*b)->compute(*src, keypts, *desc); +} \ No newline at end of file diff --git a/contrib/xfeatures2d.go b/contrib/xfeatures2d.go index be943281..e0ea134b 100644 --- a/contrib/xfeatures2d.go +++ b/contrib/xfeatures2d.go @@ -76,3 +76,58 @@ func getKeyPoints(ret C.KeyPoints) []gocv.KeyPoint { } return keys } + +// BeblidDescriptorExtractor is a wrapper around the cv::BeblidDescriptorExtractor descriptor algorithm. +type BeblidDescriptorExtractor struct { + // C.BeblidDescriptorExtractor + p unsafe.Pointer +} + +type BeblidDescriptorExtractorSize = int + +const ( + BEBLID_SIZE_256_BITS BeblidDescriptorExtractorSize = 101 + BEBLID_SIZE_512_BITS BeblidDescriptorExtractorSize = 100 +) + +// NewBeblidDescriptorExtractor returns a new BEBLID descriptor algorithm. +// +// For further details, please see: +// https://docs.opencv.org/master/d5/df7/classcv_1_1xfeatures2d_1_1SURF.html +func NewBeblidDescriptorExtractor(scaleFactor float32, size BeblidDescriptorExtractorSize) BeblidDescriptorExtractor { + return BeblidDescriptorExtractor{p: unsafe.Pointer(C.BeblidDescriptorExtractor_Create(C.float(scaleFactor), C.int(size)))} +} + +// Close BEBLID. +func (d *BeblidDescriptorExtractor) Close() error { + C.BeblidDescriptorExtractor_Close((C.BeblidDescriptorExtractor)(d.p)) + d.p = nil + return nil +} + +// Detect describes keypoints in an image using BEBLID +// +// For further details, please see: +// https://docs.opencv.org/4.9.0/d7/d99/classcv_1_1xfeatures2d_1_1BEBLID.html +func (b *BeblidDescriptorExtractor) Compute(keyPoints []gocv.KeyPoint, src gocv.Mat) gocv.Mat { + desc := gocv.NewMat() + cKeyPointArray := make([]C.struct_KeyPoint, len(keyPoints)) + + for i, kp := range keyPoints { + cKeyPointArray[i].x = C.double(kp.X) + cKeyPointArray[i].y = C.double(kp.Y) + cKeyPointArray[i].size = C.double(kp.Size) + cKeyPointArray[i].angle = C.double(kp.Angle) + cKeyPointArray[i].response = C.double(kp.Response) + cKeyPointArray[i].octave = C.int(kp.Octave) + cKeyPointArray[i].classID = C.int(kp.ClassID) + } + + cKeyPoints := C.struct_KeyPoints{ + keypoints: (*C.struct_KeyPoint)(&cKeyPointArray[0]), + length: (C.int)(len(keyPoints)), + } + + C.BeblidDescriptorExtractor_Compute((C.BeblidDescriptorExtractor)(b.p), C.Mat(src.Ptr()), cKeyPoints, C.Mat(desc.Ptr())) + return desc +} diff --git a/contrib/xfeatures2d.h b/contrib/xfeatures2d.h index e513a160..78ba5194 100644 --- a/contrib/xfeatures2d.h +++ b/contrib/xfeatures2d.h @@ -11,8 +11,10 @@ extern "C" { #ifdef __cplusplus typedef cv::Ptr* SURF; +typedef cv::Ptr* BeblidDescriptorExtractor; #else typedef void* SURF; +typedef void* BeblidDescriptorExtractor; #endif SURF SURF_Create(); @@ -20,6 +22,10 @@ void SURF_Close(SURF f); struct KeyPoints SURF_Detect(SURF f, Mat src); struct KeyPoints SURF_DetectAndCompute(SURF f, Mat src, Mat mask, Mat desc); +BeblidDescriptorExtractor BeblidDescriptorExtractor_Create(float scaleFactor, int size); +void BeblidDescriptorExtractor_Close(BeblidDescriptorExtractor b); +void BeblidDescriptorExtractor_Compute(BeblidDescriptorExtractor b, Mat src, struct KeyPoints kp, Mat desc); + #ifdef __cplusplus } #endif diff --git a/contrib/xfeatures2d_test.go b/contrib/xfeatures2d_test.go index 06eb54e9..5411ea75 100644 --- a/contrib/xfeatures2d_test.go +++ b/contrib/xfeatures2d_test.go @@ -42,3 +42,33 @@ func TestSURF(t *testing.T) { t.Error("Invalid Mat desc in SURF DetectAndCompute") } } + +func TestBeblidDescriptorExtractor(t *testing.T) { + testNonFree := os.Getenv("OPENCV_ENABLE_NONFREE") + if testNonFree == "" { + t.Skip("Skipping BeblidDescriptorExtractor test since OPENCV_ENABLE_NONFREE was not set") + } + + img := gocv.IMRead("../images/face.jpg", gocv.IMReadGrayScale) + if img.Empty() { + t.Error("Invalid Mat in BeblidDescriptorExtractor test") + } + defer img.Close() + + fast := gocv.NewFastFeatureDetector() + defer fast.Close() + + b := NewBeblidDescriptorExtractor(1.00, BEBLID_SIZE_512_BITS) + defer b.Close() + + kp := fast.Detect(img) + + mask := gocv.NewMat() + defer mask.Close() + + desc := b.Compute(kp, img) + + if desc.Empty() { + t.Error("Invalid Mat desc in BeblidDescriptorExtractor Compute") + } +}