Skip to content

Commit

Permalink
xfeatures2d: add SIFT and SURF algorithms from OpenCV contrib
Browse files Browse the repository at this point in the history
Signed-off-by: deadprogram <[email protected]>
  • Loading branch information
deadprogram committed Nov 30, 2017
1 parent 475da93 commit d24f3e5
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ before_cache:

script:
- export CGO_CPPFLAGS="-I${HOME}/usr/include"
- export CGO_LDFLAGS="-L${HOME}/usr/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video"
- export CGO_LDFLAGS="-L${HOME}/usr/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_xfeatures2d"
- echo "Ensuring code is well formatted"; ! gofmt -s -d . | read
- go test -coverprofile=coverage.txt -covermode=atomic

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ install:
- cd c:\gopath\src\gocv.io\x\gocv
- go get -d .
- set CGO_CPPFLAGS=-IC:\opencv\build\install\include
- set CGO_LDFLAGS=-LC:\opencv\build\install\x64\mingw\lib -lopencv_core331 -lopencv_videoio331 -lopencv_imgproc331 -lopencv_highgui331 -lopencv_imgcodecs331 -lopencv_objdetect331 -lopencv_features2d331 -lopencv_video331
- set CGO_LDFLAGS=-LC:\opencv\build\install\x64\mingw\lib -lopencv_core331 -lopencv_videoio331 -lopencv_imgproc331 -lopencv_highgui331 -lopencv_imgcodecs331 -lopencv_objdetect331 -lopencv_features2d331 -lopencv_video331 -lopencv_xfeatures2d331
- go env

build_script:
Expand Down
13 changes: 13 additions & 0 deletions contrib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Using OpenCV Contrib

GoCV support for OpenCV's Contrib can be found here in the "gocv.io/x/gocv/contrib" package.

For more information about OpenCV Contrib, please go to:

https://github.com/opencv/opencv_contrib

## How to use

```go
// code here...
```
6 changes: 6 additions & 0 deletions contrib/contrib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Package contrib is the GoCV wrapper around OpenCV Contrib.
//
// For further details, please see:
// https://github.com/opencv/opencv_contrib
//
package contrib // import "gocv.io/x/gocv/contrib"
75 changes: 75 additions & 0 deletions contrib/xfeatures2d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#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
return new cv::Ptr<cv::xfeatures2d::SURF>(cv::xfeatures2d::SURF::create());
}

void SURF_Close(SURF d) {
delete d;
}

struct KeyPoints SURF_Detect(SURF 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 SURF_DetectAndCompute(SURF 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;
}
128 changes: 128 additions & 0 deletions contrib/xfeatures2d.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package contrib

/*
#include <stdlib.h>
#include "xfeatures2d.h"
*/
import "C"

import (
"reflect"
"unsafe"

"gocv.io/x/gocv"
)

// SIFT is a wrapper around the cv::SIFT algorithm.
type SIFT struct {
// C.SIFT
p unsafe.Pointer
}

// NewSIFT returns a new SIFT algorithm.
//
// For further details, please see:
// https://docs.opencv.org/3.3.1/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/3.3.1/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()))
//defer C.KeyPoints_Close(ret)

return getKeyPoints(ret)
}

// DetectAndCompute detects and computes keypoints in an image using SIFT.
//
// For further details, please see:
// https://docs.opencv.org/3.3.1/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()))
//defer C.KeyPoints_Close(ret)

return getKeyPoints(ret), desc
}

// SURF is a wrapper around the cv::SURF algorithm.
type SURF struct {
// C.SURF
p unsafe.Pointer
}

// NewSURF returns a new SURF algorithm.
//
// For further details, please see:
// https://docs.opencv.org/3.3.1/d5/df7/classcv_1_1xfeatures2d_1_1SURF.html
//
func NewSURF() SURF {
return SURF{p: unsafe.Pointer(C.SURF_Create())}
}

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

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

return getKeyPoints(ret)
}

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

return getKeyPoints(ret), desc
}

func getKeyPoints(ret C.KeyPoints) []gocv.KeyPoint {
cArray := ret.keypoints
length := int(ret.length)
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cArray)),
Len: length,
Cap: length,
}
s := *(*[]C.KeyPoint)(unsafe.Pointer(&hdr))

keys := make([]gocv.KeyPoint, length)
for i, r := range s {
keys[i] = gocv.KeyPoint{float64(r.x), float64(r.y), float64(r.size), float64(r.angle), float64(r.response),
int(r.octave), int(r.classID)}
}
return keys
}
34 changes: 34 additions & 0 deletions contrib/xfeatures2d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef _OPENCV3_XFEATURES2D_H_
#define _OPENCV3_XFEATURES2D_H_

#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
extern "C" {
#endif

#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);
struct KeyPoints SURF_DetectAndCompute(SURF f, Mat src, Mat mask, Mat desc);

#ifdef __cplusplus
}
#endif

#endif //_OPENCV3_XFEATURES2D_H_
69 changes: 69 additions & 0 deletions contrib/xfeatures2d_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package contrib

import (
"testing"

"gocv.io/x/gocv"
)

func TestSIFT(t *testing.T) {
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) {
img := gocv.IMRead("../images/face.jpg", gocv.IMReadGrayScale)
if img.Empty() {
t.Error("Invalid Mat in SURF test")
}
defer img.Close()

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

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

kp := si.Detect(img)
if len(kp) == 512 {
t.Errorf("Invalid KeyPoint array in SURF Detect: %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 SURF DetectAndCompute: %d", len(kp2))
}

if desc.Empty() {
t.Error("Invalid Mat desc in SURF DetectAndCompute")
}
}
6 changes: 3 additions & 3 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ if [[ "$uname_val" == "Darwin" ]]; then
CVPATH=$(brew info opencv | sed -n "4p" | sed -e "s/ (.*//g")
export CGO_CPPFLAGS="-I$CVPATH/include -I$CVPATH/include/opencv2"
export CGO_CXXFLAGS="--std=c++1z -stdlib=libc++"
export CGO_LDFLAGS="-L$CVPATH/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video"
export CGO_LDFLAGS="-L$CVPATH/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_xfeatures2d"
echo "Environment variables configured for OSX"
elif [[ "$uname_val" == "Linux" ]]; then
if [[ -f /etc/pacman.conf ]]; then
export CGO_CPPFLAGS="-I/usr/include"
export CGO_CXXFLAGS="--std=c++1z"
export CGO_LDFLAGS="-L/lib64 -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video"
export CGO_LDFLAGS="-L/lib64 -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_xfeatures2d"
else
export CGO_CPPFLAGS="-I/usr/local/include"
export CGO_CXXFLAGS="--std=c++1z"
export CGO_LDFLAGS="-L/usr/local/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video"
export CGO_LDFLAGS="-L/usr/local/lib -lopencv_core -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_xfeatures2d"
fi
echo "Environment variables configured for Linux"
else
Expand Down

0 comments on commit d24f3e5

Please sign in to comment.