Skip to content

Commit

Permalink
features2d: SIFT patent now expired so is part of main OpenCV modules
Browse files Browse the repository at this point in the history
Signed-off-by: deadprogram <[email protected]>
  • Loading branch information
deadprogram committed Jul 20, 2020
1 parent d54c3bc commit 04b71cb
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 134 deletions.
42 changes: 0 additions & 42 deletions contrib/xfeatures2d.cpp
Original file line number Diff line number Diff line change
@@ -1,47 +1,5 @@
#include "xfeatures2d.h"

SIFT SIFT_Create() {
// TODO: params
return new cv::Ptr<cv::xfeatures2d::SIFT>(cv::xfeatures2d::SIFT::create());
}

void SIFT_Close(SIFT d) {
delete d;
}

struct KeyPoints SIFT_Detect(SIFT d, Mat src) {
std::vector<cv::KeyPoint> detected;
(*d)->detect(*src, detected);

KeyPoint* kps = new KeyPoint[detected.size()];

for (size_t i = 0; i < detected.size(); ++i) {
KeyPoint k = {detected[i].pt.x, detected[i].pt.y, detected[i].size, detected[i].angle,
detected[i].response, detected[i].octave, detected[i].class_id
};
kps[i] = k;
}

KeyPoints ret = {kps, (int)detected.size()};
return ret;
}

struct KeyPoints SIFT_DetectAndCompute(SIFT d, Mat src, Mat mask, Mat desc) {
std::vector<cv::KeyPoint> detected;
(*d)->detectAndCompute(*src, *mask, detected, *desc);

KeyPoint* kps = new KeyPoint[detected.size()];

for (size_t i = 0; i < detected.size(); ++i) {
KeyPoint k = {detected[i].pt.x, detected[i].pt.y, detected[i].size, detected[i].angle,
detected[i].response, detected[i].octave, detected[i].class_id
};
kps[i] = k;
}

KeyPoints ret = {kps, (int)detected.size()};
return ret;
}

