PICCANTE  0.4
The hottest HDR imaging library!
susan_corner_detector.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_FEATURES_MATCHING_SUSAN_CORNER_DETECTOR_HPP
19 #define PIC_FEATURES_MATCHING_SUSAN_CORNER_DETECTOR_HPP
20 
21 #include "../util/vec.hpp"
22 #include "../util/std_util.hpp"
23 #include "../image.hpp"
24 #include "../filtering/filter_luminance.hpp"
25 #include "../filtering/filter_gaussian_2d.hpp"
26 
27 #include "../features_matching/general_corner_detector.hpp"
28 
29 #ifndef PIC_DISABLE_EIGEN
30 
31 #ifndef PIC_EIGEN_NOT_BUNDLED
32  #include "../externals/Eigen/Dense"
33 #else
34  #include <Eigen/Dense>
35 #endif
36 
37 #endif
38 
39 namespace pic {
40 
41 #ifndef PIC_DISABLE_EIGEN
42 
47 {
48 protected:
51 
52  float sigma, threshold;
54 
55  void release()
56  {
57  lum = delete_s(lum);
59  }
60 
61 public:
66  {
67  lum_flt = NULL;
68 
69  bComputeThreshold = true;
70  update();
71  }
72 
74  {
75  release();
76  }
77 
85  void update(float sigma = 1.0f, int radius_maxima = 5, int radius = 3, float threshold = 0.001f)
86  {
87  this->sigma = sigma > 0.0f ? sigma : 1.0f;
88  this->radius = radius > 0 ? radius : 3;
89  this->threshold = threshold > 0.0f ? threshold : 0.001f;
90  this->radius_maxima = radius_maxima > 0 ? radius_maxima : 5;
91  }
92 
98  void execute(Image *img, std::vector< Eigen::Vector2f > *corners)
99  {
100  if(img == NULL || corners == NULL) {
101  return;
102  }
103 
104  if(img->channels == 1) {
105  bLum = false;
106  lum = img;
107  } else {
108  bLum = true;
110  }
111 
112  corners->clear();
113 
114  std::vector< Eigen::Vector3f > corners_w_quality;
115 
116  //filter the input image
117  FilterGaussian2D flt(sigma);
118  lum_flt = flt.Process(Single(lum), NULL);
119 
120  //"rasterizing" a circle
121  std::vector< int > x, y;
122  int radius_sq = radius * radius;
123  for(int i=-radius; i<=radius; i++) {
124  int i_sq = i * i;
125  for(int j=-radius; j<=radius; j++) {
126 
127  if((j == 0) && (i == 0)) {
128  continue;
129  }
130 
131  int r_sq = i_sq + j * j;
132  if(r_sq <= radius_sq){
133  x.push_back(j);
134  y.push_back(i);
135  }
136  }
137  }
138 
139  int width = lum_flt->width;
140  int height = lum_flt->height;
141 
142  float C = float(x.size());
143 
144  float t = 0.05f; //depends on image noise
145 
146  float g = C * 0.5f; //geometric constant for determing corners
147 
148  Image R(1,width, height, 1);
149  R.setZero();
150  for(int i = radius; i < (height - radius - 1); i++) {
151  for(int j = radius; j < (width - radius - 1); j++) {
152 
153  int ind = i * width + j;
154 
155  float sum = 0.0f;
156 
157  for(unsigned int k = 0; k < x.size(); k++) {
158  int ind_c = (i + y[k]) * width + (j + x[k]);
159 
160  float diff = (lum_flt->data[ind_c] - lum_flt->data[ind]) / t;
161  float diff_2 = diff * diff;
162  float diff_4 = diff_2 * diff_2;
163  float diff_6 = diff_4 * diff_2;
164 
165  sum += expf(-diff_6);
166  }
167 
168  if(sum < g) {
169  R.data[ind] = g - sum;
170  }
171  }
172  }
173 
174  //non-maximal supression
175  int side = radius_maxima * 2 + 1;
176  int *indices = new int [side * side];
177 
178  for(int i = radius_maxima; i< (height - radius_maxima - 1); i++) {
179 
180  int tmp = i * width;
181 
182  for(int j = radius_maxima; j < (width - radius_maxima - 1); j++) {
183  int ind = tmp + j;
184 
185  if(R.data[ind] <= 0.0f) {
186  continue;
187  }
188 
189  indices[0] = ind;
190  int counter = 1;
191 
192  for(int k = -radius_maxima; k <= radius_maxima; k++) {
193  int yy = CLAMP(i + k, height);
194 
195  for(int l = -radius_maxima; l <= radius_maxima; l++) {
196 
197  if((l == 0) && (k == 0)) {
198  continue;
199  }
200 
201  int xx = CLAMP(j + l, width);
202 
203  ind = yy * width + xx;
204 
205  if(R.data[ind]>0.0f){
206  indices[counter] = ind;
207  counter++;
208  }
209 
210  }
211  }
212 
213  //are other corners near-by?
214  if(counter > 1) {
215  //find the maximum value
216  float R_value = R.data[indices[0]];
217  int index = 0;
218 
219  for(int k = 1; k < counter; k++){
220  if(R.data[indices[k]] > R_value) {
221  R_value = R.data[indices[k]];
222  index = k;
223  }
224  }
225 
226  if(index == 0){
227  corners_w_quality.push_back(Eigen::Vector3f (float(j), float(i), 1.0f) );
228  }
229  } else {
230  corners_w_quality.push_back(Eigen::Vector3f (float(j), float(i), 1.0f) );
231  }
232  }
233  }
234 
235  sortCornersAndTransfer(&corners_w_quality, corners);
236 
237  if(indices != NULL) {
238  delete[] indices;
239  indices = NULL;
240  }
241  }
242 };
243 
244 #endif
245 
246 } // end namespace pic
247 
248 #endif /* PIC_FEATURES_MATCHING_SUSAN_CORNER_DETECTOR_HPP */
249 
Definition: filter_luminance.hpp:28
~SusanCornerDetector()
Definition: susan_corner_detector.hpp:73
bool bComputeThreshold
Definition: susan_corner_detector.hpp:50
float * data
data is the main buffer where pixel values are stored.
Definition: image.hpp:91
void setZero()
setZero sets data to 0.0f.
int channels
Definition: image.hpp:80
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
int radius_maxima
Definition: susan_corner_detector.hpp:53
Image * lum_flt
Definition: susan_corner_detector.hpp:49
int radius
Definition: susan_corner_detector.hpp:53
void execute(Image *img, std::vector< Eigen::Vector2f > *corners)
execute
Definition: susan_corner_detector.hpp:98
float sigma
Definition: susan_corner_detector.hpp:52
float threshold
Definition: susan_corner_detector.hpp:52
static Image * execute(Image *imgIn, Image *imgOut, LUMINANCE_TYPE type=LT_CIE_LUMINANCE)
execute
Definition: filter_luminance.hpp:166
Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter_npasses.hpp:310
The GeneralCornerDetector class.
Definition: general_corner_detector.hpp:42
SusanCornerDetector()
SusanCornerDetector.
Definition: susan_corner_detector.hpp:65
The Image class stores an image as buffer of float.
Definition: image.hpp:60
bool bLum
Definition: general_corner_detector.hpp:46
The SusanCornerDetector class.
Definition: susan_corner_detector.hpp:46
PIC_INLINE ImageVec Single(Image *img)
Single creates an std::vector which contains img; this is for filters input.
Definition: image_vec.hpp:36
Definition: bilateral_separation.hpp:25
Image * lum
Definition: general_corner_detector.hpp:45
#define CLAMP(x, a)
Definition: math.hpp:77
The FilterGaussian2D class.
Definition: filter_gaussian_2d.hpp:31
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
static void sortCornersAndTransfer(std::vector< Eigen::Vector3f > *corners, std::vector< Eigen::Vector2f > *cornersOut, int nBestPoints=-1, bool bDescend=true)
sortCornersAndTransfer
Definition: general_corner_detector.hpp:127
void release()
Definition: susan_corner_detector.hpp:55
void update(float sigma=1.0f, int radius_maxima=5, int radius=3, float threshold=0.001f)
update
Definition: susan_corner_detector.hpp:85