opencv-ffi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +15 -0
- data/README.md +126 -0
- data/Rakefile +52 -0
- data/docs/DocsIndex.md +1 -0
- data/docs/examples/load_image.rb +25 -0
- data/ext/Rakefile +13 -0
- data/ext/aishack-sift/.gitignore +4 -0
- data/ext/aishack-sift/Descriptor.h +34 -0
- data/ext/aishack-sift/KeyPoint.h +38 -0
- data/ext/aishack-sift/README +20 -0
- data/ext/aishack-sift/SIFT.cpp +1036 -0
- data/ext/aishack-sift/SIFT.h +84 -0
- data/ext/aishack-sift/example/.gitignore +2 -0
- data/ext/aishack-sift/example/Makefile +24 -0
- data/ext/aishack-sift/example/MySIFT.cpp +29 -0
- data/ext/aishack-sift/mkrf_conf.rb +13 -0
- data/ext/aishack-sift/siftlib.cpp +85 -0
- data/ext/eigen/.gitignore +4 -0
- data/ext/eigen/eigen_polynomial.cpp +41 -0
- data/ext/eigen/eigen_svd.cpp +100 -0
- data/ext/eigen/mkrf_conf.rb +14 -0
- data/ext/mkrf-monkey.rb +85 -0
- data/ext/mkrf-rakehelper-monkey.rb +52 -0
- data/ext/mkrf_conf.rb +3 -0
- data/ext/opencv-ffi/.gitignore +4 -0
- data/ext/opencv-ffi/matcher_helper.cpp +56 -0
- data/ext/opencv-ffi/mkrf_conf.rb +12 -0
- data/ext/opencv-ffi/vector_math.cpp +39 -0
- data/ext/opensurf/.gitignore +4 -0
- data/ext/opensurf/README +38 -0
- data/ext/opensurf/fasthessian.cpp +376 -0
- data/ext/opensurf/fasthessian.h +108 -0
- data/ext/opensurf/integral.cpp +58 -0
- data/ext/opensurf/integral.h +55 -0
- data/ext/opensurf/ipoint.cpp +108 -0
- data/ext/opensurf/ipoint.h +76 -0
- data/ext/opensurf/kmeans.h +172 -0
- data/ext/opensurf/mkrf_conf.rb +10 -0
- data/ext/opensurf/responselayer.h +92 -0
- data/ext/opensurf/surf.cpp +317 -0
- data/ext/opensurf/surf.h +66 -0
- data/ext/opensurf/surflib.cpp +98 -0
- data/ext/opensurf/surflib.h +96 -0
- data/ext/opensurf/utils.cpp +357 -0
- data/ext/opensurf/utils.h +63 -0
- data/lib/.gitignore +1 -0
- data/lib/opencv-ffi-ext/eigen.rb +84 -0
- data/lib/opencv-ffi-ext/features2d.rb +4 -0
- data/lib/opencv-ffi-ext/matcher_helper.rb +24 -0
- data/lib/opencv-ffi-ext/opensurf.rb +217 -0
- data/lib/opencv-ffi-ext/sift.rb +118 -0
- data/lib/opencv-ffi-ext/vector_math.rb +115 -0
- data/lib/opencv-ffi-wrappers.rb +7 -0
- data/lib/opencv-ffi-wrappers/core.rb +24 -0
- data/lib/opencv-ffi-wrappers/core/iplimage.rb +50 -0
- data/lib/opencv-ffi-wrappers/core/mat.rb +268 -0
- data/lib/opencv-ffi-wrappers/core/misc_draw.rb +44 -0
- data/lib/opencv-ffi-wrappers/core/point.rb +286 -0
- data/lib/opencv-ffi-wrappers/core/rect.rb +40 -0
- data/lib/opencv-ffi-wrappers/core/scalar.rb +104 -0
- data/lib/opencv-ffi-wrappers/core/size.rb +88 -0
- data/lib/opencv-ffi-wrappers/enumerable.rb +10 -0
- data/lib/opencv-ffi-wrappers/features2d.rb +17 -0
- data/lib/opencv-ffi-wrappers/features2d/image_patch.rb +322 -0
- data/lib/opencv-ffi-wrappers/features2d/star.rb +111 -0
- data/lib/opencv-ffi-wrappers/features2d/surf.rb +115 -0
- data/lib/opencv-ffi-wrappers/highgui.rb +10 -0
- data/lib/opencv-ffi-wrappers/imgproc.rb +4 -0
- data/lib/opencv-ffi-wrappers/imgproc/features.rb +35 -0
- data/lib/opencv-ffi-wrappers/imgproc/geometric.rb +39 -0
- data/lib/opencv-ffi-wrappers/matcher.rb +297 -0
- data/lib/opencv-ffi-wrappers/matrix.rb +37 -0
- data/lib/opencv-ffi-wrappers/misc.rb +41 -0
- data/lib/opencv-ffi-wrappers/misc/params.rb +34 -0
- data/lib/opencv-ffi-wrappers/sequence.rb +37 -0
- data/lib/opencv-ffi-wrappers/vectors.rb +38 -0
- data/lib/opencv-ffi.rb +12 -0
- data/lib/opencv-ffi/calib3d.rb +26 -0
- data/lib/opencv-ffi/core.rb +15 -0
- data/lib/opencv-ffi/core/draw.rb +68 -0
- data/lib/opencv-ffi/core/dynamic.rb +13 -0
- data/lib/opencv-ffi/core/library.rb +5 -0
- data/lib/opencv-ffi/core/operations.rb +122 -0
- data/lib/opencv-ffi/core/point.rb +22 -0
- data/lib/opencv-ffi/core/types.rb +172 -0
- data/lib/opencv-ffi/cvffi.rb +8 -0
- data/lib/opencv-ffi/features2d.rb +7 -0
- data/lib/opencv-ffi/features2d/library.rb +6 -0
- data/lib/opencv-ffi/features2d/star.rb +30 -0
- data/lib/opencv-ffi/features2d/surf.rb +38 -0
- data/lib/opencv-ffi/highgui.rb +31 -0
- data/lib/opencv-ffi/imgproc.rb +9 -0
- data/lib/opencv-ffi/imgproc/features.rb +37 -0
- data/lib/opencv-ffi/imgproc/geometric.rb +42 -0
- data/lib/opencv-ffi/imgproc/library.rb +6 -0
- data/lib/opencv-ffi/imgproc/misc.rb +39 -0
- data/lib/opencv-ffi/version.rb +3 -0
- data/opencv-ffi.gemspec +26 -0
- data/test/core/test_draw.rb +46 -0
- data/test/core/test_operations.rb +135 -0
- data/test/core/test_size.rb +14 -0
- data/test/core/test_text.rb +52 -0
- data/test/ext/test_eigen.rb +105 -0
- data/test/ext/test_opensurf.rb +35 -0
- data/test/ext/test_sift.rb +26 -0
- data/test/ext/test_vector_math.rb +85 -0
- data/test/features2d/test_surf.rb +63 -0
- data/test/imgproc/test_goodfeatures.rb +18 -0
- data/test/setup.rb +65 -0
- data/test/test_calib3d.rb +38 -0
- data/test/test_core.rb +26 -0
- data/test/test_ext.rb +8 -0
- data/test/test_features2d.rb +9 -0
- data/test/test_files/images/IMG_7088.JPG +0 -0
- data/test/test_files/images/IMG_7088_small.JPG +0 -0
- data/test/test_files/images/IMG_7089.JPG +0 -0
- data/test/test_highgui.rb +26 -0
- data/test/test_imgproc.rb +35 -0
- data/test/test_wrappers.rb +8 -0
- data/test/wrappers/core/test_draw.rb +41 -0
- data/test/wrappers/core/test_mat.rb +40 -0
- data/test/wrappers/core/test_operations.rb +35 -0
- data/test/wrappers/core/test_types.rb +235 -0
- data/test/wrappers/features2d/test_image_patch.rb +108 -0
- data/test/wrappers/test_imgproc.rb +87 -0
- data/test/wrappers/test_matcher.rb +96 -0
- data/test/wrappers/test_star.rb +28 -0
- data/test/wrappers/test_surf.rb +36 -0
- metadata +234 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/***********************************************************
|
|
2
|
+
* --- OpenSURF --- *
|
|
3
|
+
* This library is distributed under the GNU GPL. Please *
|
|
4
|
+
* use the contact form at http://www.chrisevansdev.com *
|
|
5
|
+
* for more information. *
|
|
6
|
+
* *
|
|
7
|
+
* C. Evans, Research Into Robust Visual Features, *
|
|
8
|
+
* MSc University of Bristol, 2008. *
|
|
9
|
+
* *
|
|
10
|
+
************************************************************/
|
|
11
|
+
|
|
12
|
+
#ifndef UTILS_H
|
|
13
|
+
#define UTILS_H
|
|
14
|
+
|
|
15
|
+
#include <opencv2/core/core.hpp>
|
|
16
|
+
#include "ipoint.h"
|
|
17
|
+
|
|
18
|
+
#include <vector>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
//! Display error message and terminate program
|
|
22
|
+
void error(const char *msg);
|
|
23
|
+
|
|
24
|
+
//! Show the provided image and wait for keypress
|
|
25
|
+
void showImage(const IplImage *img);
|
|
26
|
+
|
|
27
|
+
//! Show the provided image in titled window and wait for keypress
|
|
28
|
+
void showImage(char *title,const IplImage *img);
|
|
29
|
+
|
|
30
|
+
// Convert image to single channel 32F
|
|
31
|
+
IplImage* getGray(const IplImage *img);
|
|
32
|
+
|
|
33
|
+
//! Draw a single feature on the image
|
|
34
|
+
void drawIpoint(IplImage *img, Ipoint &ipt, int tailSize = 0);
|
|
35
|
+
|
|
36
|
+
//! Draw all the Ipoints in the provided vector
|
|
37
|
+
void drawIpoints(IplImage *img, std::vector<Ipoint> &ipts, int tailSize = 0);
|
|
38
|
+
|
|
39
|
+
//! Draw descriptor windows around Ipoints in the provided vector
|
|
40
|
+
void drawWindows(IplImage *img, std::vector<Ipoint> &ipts);
|
|
41
|
+
|
|
42
|
+
// Draw the FPS figure on the image (requires at least 2 calls)
|
|
43
|
+
void drawFPS(IplImage *img);
|
|
44
|
+
|
|
45
|
+
//! Draw a Point at feature location
|
|
46
|
+
void drawPoint(IplImage *img, Ipoint &ipt);
|
|
47
|
+
|
|
48
|
+
//! Draw a Point at all features
|
|
49
|
+
void drawPoints(IplImage *img, std::vector<Ipoint> &ipts);
|
|
50
|
+
|
|
51
|
+
//! Save the SURF features to file
|
|
52
|
+
void saveSurf(char *filename, std::vector<Ipoint> &ipts);
|
|
53
|
+
|
|
54
|
+
//! Load the SURF features from file
|
|
55
|
+
void loadSurf(char *filename, std::vector<Ipoint> &ipts);
|
|
56
|
+
|
|
57
|
+
//! Round float to nearest integer
|
|
58
|
+
inline int fRound(float flt)
|
|
59
|
+
{
|
|
60
|
+
return (int) floor(flt+0.5f);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#endif
|
data/lib/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.so
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
require 'opencv-ffi'
|
|
3
|
+
require 'opencv-ffi-wrappers'
|
|
4
|
+
|
|
5
|
+
module CVFFI
|
|
6
|
+
module Eigen
|
|
7
|
+
extend NiceFFI::Library
|
|
8
|
+
|
|
9
|
+
libs_dir = File.dirname(__FILE__) + "/../../ext/eigen/"
|
|
10
|
+
pathset = NiceFFI::PathSet::DEFAULT.prepend( libs_dir )
|
|
11
|
+
load_library("cvffi_eigen", pathset)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##--- SVD bits ---
|
|
15
|
+
class EigenSvdResults < NiceFFI::Struct
|
|
16
|
+
layout :D, CvMat.typed_pointer,
|
|
17
|
+
:U, CvMat.typed_pointer,
|
|
18
|
+
:V, CvMat.typed_pointer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attach_function :eigenSvdWithCvMat, [:pointer, :pointer, :uchar], :void
|
|
22
|
+
|
|
23
|
+
def self.svd( a, opts = {} )
|
|
24
|
+
thin = opts[:thin] ? 1 : 0
|
|
25
|
+
|
|
26
|
+
results = EigenSvdResults.new '\0'
|
|
27
|
+
eigenSvdWithCvMat( a.to_CvMat, results, thin )
|
|
28
|
+
|
|
29
|
+
[ results.U, results.D, results.V ]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##-- Eigenvector solvers
|
|
33
|
+
class EigenDecompResults < NiceFFI::Struct
|
|
34
|
+
layout :D, CvMat.typed_pointer,
|
|
35
|
+
:V, CvMat.typed_pointer
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attach_function :eigenDecompWithCvMat, [:pointer, :pointer], :void
|
|
39
|
+
|
|
40
|
+
def self.eigen( a )
|
|
41
|
+
results = EigenDecompResults.new '\0'
|
|
42
|
+
eigenDecompWithCvMat( a.to_CvMat, results )
|
|
43
|
+
|
|
44
|
+
[results.D, results.V]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
##--- Polynomial solver bits --
|
|
49
|
+
class Eigen7d <NiceFFI::Struct
|
|
50
|
+
layout :a, :double,
|
|
51
|
+
:b, :double,
|
|
52
|
+
:c, :double,
|
|
53
|
+
:d, :double,
|
|
54
|
+
:e, :double,
|
|
55
|
+
:f, :double,
|
|
56
|
+
:g, :double
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Eigen6d < NiceFFI::Struct
|
|
60
|
+
layout :a, :double,
|
|
61
|
+
:b, :double,
|
|
62
|
+
:c, :double,
|
|
63
|
+
:d, :double,
|
|
64
|
+
:e, :double,
|
|
65
|
+
:f, :double
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
attach_function :eigenPoly6Solver, [Eigen7d.by_value], Eigen6d.by_value
|
|
69
|
+
|
|
70
|
+
def self.polySolver( a )
|
|
71
|
+
|
|
72
|
+
case a.length
|
|
73
|
+
when 7 then
|
|
74
|
+
coeffs = Eigen7d.new( a )
|
|
75
|
+
answer = eigenPoly6Solver( coeffs )
|
|
76
|
+
else
|
|
77
|
+
raise "Can't solve polynomial with #{a.length} coefficients"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
answer.to_ary
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
require 'nice-ffi'
|
|
3
|
+
require 'opencv-ffi-wrappers/matcher'
|
|
4
|
+
|
|
5
|
+
module CVFFI
|
|
6
|
+
extend NiceFFI::Library
|
|
7
|
+
|
|
8
|
+
libs_dir = File.dirname(__FILE__) + "/../../ext/opencv-ffi/"
|
|
9
|
+
pathset = NiceFFI::PathSet::DEFAULT.prepend( libs_dir )
|
|
10
|
+
load_library("cvffi", pathset)
|
|
11
|
+
|
|
12
|
+
attach_function :computeReprojError, [:pointer, :pointer], :double
|
|
13
|
+
attach_function :computeSetReprojError, [:pointer, :pointer], :void
|
|
14
|
+
|
|
15
|
+
def self.compute_reproj_error( match, model )
|
|
16
|
+
computeReprojError( match, model.to_CvMat( :type => :CV_64F ) )
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.compute_set_reproj_error( matchSet, model )
|
|
20
|
+
computeSetReprojError( matchSet, model.to_CvMat( :type => :CV_64F ) )
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
|
|
2
|
+
require 'nice-ffi'
|
|
3
|
+
|
|
4
|
+
require 'opencv-ffi-wrappers/features2d/surf'
|
|
5
|
+
|
|
6
|
+
module CVFFI
|
|
7
|
+
module OpenSURF
|
|
8
|
+
extend NiceFFI::Library
|
|
9
|
+
|
|
10
|
+
libs_dir = File.dirname(__FILE__) + "/../../ext/opensurf/"
|
|
11
|
+
pathset = NiceFFI::PathSet::DEFAULT.prepend( libs_dir )
|
|
12
|
+
load_library("cvffi_opensurf", pathset)
|
|
13
|
+
|
|
14
|
+
class OpenSURFParams < NiceFFI::Struct
|
|
15
|
+
layout :upright, :char,
|
|
16
|
+
:octaves, :int,
|
|
17
|
+
:intervals, :int,
|
|
18
|
+
:init_sample, :int,
|
|
19
|
+
:thres, :float
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class OpenSURFPoint < NiceFFI::Struct
|
|
23
|
+
layout :pt, CvPoint,
|
|
24
|
+
:scale, :float,
|
|
25
|
+
:orientation, :float,
|
|
26
|
+
:laplacian, :int,
|
|
27
|
+
:descriptor, [ :float, 64 ]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# CvSeq *opensurfDet( IplImage *img,
|
|
32
|
+
# CvMemStorage *storage,
|
|
33
|
+
# CvSURFParams params )
|
|
34
|
+
attach_function :openSurfDetect, [ :pointer, :pointer, OpenSURFParams.by_value ], CvSeq.typed_pointer
|
|
35
|
+
attach_function :openSurfDescribe, [ :pointer, :pointer, OpenSURFParams.by_value ], CvSeq.typed_pointer
|
|
36
|
+
attach_function :createOpenSURFPointSequence, [:pointer ], CvSeq.typed_pointer
|
|
37
|
+
|
|
38
|
+
class Result
|
|
39
|
+
attr_accessor :kp
|
|
40
|
+
def initialize( kp )
|
|
41
|
+
@kp = CVFFI::OpenSURF::OpenSURFPoint.new(kp)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def pt; @kp.pt; end
|
|
45
|
+
def x; pt.x; end
|
|
46
|
+
def y; pt.y; end
|
|
47
|
+
|
|
48
|
+
def scale; @kp.scale; end
|
|
49
|
+
def laplacian; @kp.laplacian; end
|
|
50
|
+
def orientation; @kp.orientation; end
|
|
51
|
+
def descriptor; @kp.descriptor; end
|
|
52
|
+
|
|
53
|
+
def distance_to(b)
|
|
54
|
+
CVFFI::VectorMath::L2distance( @kp.descriptor, b.descriptor, 64 )
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_vector
|
|
58
|
+
Vector.[]( x, y, 1 )
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def to_Point
|
|
62
|
+
pt.to_Point
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def packed_descriptor
|
|
66
|
+
[@kp.descriptor.to_a.pack('e64')].pack('m0')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class ResultArray
|
|
71
|
+
include Enumerable
|
|
72
|
+
|
|
73
|
+
attr_reader :kp, :pool
|
|
74
|
+
|
|
75
|
+
def initialize( kp, pool )
|
|
76
|
+
@kp = Sequence.new(kp)
|
|
77
|
+
@pool = pool
|
|
78
|
+
@results = Array.new( @kp.length )
|
|
79
|
+
|
|
80
|
+
destructor = Proc.new { poolPtr = FFI::MemoryPointer.new :pointer
|
|
81
|
+
poolPtr.putPointer( 0, @pool )
|
|
82
|
+
cvReleaseMemStorage( poolPtr ) }
|
|
83
|
+
ObjectSpace.define_finalizer( self, destructor )
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def reset( kp )
|
|
87
|
+
@kp = Sequence.new(kp)
|
|
88
|
+
@pool = kp.storage
|
|
89
|
+
@results = Array.new( @kp.length )
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def result(i)
|
|
94
|
+
@results[i] ||= Result.new( @kp[i] )
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def each
|
|
98
|
+
@results.each_index { |i|
|
|
99
|
+
yield result(i)
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def [](i)
|
|
104
|
+
result(i)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def size
|
|
108
|
+
@kp.size
|
|
109
|
+
end
|
|
110
|
+
alias :length :size
|
|
111
|
+
|
|
112
|
+
def to_CvSeq
|
|
113
|
+
@kp.seq
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def mark_on_image( img, opts )
|
|
117
|
+
each { |r|
|
|
118
|
+
CVFFI::draw_circle( img, r.kp.pt, opts )
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def to_a
|
|
123
|
+
Array.new( size ) { |i|
|
|
124
|
+
r = result(i)
|
|
125
|
+
[ r.x, r.y, r.scale, r.orientation, r.laplacian, r.packed_descriptor ]
|
|
126
|
+
}
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.from_a( a )
|
|
130
|
+
a = YAML::load(a) if a.is_a? String
|
|
131
|
+
raise "Don't know what to do" unless a.is_a? Array
|
|
132
|
+
|
|
133
|
+
pool = CVFFI::cvCreateMemStorage(0)
|
|
134
|
+
cvseq = CVFFI::OpenSURF::createOpenSURFPointSequence( pool )
|
|
135
|
+
seq = Sequence.new cvseq
|
|
136
|
+
|
|
137
|
+
a.each { |r|
|
|
138
|
+
raise "Hm, not what I expected" unless r.length == 6
|
|
139
|
+
point = CVFFI::OpenSURF::OpenSURFPoint.new( '' )
|
|
140
|
+
# Hm, the embedded CvPoint buggers up initialization by hash
|
|
141
|
+
point.scale = r[2]
|
|
142
|
+
point.orientation = r[3]
|
|
143
|
+
point.laplacian = r[4]
|
|
144
|
+
d = r[5].unpack('m')[0].unpack('e64')
|
|
145
|
+
|
|
146
|
+
d.each_with_index { |d,i| point.descriptor[i] = d }
|
|
147
|
+
|
|
148
|
+
# r[5].unpack('e64')
|
|
149
|
+
point.pt.x = r[0]
|
|
150
|
+
point.pt.y = r[1]
|
|
151
|
+
seq.push( point )
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
ra = ResultArray.new( cvseq, pool )
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class Params
|
|
161
|
+
DEFAULTS = { upright: 0,
|
|
162
|
+
octaves: 5,
|
|
163
|
+
intervals: 4,
|
|
164
|
+
thres: 0.0004,
|
|
165
|
+
init_sample: 2 }
|
|
166
|
+
|
|
167
|
+
def initialize( opts = {} )
|
|
168
|
+
@params = {}
|
|
169
|
+
DEFAULTS.keys.each { |k|
|
|
170
|
+
@params[k] = opts[k] || DEFAULTS[k]
|
|
171
|
+
}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def to_OpenSurfParams
|
|
175
|
+
OpenSURFParams.new( @params )
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def to_hash
|
|
179
|
+
@params
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# Detection sets x,y,scale, laplacian
|
|
185
|
+
def self.detect( img, params )
|
|
186
|
+
params = params.to_OpenSurfParams unless params.is_a?( OpenSURFParams )
|
|
187
|
+
raise ArgumentError unless params.is_a?( OpenSURFParams )
|
|
188
|
+
|
|
189
|
+
mem_storage = CVFFI::cvCreateMemStorage( 0 )
|
|
190
|
+
|
|
191
|
+
img = img.ensure_greyscale
|
|
192
|
+
kp = CVFFI::CvSeq.new openSurfDetect( img, mem_storage, params )
|
|
193
|
+
|
|
194
|
+
ResultArray.new( kp, mem_storage )
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Descriptor takes x,y, scale. Apparently not laplcian
|
|
198
|
+
# Sets orientation, descriptor
|
|
199
|
+
def self.describe( img, points, params )
|
|
200
|
+
params = params.to_OpenSurfParams unless params.is_a?( OpenSURFParams )
|
|
201
|
+
raise ArgumentError unless params.is_a?( OpenSURFParams )
|
|
202
|
+
|
|
203
|
+
img = img.ensure_greyscale
|
|
204
|
+
|
|
205
|
+
puts "Extracting #{points.length} features"
|
|
206
|
+
|
|
207
|
+
kp = points.to_CvSeq
|
|
208
|
+
|
|
209
|
+
openSurfDescribe( img, kp, params )
|
|
210
|
+
|
|
211
|
+
points.reset(kp)
|
|
212
|
+
points
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
|
|
2
|
+
require 'nice-ffi'
|
|
3
|
+
|
|
4
|
+
require 'opencv-ffi-wrappers/misc/params'
|
|
5
|
+
|
|
6
|
+
module CVFFI
|
|
7
|
+
|
|
8
|
+
module SIFT
|
|
9
|
+
extend NiceFFI::Library
|
|
10
|
+
|
|
11
|
+
libs_dir = File.dirname(__FILE__) + "/../../ext/aishack-sift/"
|
|
12
|
+
pathset = NiceFFI::PathSet::DEFAULT.prepend( libs_dir )
|
|
13
|
+
load_library("cvffi_sift", pathset)
|
|
14
|
+
|
|
15
|
+
class SiftParams < NiceFFI::Struct
|
|
16
|
+
layout :octaves, :int,
|
|
17
|
+
:intervals, :int
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
NUM_BINS = 36
|
|
21
|
+
class SiftKeypoint < NiceFFI::Struct
|
|
22
|
+
layout :x, :float,
|
|
23
|
+
:y, :float,
|
|
24
|
+
:mag, [:float, NUM_BINS],
|
|
25
|
+
:orien, [:float, NUM_BINS],
|
|
26
|
+
:num_bins, :uint,
|
|
27
|
+
:scale, :uint
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
FV_LENGTH = 128
|
|
31
|
+
class SiftDescriptor < NiceFFI::Struct
|
|
32
|
+
layout :x, :float,
|
|
33
|
+
:y, :float,
|
|
34
|
+
:fv, [:float, FV_LENGTH],
|
|
35
|
+
:fv_length, :uint
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class SiftResults< NiceFFI::Struct
|
|
39
|
+
layout :kps, :pointer,
|
|
40
|
+
:descs, :pointer,
|
|
41
|
+
:len, :uint
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Results
|
|
45
|
+
attr_accessor :kps, :descs
|
|
46
|
+
|
|
47
|
+
def initialize( k, d )
|
|
48
|
+
@kps = k
|
|
49
|
+
@descs = d
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def size
|
|
53
|
+
@kps.length
|
|
54
|
+
end
|
|
55
|
+
alias :length :size
|
|
56
|
+
|
|
57
|
+
def to_a
|
|
58
|
+
a = Array.new
|
|
59
|
+
a << Array.new( size ) { |i|
|
|
60
|
+
kp = kps[i]
|
|
61
|
+
[ kp.x, kp.y, kp.mag, kp.orien, kp.num_bins, kp.scale ]
|
|
62
|
+
}
|
|
63
|
+
a << Array.new( size ) { |i|
|
|
64
|
+
d = descs[i]
|
|
65
|
+
[d.x, d.y, d.fv, d.fv_length]
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.from_a( a )
|
|
70
|
+
a = YAML::load(a) if a.is_a? String
|
|
71
|
+
raise "Don't know what to do" unless a.is_a? Array
|
|
72
|
+
raise "Result isn't a two-element array" unless a.length == 2
|
|
73
|
+
|
|
74
|
+
kps = a[0]
|
|
75
|
+
descs = a[1]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
attach_function :siftDetectDescribe_real, :siftDetectDescribe, [ :pointer, SiftParams.by_value ], SiftResults.typed_pointer
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Params < CVFFI::Params
|
|
84
|
+
param :octaves, 4
|
|
85
|
+
param :intervals, 5
|
|
86
|
+
|
|
87
|
+
def to_SiftParams
|
|
88
|
+
SiftParams.new( octaves: octaves,
|
|
89
|
+
intervals: intervals )
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def self.detect( image, params )
|
|
96
|
+
params = params.to_SiftParams unless params.is_a?( SiftParams )
|
|
97
|
+
|
|
98
|
+
puts "Running SIFT algorithm with #{params.octaves} octaves and #{params.intervals} intervals."
|
|
99
|
+
|
|
100
|
+
kps = siftDetectDescribe_real( image, params )
|
|
101
|
+
|
|
102
|
+
# Unwrap the SiftKeypoints to an Array.
|
|
103
|
+
keypoints = Array.new( kps.len ) { |i|
|
|
104
|
+
SiftKeypoint.new( kps.kps + (i*SiftKeypoint.size))
|
|
105
|
+
}
|
|
106
|
+
descs = Array.new( kps.len ) { |i|
|
|
107
|
+
SiftDescriptor.new( kps.descs + (i*SiftDescriptor.size) )
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
p keypoints[0]
|
|
111
|
+
p descs[0]
|
|
112
|
+
|
|
113
|
+
Results.new( keypoints, descs )
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
end
|