SURF SURF_Create() {
// TODO: params
Expand Down
48 changes: 0 additions & 48 deletions contrib/xfeatures2d.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,6 @@ import (
"gocv.io/x/gocv"
)

// SIFT is a wrapper around the cv::SIFT algorithm.
// Due to being a patented algorithm you must set the OpenCV contrib build flag OPENCV_ENABLE_NONFREE=1
// in order to use it.
type SIFT struct {
// C.SIFT
p unsafe.Pointer
}

// NewSIFT returns a new SIFT algorithm.
//
// For further details, please see:
// https://docs.opencv.org/master/d5/d3c/classcv_1_1xfeatures2d_1_1SIFT.html
//
func NewSIFT() SIFT {
return SIFT{p: unsafe.Pointer(C.SIFT_Create())}
}

// Close SIFT.
func (d *SIFT) Close() error {
C.SIFT_Close((C.SIFT)(d.p))
d.p = nil
return nil
}

// Detect keypoints in an image using SIFT.
//
// For further details, please see:
// https://docs.opencv.org/master/d0/d13/classcv_1_1Feature2D.html#aa4e9a7082ec61ebc108806704fbd7887
//
func (d *SIFT) Detect(src gocv.Mat) []gocv.KeyPoint {
ret := C.SIFT_Detect((C.SIFT)(d.p), C.Mat(src.Ptr()))

return getKeyPoints(ret)
}

// DetectAndCompute detects and computes keypoints in an image using SIFT.
//
// For further details, please see:
// https://docs.opencv.org/master/d0/d13/classcv_1_1Feature2D.html#a8be0d1c20b08eb867184b8d74c15a677
//
func (d *SIFT) DetectAndCompute(src gocv.Mat, mask gocv.Mat) ([]gocv.KeyPoint, gocv.Mat) {
desc := gocv.NewMat()
ret := C.SIFT_DetectAndCompute((C.SIFT)(d.p), C.Mat(src.Ptr()), C.Mat(mask.Ptr()),
C.Mat(desc.Ptr()))

return getKeyPoints(ret), desc
}

// SURF is a wrapper around the cv::SURF algorithm.
// Due to being a patented algorithm you must set the OpenCV contrib build flag OPENCV_ENABLE_NONFREE=1
// in order to use it.
Expand Down
7 changes: 0 additions & 7 deletions contrib/xfeatures2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,11 @@ extern "C" {
#include "../core.h"

#ifdef __cplusplus
typedef cv::Ptr<cv::xfeatures2d::SIFT>* SIFT;
typedef cv::Ptr<cv::xfeatures2d::SURF>* SURF;
#else
typedef void* SIFT;
typedef void* SURF;
#endif

SIFT SIFT_Create();
void SIFT_Close(SIFT f);
struct KeyPoints SIFT_Detect(SIFT f, Mat src);
struct KeyPoints SIFT_DetectAndCompute(SIFT f, Mat src, Mat mask, Mat desc);

SURF SURF_Create();
void SURF_Close(SURF f);
struct KeyPoints SURF_Detect(SURF f, Mat src);
Expand Down
36 changes: 0 additions & 36 deletions contrib/xfeatures2d_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,6 @@ import (
"gocv.io/x/gocv"
)

func TestSIFT(t *testing.T) {
testNonFree := os.Getenv("OPENCV_ENABLE_NONFREE")
if testNonFree == "" {
t.Skip("Skipping SIFT test since OPENCV_ENABLE_NONFREE was not set")
}

img := gocv.IMRead("../images/face.jpg", gocv.IMReadGrayScale)
if img.Empty() {
t.Error("Invalid Mat in SIFT test")
}
defer img.Close()

dst := gocv.NewMat()
defer dst.Close()

si := NewSIFT()
defer si.Close()

kp := si.Detect(img)
if len(kp) == 512 {
t.Errorf("Invalid KeyPoint array in SIFT test: %d", len(kp))
}

mask := gocv.NewMat()
defer mask.Close()

kp2, desc := si.DetectAndCompute(img, mask)
if len(kp2) == 512 {
t.Errorf("Invalid KeyPoint array in SIFT DetectAndCompute: %d", len(kp2))
}

if desc.Empty() {
t.Error("Invalid Mat desc in SIFT DetectAndCompute")
}
}

func TestSURF(t *testing.T) {
testNonFree := os.Getenv("OPENCV_ENABLE_NONFREE")
if testNonFree == "" {
Expand Down
43 changes: 43 additions & 0 deletions features2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,3 +428,46 @@ void DrawKeyPoints(Mat src, struct KeyPoints kp, Mat dst, Scalar s, int flags) {

cv::drawKeypoints(*src, keypts, *dst, color, static_cast<cv::DrawMatchesFlags>(flags));
}

SIFT SIFT_Create() {
// TODO: params
return new cv::Ptr<cv::SIFT>(cv::SIFT::create());
}

void SIFT_Close(SIFT d) {
delete d;
}

struct KeyPoints SIFT_Detect(SIFT d, Mat src) {
std::vector<cv::KeyPoint> detected;
(*d)->detect(*src, detected);

KeyPoint* kps = new KeyPoint[detected.size()];

for (size_t i = 0; i < detected.size(); ++i) {
KeyPoint k = {detected[i].pt.x, detected[i].pt.y, detected[i].size, detected[i].angle,
detected[i].response, detected[i].octave, detected[i].class_id
};
kps[i] = k;
}

KeyPoints ret = {kps, (int)detected.size()};
return ret;
}

struct KeyPoints SIFT_DetectAndCompute(SIFT d, Mat src, Mat mask, Mat desc) {
std::vector<cv::KeyPoint> detected;
(*d)->detectAndCompute(*src, *mask, detected, *desc);

KeyPoint* kps = new KeyPoint[detected.size()];

for (size_t i = 0; i < detected.size(); ++i) {
KeyPoint k = {detected[i].pt.x, detected[i].pt.y, detected[i].size, detected[i].angle,
detected[i].response, detected[i].octave, detected[i].class_id
};
kps[i] = k;
}

KeyPoints ret = {kps, (int)detected.size()};
return ret;
}
47 changes: 47 additions & 0 deletions features2d.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,3 +748,50 @@ func DrawKeyPoints(src Mat, keyPoints []KeyPoint, dst *Mat, color color.RGBA, fl

C.DrawKeyPoints(src.p, cKeyPoints, dst.p, scalar, C.int(flag))
}

// SIFT is a wrapper around the cv::SIFT algorithm.
// Due to the patent having expired, this is now in the main OpenCV code modules.
type SIFT struct {
// C.SIFT
p unsafe.Pointer
}

// NewSIFT returns a new SIFT algorithm.
//
// For further details, please see:
// https://docs.opencv.org/master/d5/d3c/classcv_1_1xfeatures2d_1_1SIFT.html
//
func NewSIFT() SIFT {
return SIFT{p: unsafe.Pointer(C.SIFT_Create())}
}

// Close SIFT.
func (d *SIFT) Close() error {
C.SIFT_Close((C.SIFT)(d.p))
d.p = nil
return nil
}

// Detect keypoints in an image using SIFT.
//
// For further details, please see:
// https://docs.opencv.org/master/d0/d13/classcv_1_1Feature2D.html#aa4e9a7082ec61ebc108806704fbd7887
//
func (d *SIFT) Detect(src Mat) []KeyPoint {
ret := C.SIFT_Detect((C.SIFT)(d.p), C.Mat(src.Ptr()))

return getKeyPoints(ret)
}

// DetectAndCompute detects and computes keypoints in an image using SIFT.
//
// For further details, please see:
// https://docs.opencv.org/master/d0/d13/classcv_1_1Feature2D.html#a8be0d1c20b08eb867184b8d74c15a677
//
func (d *SIFT) DetectAndCompute(src Mat, mask Mat) ([]KeyPoint, Mat) {
desc := NewMat()
ret := C.SIFT_DetectAndCompute((C.SIFT)(d.p), C.Mat(src.Ptr()), C.Mat(mask.Ptr()),
C.Mat(desc.Ptr()))

return getKeyPoints(ret), desc
}
7 changes: 7 additions & 0 deletions features2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ typedef cv::Ptr<cv::MSER>* MSER;
typedef cv::Ptr<cv::ORB>* ORB;
typedef cv::Ptr<cv::SimpleBlobDetector>* SimpleBlobDetector;
typedef cv::Ptr<cv::BFMatcher>* BFMatcher;
typedef cv::Ptr<cv::SIFT>* SIFT;
#else
typedef void* AKAZE;
typedef void* AgastFeatureDetector;
Expand All @@ -30,6 +31,7 @@ typedef void* MSER;
typedef void* ORB;
typedef void* SimpleBlobDetector;
typedef void* BFMatcher;
typedef void* SIFT;
#endif

AKAZE AKAZE_Create();
Expand Down Expand Up @@ -82,6 +84,11 @@ struct MultiDMatches BFMatcher_KnnMatch(BFMatcher b, Mat query, Mat train, int k

void DrawKeyPoints(Mat src, struct KeyPoints kp, Mat dst, const Scalar s, int flags);

SIFT SIFT_Create();
void SIFT_Close(SIFT f);
struct KeyPoints SIFT_Detect(SIFT f, Mat src);
struct KeyPoints SIFT_DetectAndCompute(SIFT f, Mat src, Mat mask, Mat desc);

#ifdef __cplusplus
}
#endif
Expand Down
31 changes: 31 additions & 0 deletions features2d_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,34 @@ func TestDrawKeyPoints(t *testing.T) {
t.Error("Invalid DrawKeyPoints test")
}
}

func TestSIFT(t *testing.T) {
img := IMRead("./images/face.jpg", IMReadGrayScale)
if img.Empty() {
t.Error("Invalid Mat in SIFT test")
}
defer img.Close()

dst := NewMat()
defer dst.Close()

si := NewSIFT()
defer si.Close()

kp := si.Detect(img)
if len(kp) == 512 {
t.Errorf("Invalid KeyPoint array in SIFT test: %d", len(kp))
}

mask := NewMat()
defer mask.Close()

kp2, desc := si.DetectAndCompute(img, mask)
if len(kp2) == 512 {
t.Errorf("Invalid KeyPoint array in SIFT DetectAndCompute: %d", len(kp2))
}

if desc.Empty() {
t.Error("Invalid Mat desc in SIFT DetectAndCompute")
}
}
2 changes: 1 addition & 1 deletion version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
func TestVersions(t *testing.T) {
ocvv := OpenCVVersion()

if !strings.Contains(ocvv, "4.3") {
if !strings.Contains(ocvv, "4.4") {
t.Error("Wrong version of OpenCV:", ocvv)
}

Expand Down

0 comments on commit 04b71cb

Please sign in to comment.