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.
Files changed (130) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +15 -0
  3. data/README.md +126 -0
  4. data/Rakefile +52 -0
  5. data/docs/DocsIndex.md +1 -0
  6. data/docs/examples/load_image.rb +25 -0
  7. data/ext/Rakefile +13 -0
  8. data/ext/aishack-sift/.gitignore +4 -0
  9. data/ext/aishack-sift/Descriptor.h +34 -0
  10. data/ext/aishack-sift/KeyPoint.h +38 -0
  11. data/ext/aishack-sift/README +20 -0
  12. data/ext/aishack-sift/SIFT.cpp +1036 -0
  13. data/ext/aishack-sift/SIFT.h +84 -0
  14. data/ext/aishack-sift/example/.gitignore +2 -0
  15. data/ext/aishack-sift/example/Makefile +24 -0
  16. data/ext/aishack-sift/example/MySIFT.cpp +29 -0
  17. data/ext/aishack-sift/mkrf_conf.rb +13 -0
  18. data/ext/aishack-sift/siftlib.cpp +85 -0
  19. data/ext/eigen/.gitignore +4 -0
  20. data/ext/eigen/eigen_polynomial.cpp +41 -0
  21. data/ext/eigen/eigen_svd.cpp +100 -0
  22. data/ext/eigen/mkrf_conf.rb +14 -0
  23. data/ext/mkrf-monkey.rb +85 -0
  24. data/ext/mkrf-rakehelper-monkey.rb +52 -0
  25. data/ext/mkrf_conf.rb +3 -0
  26. data/ext/opencv-ffi/.gitignore +4 -0
  27. data/ext/opencv-ffi/matcher_helper.cpp +56 -0
  28. data/ext/opencv-ffi/mkrf_conf.rb +12 -0
  29. data/ext/opencv-ffi/vector_math.cpp +39 -0
  30. data/ext/opensurf/.gitignore +4 -0
  31. data/ext/opensurf/README +38 -0
  32. data/ext/opensurf/fasthessian.cpp +376 -0
  33. data/ext/opensurf/fasthessian.h +108 -0
  34. data/ext/opensurf/integral.cpp +58 -0
  35. data/ext/opensurf/integral.h +55 -0
  36. data/ext/opensurf/ipoint.cpp +108 -0
  37. data/ext/opensurf/ipoint.h +76 -0
  38. data/ext/opensurf/kmeans.h +172 -0
  39. data/ext/opensurf/mkrf_conf.rb +10 -0
  40. data/ext/opensurf/responselayer.h +92 -0
  41. data/ext/opensurf/surf.cpp +317 -0
  42. data/ext/opensurf/surf.h +66 -0
  43. data/ext/opensurf/surflib.cpp +98 -0
  44. data/ext/opensurf/surflib.h +96 -0
  45. data/ext/opensurf/utils.cpp +357 -0
  46. data/ext/opensurf/utils.h +63 -0
  47. data/lib/.gitignore +1 -0
  48. data/lib/opencv-ffi-ext/eigen.rb +84 -0
  49. data/lib/opencv-ffi-ext/features2d.rb +4 -0
  50. data/lib/opencv-ffi-ext/matcher_helper.rb +24 -0
  51. data/lib/opencv-ffi-ext/opensurf.rb +217 -0
  52. data/lib/opencv-ffi-ext/sift.rb +118 -0
  53. data/lib/opencv-ffi-ext/vector_math.rb +115 -0
  54. data/lib/opencv-ffi-wrappers.rb +7 -0
  55. data/lib/opencv-ffi-wrappers/core.rb +24 -0
  56. data/lib/opencv-ffi-wrappers/core/iplimage.rb +50 -0
  57. data/lib/opencv-ffi-wrappers/core/mat.rb +268 -0
  58. data/lib/opencv-ffi-wrappers/core/misc_draw.rb +44 -0
  59. data/lib/opencv-ffi-wrappers/core/point.rb +286 -0
  60. data/lib/opencv-ffi-wrappers/core/rect.rb +40 -0
  61. data/lib/opencv-ffi-wrappers/core/scalar.rb +104 -0
  62. data/lib/opencv-ffi-wrappers/core/size.rb +88 -0
  63. data/lib/opencv-ffi-wrappers/enumerable.rb +10 -0
  64. data/lib/opencv-ffi-wrappers/features2d.rb +17 -0
  65. data/lib/opencv-ffi-wrappers/features2d/image_patch.rb +322 -0
  66. data/lib/opencv-ffi-wrappers/features2d/star.rb +111 -0
  67. data/lib/opencv-ffi-wrappers/features2d/surf.rb +115 -0
  68. data/lib/opencv-ffi-wrappers/highgui.rb +10 -0
  69. data/lib/opencv-ffi-wrappers/imgproc.rb +4 -0
  70. data/lib/opencv-ffi-wrappers/imgproc/features.rb +35 -0
  71. data/lib/opencv-ffi-wrappers/imgproc/geometric.rb +39 -0
  72. data/lib/opencv-ffi-wrappers/matcher.rb +297 -0
  73. data/lib/opencv-ffi-wrappers/matrix.rb +37 -0
  74. data/lib/opencv-ffi-wrappers/misc.rb +41 -0
  75. data/lib/opencv-ffi-wrappers/misc/params.rb +34 -0
  76. data/lib/opencv-ffi-wrappers/sequence.rb +37 -0
  77. data/lib/opencv-ffi-wrappers/vectors.rb +38 -0
  78. data/lib/opencv-ffi.rb +12 -0
  79. data/lib/opencv-ffi/calib3d.rb +26 -0
  80. data/lib/opencv-ffi/core.rb +15 -0
  81. data/lib/opencv-ffi/core/draw.rb +68 -0
  82. data/lib/opencv-ffi/core/dynamic.rb +13 -0
  83. data/lib/opencv-ffi/core/library.rb +5 -0
  84. data/lib/opencv-ffi/core/operations.rb +122 -0
  85. data/lib/opencv-ffi/core/point.rb +22 -0
  86. data/lib/opencv-ffi/core/types.rb +172 -0
  87. data/lib/opencv-ffi/cvffi.rb +8 -0
  88. data/lib/opencv-ffi/features2d.rb +7 -0
  89. data/lib/opencv-ffi/features2d/library.rb +6 -0
  90. data/lib/opencv-ffi/features2d/star.rb +30 -0
  91. data/lib/opencv-ffi/features2d/surf.rb +38 -0
  92. data/lib/opencv-ffi/highgui.rb +31 -0
  93. data/lib/opencv-ffi/imgproc.rb +9 -0
  94. data/lib/opencv-ffi/imgproc/features.rb +37 -0
  95. data/lib/opencv-ffi/imgproc/geometric.rb +42 -0
  96. data/lib/opencv-ffi/imgproc/library.rb +6 -0
  97. data/lib/opencv-ffi/imgproc/misc.rb +39 -0
  98. data/lib/opencv-ffi/version.rb +3 -0
  99. data/opencv-ffi.gemspec +26 -0
  100. data/test/core/test_draw.rb +46 -0
  101. data/test/core/test_operations.rb +135 -0
  102. data/test/core/test_size.rb +14 -0
  103. data/test/core/test_text.rb +52 -0
  104. data/test/ext/test_eigen.rb +105 -0
  105. data/test/ext/test_opensurf.rb +35 -0
  106. data/test/ext/test_sift.rb +26 -0
  107. data/test/ext/test_vector_math.rb +85 -0
  108. data/test/features2d/test_surf.rb +63 -0
  109. data/test/imgproc/test_goodfeatures.rb +18 -0
  110. data/test/setup.rb +65 -0
  111. data/test/test_calib3d.rb +38 -0
  112. data/test/test_core.rb +26 -0
  113. data/test/test_ext.rb +8 -0
  114. data/test/test_features2d.rb +9 -0
  115. data/test/test_files/images/IMG_7088.JPG +0 -0
  116. data/test/test_files/images/IMG_7088_small.JPG +0 -0
  117. data/test/test_files/images/IMG_7089.JPG +0 -0
  118. data/test/test_highgui.rb +26 -0
  119. data/test/test_imgproc.rb +35 -0
  120. data/test/test_wrappers.rb +8 -0
  121. data/test/wrappers/core/test_draw.rb +41 -0
  122. data/test/wrappers/core/test_mat.rb +40 -0
  123. data/test/wrappers/core/test_operations.rb +35 -0
  124. data/test/wrappers/core/test_types.rb +235 -0
  125. data/test/wrappers/features2d/test_image_patch.rb +108 -0
  126. data/test/wrappers/test_imgproc.rb +87 -0
  127. data/test/wrappers/test_matcher.rb +96 -0
  128. data/test/wrappers/test_star.rb +28 -0
  129. data/test/wrappers/test_surf.rb +36 -0
  130. 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
@@ -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,4 @@
1
+
2
+
3
+ require 'opencv-ffi-wrappers/features2d/image_patch'
4
+
@@ -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