PICCANTE  0.4
The hottest HDR imaging library!
fast_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_FAST_CORNER_DETECTOR_HPP
19 #define PIC_FEATURES_MATCHING_FAST_CORNER_DETECTOR_HPP
20 
21 #include "../util/vec.hpp"
22 #include "../util/std_util.hpp"
23 
24 #include "../image.hpp"
25 #include "../filtering/filter_luminance.hpp"
26 #include "../filtering/filter_gaussian_2d.hpp"
27 
28 #include "../features_matching/general_corner_detector.hpp"
29 
30 #ifndef PIC_DISABLE_EIGEN
31 
32 #ifndef PIC_EIGEN_NOT_BUNDLED
33  #include "../externals/Eigen/Dense"
34 #else
35  #include <Eigen/Dense>
36 #endif
37 
38 #endif
39 
40 namespace pic {
41 
42 #ifndef PIC_DISABLE_EIGEN
43 
45 {
46 protected:
49 
50  float sigma, threshold;
51  int radius;
52 
53 public:
60  FastCornerDetector(float sigma = 1.0f, int radius = 1, float threshold = 0.001f) : GeneralCornerDetector()
61  {
62  bexecuteThreshold = true;
63 
64  lum_flt = NULL;
65 
67  }
68 
70  {
71  lum = delete_s(lum);
73  }
74 
81  void update(float sigma = 1.0f, int radius = 1, float threshold = 0.001f)
82  {
83  this->sigma = sigma > 0.0f ? sigma : 1.0f;
84  this->radius = radius > 0 ? radius : 1;
85  this->threshold = threshold > 0.001f ? threshold : 0.001f;
86  }
87 
93  void execute(Image *img, std::vector< Eigen::Vector2f > *corners)
94  {
95  if(img == NULL || corners == NULL) {
96  return;
97  }
98 
99  if(img->channels == 1) {
100  bLum = false;
101  lum = img;
102  } else {
103  bLum = true;
105  }
106 
107  corners->clear();
108 
109  std::vector< Eigen::Vector3f > corners_w_quality;
110 
111  //filter the input image
112  FilterGaussian2D flt(sigma);
113  lum_flt = flt.Process(Single(lum), lum_flt);
114 
115  int x[] = {0, 1, 2, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -2, -1};
116  int y[] = {3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -2, -1, 0, 1, 2, 3};
117 
118  int width = lum_flt->width;
119  int height = lum_flt->height;
120 
121  bool *corners_map = new bool[width * height];
122 
123  memset(corners_map, 0, sizeof(bool) * width * height);
124 
125  Image V(1,width, height, 1);
126  V.setZero();
127 
128  for(int i=3; i<(height - 3); i++) {
129  for(int j=3; j<(width - 3); j++) {
130  int ind = i * width + j;
131 
132  float p = lum_flt->data[ind];
133 
134  bool bDark[16];
135  bool bBright[16];
136  float v[16];
137 
138  float sum = p;
139 
140  for(int k=0; k<16; k++){
141  float value = (*lum_flt)(j + x[k], i + y[k])[0];
142  v[k] = value;
143  sum += value;
144  }
145 
146  //compute the threshold
147  float thr;
148  if(bexecuteThreshold) {
149  thr = 0.2f * sum / 16.0f;
150  thr = (thr > 1e-9f ) ? thr : threshold;
151 
152  } else {
153  thr = threshold;
154  }
155 
156  //test
157  float p_thr_dark = p - thr;
158  float p_thr_bright = p + thr;
159 
160  for(int k=0; k<16; k++){
161  bDark[k] = v[k] <= p_thr_dark;
162  bBright[k] = v[k] >= p_thr_bright;
163  }
164 
165  //first test: 0, 4, 8, 12
166  int cDark = bDark[0] + bDark[4] + bDark[8] + bDark[12];
167  int cBright = bBright[0] + bBright[4] + bBright[8] + bBright[12];
168 
169  if((cDark < 3) && (cBright < 3) ){
170  //corners_map[ind] = false;
171  continue;
172  }
173 
174  //second test: check for 12 continuous true values in bDark or cBright
175  int counter_dark = 0;
176  int counter_bright = 0;
177 
178  //corners_map[ind] = false;
179  for(int k=0; k<16; k++){
180  if(bDark[k]){
181  counter_dark++;
182  } else {
183  counter_dark = 0;
184  }
185 
186  if(bBright[k]){
187  counter_bright++;
188  } else {
189  counter_dark = 0;
190  }
191 
192  if((counter_bright > 11) || (counter_dark > 11)) {
193  corners_map[ind] = true;
194 
195  //Computing V function
196  float V_dark = 0.0f;
197  float V_bright = 0.0f;
198  for(int k=0; k<16; k++){
199  if(bDark[k]) {
200  V_bright += fabsf(v[k] - p) - thr;
201  }
202 
203  if(bBright[k]) {
204  V_dark += fabsf(p - v[k]) - thr;
205  }
206  }
207  V.data[ind] = MAX(V_bright, V_dark);
208 
209  break;
210  }
211  }
212  }
213  }
214 
215  //non-maximal supression
216  int side = radius * 2 + 1;
217  int *indices = new int[side * side];
218 
219  for(int i=3; i<(height - 3); i++) {
220  for(int j=3; j<(width - 3); j++) {
221  int ind = i * width + j;
222 
223  if(!corners_map[ind]){
224  continue;
225  }
226 
227  indices[0] = ind;
228  int counter = 1;
229 
230  for(int k = -radius; k <= radius; k++) {
231  int yy = CLAMP(i + k, height);
232 
233  for(int l = -radius; l <= radius; l++) {
234 
235  if((l == 0)&&(k == 0)) {
236  continue;
237  }
238 
239  int xx = CLAMP(j + l, width);
240 
241  ind = yy * width + xx;
242 
243  if(corners_map[ind]){
244  indices[counter] = ind;
245  counter++;
246  }
247 
248  }
249  }
250 
251  //are other corners near-by?
252  if(counter > 1) {
253  //finding the maximum value
254  float V_value = V.data[indices[0]];
255  int index = 0;
256 
257  for(int k=1; k<counter; k++){
258  if(V.data[indices[k]] > V_value) {
259  V_value = V.data[indices[k]];
260  index = k;
261  }
262  }
263 
264  if(index == 0){
265  corners_w_quality.push_back(Eigen::Vector3f (float(j), float(i), 1.0f) );
266  }
267  } else {
268  corners_w_quality.push_back(Eigen::Vector3f (float(j), float(i), 1.0f) );
269  }
270 
271  }
272  }
273 
274  sortCornersAndTransfer(&corners_w_quality, corners);
275 
276  delete[] indices;
277  }
278 };
279 
280 #endif
281 
282 } // end namespace pic
283 
284 #endif /* PIC_FEATURES_MATCHING_FAST_CORNER_DETECTOR_HPP */
285 
Definition: filter_luminance.hpp:28
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
~FastCornerDetector()
Definition: fast_corner_detector.hpp:69
bool bexecuteThreshold
Definition: fast_corner_detector.hpp:48
void update(float sigma=1.0f, int radius=1, float threshold=0.001f)
update
Definition: fast_corner_detector.hpp:81
FastCornerDetector(float sigma=1.0f, int radius=1, float threshold=0.001f)
FastCornerDetector.
Definition: fast_corner_detector.hpp:60
float sigma
Definition: fast_corner_detector.hpp:50
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
The Image class stores an image as buffer of float.
Definition: image.hpp:60
bool bLum
Definition: general_corner_detector.hpp:46
int radius
Definition: fast_corner_detector.hpp:51
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
Definition: fast_corner_detector.hpp:44
Image * lum
Definition: general_corner_detector.hpp:45
#define CLAMP(x, a)
Definition: math.hpp:77
#define MAX(a, b)
Definition: math.hpp:73
The FilterGaussian2D class.
Definition: filter_gaussian_2d.hpp:31
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
float threshold
Definition: fast_corner_detector.hpp:50
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 execute(Image *img, std::vector< Eigen::Vector2f > *corners)
execute
Definition: fast_corner_detector.hpp:93
Image * lum_flt
Definition: fast_corner_detector.hpp:47