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,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
+ //-------------------------------------------------------