opencv-ffi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,52 @@
1
+
2
+ require 'mkrf/rakehelper'
3
+
4
+ alias :old_setup_extension :setup_extension
5
+
6
+ module Mkrf
7
+ @all_libs = []
8
+
9
+ def self.all_libs
10
+ @all_libs
11
+ end
12
+
13
+ def self.all_libs=(a)
14
+ @all_libs = a
15
+ end
16
+ end
17
+
18
+ def rake( rakedir, args = nil )
19
+ Dir.chdir( rakedir ) do
20
+ if args
21
+ sh "rake #{args}"
22
+ else
23
+ sh 'rake'
24
+ end
25
+ end
26
+ end
27
+
28
+ def setup_extension(dir, extension)
29
+
30
+ old_setup_extension( dir, extension )
31
+
32
+ ext_dir = "ext/#{dir}"
33
+ ext_so = "#{ext_dir}/#{extension}.#{Config::CONFIG['DLEXT']}"
34
+
35
+ task ext_so => FileList["#{ext_dir}/**/*.c*", "#{ext_dir}/mkrf_conf.rb"]
36
+
37
+ Mkrf::all_libs << extension.to_sym
38
+
39
+ namespace extension.to_sym do
40
+
41
+ desc "Run \"rake clean\" in #{ext_dir}"
42
+ task :clean do
43
+ rake ext_dir, 'clean'
44
+ end
45
+
46
+ desc "Run \"rake clobber\" in #{ext_dir}"
47
+ task :clobber do
48
+ rake extd_dir, 'clobber'
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,3 @@
1
+ #
2
+ # Just a shell to fake out Gem
3
+ #
@@ -0,0 +1,4 @@
1
+ *.so
2
+ Rakefile
3
+ *.o
4
+ mkrf.log
@@ -0,0 +1,56 @@
1
+
2
+ #include <opencv2/core/types_c.h>
3
+
4
+ #include <stdio.h>
5
+
6
+ typedef struct {
7
+ CvPoint2D32f train, query;
8
+ double distance;
9
+ } Match_t;
10
+
11
+ typedef struct {
12
+ int length;
13
+ Match_t *d;
14
+ double *error;
15
+ } MatchSet_t;
16
+
17
+ extern "C"
18
+ double computeReprojError( const Match_t *match, const CvMat *model )
19
+ {
20
+ const double* F = model->data.db;
21
+ const CvPoint2D32f *m1 = &(match->train);
22
+ const CvPoint2D32f *m2 = &(match->query);
23
+
24
+ double a, b, c, d1, d2, s1, s2;
25
+
26
+ a = F[0]*m1->x + F[1]*m1->y + F[2];
27
+ b = F[3]*m1->x + F[4]*m1->y + F[5];
28
+ c = F[6]*m1->x + F[7]*m1->y + F[8];
29
+
30
+ s2 = 1./(a*a + b*b);
31
+ d2 = m2->x*a + m2->y*b + c;
32
+
33
+ a = F[0]*m2->x + F[3]*m2->y + F[6];
34
+ b = F[1]*m2->x + F[4]*m2->y + F[7];
35
+ c = F[2]*m2->x + F[5]*m2->y + F[8];
36
+
37
+ s1 = 1./(a*a + b*b);
38
+ d1 = m1->x*a + m1->y*b + c;
39
+
40
+
41
+ a = d1*d1*s1;
42
+ b = d2*d2*s2;
43
+
44
+ if( a>b )
45
+ return a;
46
+ else
47
+ return b;
48
+ }
49
+
50
+ extern "C"
51
+ void computeSetReprojError( MatchSet_t *set, CvMat *model )
52
+ {
53
+ for( int i = 0; i < set->length; i ++ ) {
54
+ set->error[i] = computeReprojError( &(set->d[i]), model );
55
+ }
56
+ }
@@ -0,0 +1,12 @@
1
+ require '../mkrf-monkey'
2
+
3
+ # The compiler for availability checking must be specified as 'g++'
4
+ # otherwise it will use gcc and choke on Eigen
5
+ #
6
+ Mkrf::Generator.new('libcvffi', [ "*.cpp"], { :compiler=>"g++"}) { |g|
7
+ g.include_library 'stdc++'
8
+ raise "Can't find 'opencv_core'" unless g.include_library 'opencv_core', 'main', "#{ENV['HOME']}/usr/lib"
9
+ #g.include_header 'eigen3/Eigen/Core', "#{ENV['HOME']}/usr/include"
10
+ g.cflags += "-I#{ENV['HOME']}/usr/include "
11
+ }
12
+
@@ -0,0 +1,39 @@
1
+
2
+ #include <stdint.h>
3
+
4
+ typedef struct {
5
+ unsigned int len;
6
+ uint8_t *data;
7
+ } uint8_array_t;
8
+
9
+ typedef struct {
10
+ float d[64];
11
+ } float64_t;
12
+
13
+ typedef struct {
14
+ float d[128];
15
+ } float128_t;
16
+
17
+ extern "C"
18
+ float L2distance_32f( const float64_t *a, const float64_t *b, int len )
19
+ {
20
+ // Start with brute force algorithm
21
+ float distance = 0.0;
22
+ for( int i = 0; i < len; i++ ) {
23
+ distance += (a->d[i] - b->d[i])*(a->d[i] - b->d[i]);
24
+ }
25
+ return distance;
26
+ }
27
+
28
+ extern "C"
29
+ float L2distance_8u( const uint8_array_t a, const uint8_array_t b )
30
+ {
31
+ if( a.len != b.len ) { return -1.0; }
32
+
33
+ float distance = 0.0;
34
+ for( unsigned int i = 0; i < a.len; i++ ) {
35
+ distance += (a.data[i] - b.data[i])*(a.data[i]-b.data[i]);
36
+ }
37
+
38
+ return distance;
39
+ }
@@ -0,0 +1,4 @@
1
+ *.o
2
+ Rakefile
3
+ *.so
4
+ mkrf.log
@@ -0,0 +1,38 @@
1
+ This is a version of Chris Evans' OpenSURF C++ library, from:
2
+
3
+ http://www.chrisevansdev.com/computer-vision-opensurf.html
4
+
5
+ distributed under the GPL.
6
+
7
+ All *.cpp/*.h files are from the 27/05/2010 source package bag surflib.cpp which
8
+ is my own C++ to C interface layer.
9
+
10
+ Chris' original README follows:
11
+
12
+ /***********************************************************
13
+ * --- OpenSURF --- *
14
+ * This library is distributed under the GNU GPL. Please *
15
+ * use the contact form at http://www.chrisevansdev.com *
16
+ * for more information. *
17
+ * *
18
+ * C. Evans, Research Into Robust Visual Features, *
19
+ * MSc University of Bristol, 2008. *
20
+ * *
21
+ ************************************************************/
22
+
23
+ Thanks for downloading the OpenSURF library. There are 3 different
24
+ ways to get going with the library:
25
+
26
+ 1) Build using the supplied makefile and run.
27
+ 2) Open the Visual Studio 2005 .sln file (uses OpenCV 1)
28
+ 3) Open the Visual Studio 2008 .sln file (uses OpenCV 2)
29
+
30
+ There are a several examples of code in main.cpp which can be configured
31
+ to run by change the value of PROCEDURE which is defined at the top.
32
+
33
+ If you have any questions contact me via the form on http://www.chrisevansdev.com.
34
+
35
+ If you want to stay up to date with the library follow @chrisevansdev on twitter.
36
+
37
+ Please also support the library by visiting our sponsors on http://www.chrisevansdev.com.
38
+
@@ -0,0 +1,376 @@
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
+ #include "integral.h"
13
+ #include "ipoint.h"
14
+ #include "utils.h"
15
+
16
+ #include <vector>
17
+
18
+ #include "responselayer.h"
19
+ #include "fasthessian.h"
20
+
21
+
22
+
23
+ using namespace std;
24
+ using namespace cv;
25
+
26
+ //-------------------------------------------------------
27
+
28
+ //! Constructor without image
29
+ FastHessian::FastHessian(std::vector<Ipoint> &ipts,
30
+ const int octaves, const int intervals, const int init_sample,
31
+ const float thresh)
32
+ : ipts(ipts), i_width(0), i_height(0)
33
+ {
34
+ // Save parameter set
35
+ saveParameters(octaves, intervals, init_sample, thresh);
36
+ }
37
+
38
+ //-------------------------------------------------------
39
+
40
+ //! Constructor with image
41
+ FastHessian::FastHessian(IplImage *img, std::vector<Ipoint> &ipts,
42
+ const int octaves, const int intervals, const int init_sample,
43
+ const float thresh)
44
+ : ipts(ipts), i_width(0), i_height(0)
45
+ {
46
+ // Save parameter set
47
+ saveParameters(octaves, intervals, init_sample, thresh);
48
+
49
+ // Set the current image
50
+ setIntImage(img);
51
+ }
52
+
53
+ //-------------------------------------------------------
54
+
55
+ FastHessian::~FastHessian()
56
+ {
57
+ for (unsigned int i = 0; i < responseMap.size(); ++i)
58
+ {
59
+ delete responseMap[i];
60
+ }
61
+ }
62
+
63
+ //-------------------------------------------------------
64
+
65
+ //! Save the parameters
66
+ void FastHessian::saveParameters(const int octaves, const int intervals,
67
+ const int init_sample, const float thresh)
68
+ {
69
+ // Initialise variables with bounds-checked values
70
+ this->octaves =
71
+ (octaves > 0 && octaves <= 4 ? octaves : OCTAVES);
72
+ this->intervals =
73
+ (intervals > 0 && intervals <= 4 ? intervals : INTERVALS);
74
+ this->init_sample =
75
+ (init_sample > 0 && init_sample <= 6 ? init_sample : INIT_SAMPLE);
76
+ this->thresh = (thresh >= 0 ? thresh : THRES);
77
+ }
78
+
79
+
80
+ //-------------------------------------------------------
81
+
82
+ //! Set or re-set the integral image source
83
+ void FastHessian::setIntImage(IplImage *img)
84
+ {
85
+ // Change the source image
86
+ this->img = img;
87
+
88
+ i_height = img->height;
89
+ i_width = img->width;
90
+ }
91
+
92
+ //-------------------------------------------------------
93
+
94
+ //! Find the image features and write into vector of features
95
+ void FastHessian::getIpoints()
96
+ {
97
+ // filter index map
98
+ static const int filter_map [OCTAVES][INTERVALS] = {{0,1,2,3}, {1,3,4,5}, {3,5,6,7}, {5,7,8,9}, {7,9,10,11}};
99
+
100
+ // Clear the vector of exisiting ipts
101
+ ipts.clear();
102
+
103
+ // Build the response map
104
+ buildResponseMap();
105
+
106
+ // Get the response layers
107
+ ResponseLayer *b, *m, *t;
108
+ for (int o = 0; o < octaves; ++o) for (int i = 0; i <= 1; ++i)
109
+ {
110
+ b = responseMap.at(filter_map[o][i]);
111
+ m = responseMap.at(filter_map[o][i+1]);
112
+ t = responseMap.at(filter_map[o][i+2]);
113
+
114
+ // loop over middle response layer at density of the most
115
+ // sparse layer (always top), to find maxima across scale and space
116
+ for (int r = 0; r < t->height; ++r)
117
+ {
118
+ for (int c = 0; c < t->width; ++c)
119
+ {
120
+ if (isExtremum(r, c, t, m, b))
121
+ {
122
+ interpolateExtremum(r, c, t, m, b);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ //-------------------------------------------------------
130
+
131
+ //! Build map of DoH responses
132
+ void FastHessian::buildResponseMap()
133
+ {
134
+ // Calculate responses for the first 4 octaves:
135
+ // Oct1: 9, 15, 21, 27
136
+ // Oct2: 15, 27, 39, 51
137
+ // Oct3: 27, 51, 75, 99
138
+ // Oct4: 51, 99, 147,195
139
+ // Oct5: 99, 195,291,387
140
+
141
+ // Deallocate memory and clear any existing response layers
142
+ for(unsigned int i = 0; i < responseMap.size(); ++i)
143
+ delete responseMap[i];
144
+ responseMap.clear();
145
+
146
+ // Get image attributes
147
+ int w = (i_width / init_sample);
148
+ int h = (i_height / init_sample);
149
+ int s = (init_sample);
150
+
151
+ // Calculate approximated determinant of hessian values
152
+ if (octaves >= 1)
153
+ {
154
+ responseMap.push_back(new ResponseLayer(w, h, s, 9));
155
+ responseMap.push_back(new ResponseLayer(w, h, s, 15));
156
+ responseMap.push_back(new ResponseLayer(w, h, s, 21));
157
+ responseMap.push_back(new ResponseLayer(w, h, s, 27));
158
+ }
159
+
160
+ if (octaves >= 2)
161
+ {
162
+ responseMap.push_back(new ResponseLayer(w/2, h/2, s*2, 39));
163
+ responseMap.push_back(new ResponseLayer(w/2, h/2, s*2, 51));
164
+ }
165
+
166
+ if (octaves >= 3)
167
+ {
168
+ responseMap.push_back(new ResponseLayer(w/4, h/4, s*4, 75));
169
+ responseMap.push_back(new ResponseLayer(w/4, h/4, s*4, 99));
170
+ }
171
+
172
+ if (octaves >= 4)
173
+ {
174
+ responseMap.push_back(new ResponseLayer(w/8, h/8, s*8, 147));
175
+ responseMap.push_back(new ResponseLayer(w/8, h/8, s*8, 195));
176
+ }
177
+
178
+ if (octaves >= 5)
179
+ {
180
+ responseMap.push_back(new ResponseLayer(w/16, h/16, s*16, 291));
181
+ responseMap.push_back(new ResponseLayer(w/16, h/16, s*16, 387));
182
+ }
183
+
184
+ // Extract responses from the image
185
+ for (unsigned int i = 0; i < responseMap.size(); ++i)
186
+ {
187
+ buildResponseLayer(responseMap[i]);
188
+ }
189
+ }
190
+
191
+ //-------------------------------------------------------
192
+
193
+ //! Calculate DoH responses for supplied layer
194
+ void FastHessian::buildResponseLayer(ResponseLayer *rl)
195
+ {
196
+ float *responses = rl->responses; // response storage
197
+ unsigned char *laplacian = rl->laplacian; // laplacian sign storage
198
+ int step = rl->step; // step size for this filter
199
+ int b = (rl->filter - 1) / 2 + 1; // border for this filter
200
+ int l = rl->filter / 3; // lobe for this filter (filter size / 3)
201
+ int w = rl->filter; // filter size
202
+ float inverse_area = 1.f/(w*w); // normalisation factor
203
+ float Dxx, Dyy, Dxy;
204
+
205
+ for(int r, c, ar = 0, index = 0; ar < rl->height; ++ar)
206
+ {
207
+ for(int ac = 0; ac < rl->width; ++ac, index++)
208
+ {
209
+ // get the image coordinates
210
+ r = ar * step;
211
+ c = ac * step;
212
+
213
+ // Compute response components
214
+ Dxx = BoxIntegral(img, r - l + 1, c - b, 2*l - 1, w)
215
+ - BoxIntegral(img, r - l + 1, c - l / 2, 2*l - 1, l)*3;
216
+ Dyy = BoxIntegral(img, r - b, c - l + 1, w, 2*l - 1)
217
+ - BoxIntegral(img, r - l / 2, c - l + 1, l, 2*l - 1)*3;
218
+ Dxy = + BoxIntegral(img, r - l, c + 1, l, l)
219
+ + BoxIntegral(img, r + 1, c - l, l, l)
220
+ - BoxIntegral(img, r - l, c - l, l, l)
221
+ - BoxIntegral(img, r + 1, c + 1, l, l);
222
+
223
+ // Normalise the filter responses with respect to their size
224
+ Dxx *= inverse_area;
225
+ Dyy *= inverse_area;
226
+ Dxy *= inverse_area;
227
+
228
+ // Get the determinant of hessian response & laplacian sign
229
+ responses[index] = (Dxx * Dyy - 0.81f * Dxy * Dxy);
230
+ laplacian[index] = (Dxx + Dyy >= 0 ? 1 : 0);
231
+
232
+ #ifdef RL_DEBUG
233
+ // create list of the image coords for each response
234
+ rl->coords.push_back(std::make_pair<int,int>(r,c));
235
+ #endif
236
+ }
237
+ }
238
+ }
239
+
240
+ //-------------------------------------------------------
241
+
242
+ //! Non Maximal Suppression function
243
+ int FastHessian::isExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b)
244
+ {
245
+ // bounds check
246
+ int layerBorder = (t->filter + 1) / (2 * t->step);
247
+ if (r <= layerBorder || r >= t->height - layerBorder || c <= layerBorder || c >= t->width - layerBorder)
248
+ return 0;
249
+
250
+ // check the candidate point in the middle layer is above thresh
251
+ float candidate = m->getResponse(r, c, t);
252
+ if (candidate < thresh)
253
+ return 0;
254
+
255
+ for (int rr = -1; rr <=1; ++rr)
256
+ {
257
+ for (int cc = -1; cc <=1; ++cc)
258
+ {
259
+ // if any response in 3x3x3 is greater candidate not maximum
260
+ if (
261
+ t->getResponse(r+rr, c+cc) >= candidate ||
262
+ ((rr != 0 || cc != 0) && m->getResponse(r+rr, c+cc, t) >= candidate) ||
263
+ b->getResponse(r+rr, c+cc, t) >= candidate
264
+ )
265
+ return 0;
266
+ }
267
+ }
268
+
269
+ return 1;
270
+ }
271
+
272
+ //-------------------------------------------------------
273
+
274
+ //! Interpolate scale-space extrema to subpixel accuracy to form an image feature.
275
+ void FastHessian::interpolateExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b)
276
+ {
277
+ // get the step distance between filters
278
+ // check the middle filter is mid way between top and bottom
279
+ int filterStep = (m->filter - b->filter);
280
+ assert(filterStep > 0 && t->filter - m->filter == m->filter - b->filter);
281
+
282
+ // Get the offsets to the actual location of the extremum
283
+ double xi = 0, xr = 0, xc = 0;
284
+ interpolateStep(r, c, t, m, b, &xi, &xr, &xc );
285
+
286
+ // If point is sufficiently close to the actual extremum
287
+ if( fabs( xi ) < 0.5f && fabs( xr ) < 0.5f && fabs( xc ) < 0.5f )
288
+ {
289
+ Ipoint ipt;
290
+ ipt.x = static_cast<float>((c + xc) * t->step);
291
+ ipt.y = static_cast<float>((r + xr) * t->step);
292
+ ipt.scale = static_cast<float>((0.1333f) * (m->filter + xi * filterStep));
293
+ ipt.laplacian = static_cast<int>(m->getLaplacian(r,c,t));
294
+ ipts.push_back(ipt);
295
+ }
296
+ }
297
+
298
+ //-------------------------------------------------------
299
+
300
+ //! Performs one step of extremum interpolation.
301
+ void FastHessian::interpolateStep(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b,
302
+ double* xi, double* xr, double* xc )
303
+ {
304
+ CvMat* dD, * H, * H_inv, X;
305
+ double x[3] = { 0 };
306
+
307
+ dD = deriv3D( r, c, t, m, b );
308
+ H = hessian3D( r, c, t, m, b );
309
+ H_inv = cvCreateMat( 3, 3, CV_64FC1 );
310
+ cvInvert( H, H_inv, CV_SVD );
311
+ cvInitMatHeader( &X, 3, 1, CV_64FC1, x, CV_AUTOSTEP );
312
+ cvGEMM( H_inv, dD, -1, NULL, 0, &X, 0 );
313
+
314
+ cvReleaseMat( &dD );
315
+ cvReleaseMat( &H );
316
+ cvReleaseMat( &H_inv );
317
+
318
+ *xi = x[2];
319
+ *xr = x[1];
320
+ *xc = x[0];
321
+ }
322
+
323
+ //-------------------------------------------------------
324
+
325
+ //! Computes the partial derivatives in x, y, and scale of a pixel.
326
+ CvMat* FastHessian::deriv3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b)
327
+ {
328
+ CvMat* dI;
329
+ double dx, dy, ds;
330
+
331
+ dx = (m->getResponse(r, c + 1, t) - m->getResponse(r, c - 1, t)) / 2.0;
332
+ dy = (m->getResponse(r + 1, c, t) - m->getResponse(r - 1, c, t)) / 2.0;
333
+ ds = (t->getResponse(r, c) - b->getResponse(r, c, t)) / 2.0;
334
+
335
+ dI = cvCreateMat( 3, 1, CV_64FC1 );
336
+ cvmSet( dI, 0, 0, dx );
337
+ cvmSet( dI, 1, 0, dy );
338
+ cvmSet( dI, 2, 0, ds );
339
+
340
+ return dI;
341
+ }
342
+
343
+ //-------------------------------------------------------
344
+
345
+ //! Computes the 3D Hessian matrix for a pixel.
346
+ CvMat* FastHessian::hessian3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b)
347
+ {
348
+ CvMat* H;
349
+ double v, dxx, dyy, dss, dxy, dxs, dys;
350
+
351
+ v = m->getResponse(r, c, t);
352
+ dxx = m->getResponse(r, c + 1, t) + m->getResponse(r, c - 1, t) - 2 * v;
353
+ dyy = m->getResponse(r + 1, c, t) + m->getResponse(r - 1, c, t) - 2 * v;
354
+ dss = t->getResponse(r, c) + b->getResponse(r, c, t) - 2 * v;
355
+ dxy = ( m->getResponse(r + 1, c + 1, t) - m->getResponse(r + 1, c - 1, t) -
356
+ m->getResponse(r - 1, c + 1, t) + m->getResponse(r - 1, c - 1, t) ) / 4.0;
357
+ dxs = ( t->getResponse(r, c + 1) - t->getResponse(r, c - 1) -
358
+ b->getResponse(r, c + 1, t) + b->getResponse(r, c - 1, t) ) / 4.0;
359
+ dys = ( t->getResponse(r + 1, c) - t->getResponse(r - 1, c) -
360
+ b->getResponse(r + 1, c, t) + b->getResponse(r - 1, c, t) ) / 4.0;
361
+
362
+ H = cvCreateMat( 3, 3, CV_64FC1 );
363
+ cvmSet( H, 0, 0, dxx );
364
+ cvmSet( H, 0, 1, dxy );
365
+ cvmSet( H, 0, 2, dxs );
366
+ cvmSet( H, 1, 0, dxy );
367
+ cvmSet( H, 1, 1, dyy );
368
+ cvmSet( H, 1, 2, dys );
369
+ cvmSet( H, 2, 0, dxs );
370
+ cvmSet( H, 2, 1, dys );
371
+ cvmSet( H, 2, 2, dss );
372
+
373
+ return H;
374
+ }
375
+
376
+ //-------------------------------------------------------