Main MRPT website > C++ reference for MRPT 1.9.9
CFeatureExtraction_FASTER.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "vision-precomp.h" // Precompiled headers
11 
13 
14 // Universal include for all versions of OpenCV
15 #include <mrpt/otherlibs/do_opencv_includes.h>
16 
17 #if MRPT_HAS_OPENCV
19 #endif
20 
21 using namespace mrpt;
22 using namespace mrpt::vision;
23 using namespace mrpt::system;
24 using namespace mrpt::utils;
25 using namespace std;
26 
27 // ------------ SSE2-optimized implementations of FASTER -------------
29  const CImage& img, TSimpleFeatureList& corners, const int threshold,
30  bool append_to_list, uint8_t octave,
31  std::vector<size_t>* out_feats_index_by_row)
32 {
33 #if MRPT_HAS_OPENCV
34  const IplImage* IPL = img.getAs<IplImage>();
35  ASSERTDEB_(IPL && IPL->nChannels == 1)
36  if (!append_to_list) corners.clear();
37 
39  IPL, corners, threshold, octave, out_feats_index_by_row);
40 #else
41  THROW_EXCEPTION("MRPT built without OpenCV support!")
42 #endif
43 }
45  const CImage& img, TSimpleFeatureList& corners, const int threshold,
46  bool append_to_list, uint8_t octave,
47  std::vector<size_t>* out_feats_index_by_row)
48 {
49 #if MRPT_HAS_OPENCV
50  const IplImage* IPL = img.getAs<IplImage>();
51  ASSERTDEB_(IPL && IPL->nChannels == 1)
52  if (!append_to_list) corners.clear();
53 
55  IPL, corners, threshold, octave, out_feats_index_by_row);
56 #else
57  THROW_EXCEPTION("MRPT built without OpenCV support!")
58 #endif
59 }
61  const CImage& img, TSimpleFeatureList& corners, const int threshold,
62  bool append_to_list, uint8_t octave,
63  std::vector<size_t>* out_feats_index_by_row)
64 {
65 #if MRPT_HAS_OPENCV
66  const IplImage* IPL = img.getAs<IplImage>();
67  ASSERTDEB_(IPL && IPL->nChannels == 1)
68  if (!append_to_list) corners.clear();
69 
71  IPL, corners, threshold, octave, out_feats_index_by_row);
72 #else
73  THROW_EXCEPTION("MRPT built without OpenCV support!")
74 #endif
75 }
76 
77 /************************************************************************************************
78 * extractFeaturesFASTER
79 **
80 ************************************************************************************************/
81 // N_fast = 9, 10, 12
83  const int N_fast, const mrpt::utils::CImage& inImg, CFeatureList& feats,
84  unsigned int init_ID, unsigned int nDesiredFeatures,
85  const TImageROI& ROI) const
86 {
87  MRPT_UNUSED_PARAM(ROI);
89 
90 #if MRPT_HAS_OPENCV
91  // Make sure we operate on a gray-scale version of the image:
92  const CImage inImg_gray(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
93 
94  const IplImage* IPL = inImg_gray.getAs<IplImage>();
95 
96  TSimpleFeatureList corners;
97  TFeatureType type_of_this_feature;
98 
99  switch (N_fast)
100  {
101  case 9:
103  IPL, corners, options.FASTOptions.threshold, 0, nullptr);
104  type_of_this_feature = featFASTER9;
105  break;
106  case 10:
108  IPL, corners, options.FASTOptions.threshold, 0, nullptr);
109  type_of_this_feature = featFASTER10;
110  break;
111  case 12:
113  IPL, corners, options.FASTOptions.threshold, 0, nullptr);
114  type_of_this_feature = featFASTER12;
115  break;
116  default:
118  "Only the 9,10,12 FASTER detectors are implemented.")
119  break;
120  };
121 
122  // *All* the features have been extracted.
123  const size_t N = corners.size();
124 
125  // Now:
126  // 1) Sort them by "response": It's ~100 times faster to sort a list of
127  // indices "sorted_indices" than sorting directly the actual list of
128  // features "corners"
129  std::vector<size_t> sorted_indices(N);
130  for (size_t i = 0; i < N; i++) sorted_indices[i] = i;
131 
132  // Use KLT response
133  if (options.FASTOptions.use_KLT_response ||
134  nDesiredFeatures != 0 // If the user wants us to limit the number of
135  // features, we need to do it according to some
136  // quality measure
137  )
138  {
139  const int KLT_half_win = 4;
140  const int max_x = inImg_gray.getWidth() - 1 - KLT_half_win;
141  const int max_y = inImg_gray.getHeight() - 1 - KLT_half_win;
142 
143  for (size_t i = 0; i < N; i++)
144  {
145  const int x = corners[i].pt.x;
146  const int y = corners[i].pt.y;
147  if (x > KLT_half_win && y > KLT_half_win && x <= max_x &&
148  y <= max_y)
149  corners[i].response =
150  inImg_gray.KLT_response(x, y, KLT_half_win);
151  else
152  corners[i].response = -100;
153  }
154 
155  std::sort(
156  sorted_indices.begin(), sorted_indices.end(),
158  }
159  else
160  {
161  for (size_t i = 0; i < N; i++) corners[i].response = 0;
162  }
163 
164  // 2) Filter by "min-distance" (in options.FASTOptions.min_distance)
165  // 3) Convert to MRPT CFeatureList format.
166  // Steps 2 & 3 are done together in the while() below.
167  // The "min-distance" filter is done by means of a 2D binary matrix where
168  // each cell is marked when one
169  // feature falls within it. This is not exactly the same than a pure
170  // "min-distance" but is pretty close
171  // and for large numbers of features is much faster than brute force search
172  // of kd-trees.
173  // (An intermediate approach would be the creation of a mask image updated
174  // for each accepted feature, etc.)
175 
176  const bool do_filter_min_dist = options.FASTOptions.min_distance > 1;
177 
178  // Used half the min-distance since we'll later mark as occupied the ranges
179  // [i-1,i+1] for a feature at "i"
180  const unsigned int occupied_grid_cell_size =
181  options.FASTOptions.min_distance / 2.0;
182  const float occupied_grid_cell_size_inv = 1.0f / occupied_grid_cell_size;
183 
184  unsigned int grid_lx =
185  !do_filter_min_dist
186  ? 1
187  : (unsigned int)(1 + inImg.getWidth() * occupied_grid_cell_size_inv);
188  unsigned int grid_ly =
189  !do_filter_min_dist
190  ? 1
191  : (unsigned int)(1 + inImg.getHeight() * occupied_grid_cell_size_inv);
192 
193  mrpt::math::CMatrixBool occupied_sections(
194  grid_lx, grid_ly); // See the comments above for an explanation.
195  occupied_sections.fillAll(false);
196 
197  unsigned int nMax =
198  (nDesiredFeatures != 0 && N > nDesiredFeatures) ? nDesiredFeatures : N;
199  const int offset = (int)this->options.patchSize / 2 + 1;
200  const int size_2 = options.patchSize / 2;
201  const size_t imgH = inImg.getHeight();
202  const size_t imgW = inImg.getWidth();
203  unsigned int i = 0;
204  unsigned int cont = 0;
205  TFeatureID nextID = init_ID;
206 
207  if (!options.addNewFeatures) feats.clear();
208 
209  while (cont != nMax && i != N)
210  {
211  // Take the next feature fromt the ordered list of good features:
212  const TSimpleFeature& feat = corners[sorted_indices[i]];
213  i++;
214 
215  // Patch out of the image??
216  const int xBorderInf = feat.pt.x - size_2;
217  const int xBorderSup = feat.pt.x + size_2;
218  const int yBorderInf = feat.pt.y - size_2;
219  const int yBorderSup = feat.pt.y + size_2;
220 
221  if (!(xBorderSup < (int)imgW && xBorderInf > 0 &&
222  yBorderSup < (int)imgH && yBorderInf > 0))
223  continue; // nope, skip.
224 
225  if (do_filter_min_dist)
226  {
227  // Check the min-distance:
228  const size_t section_idx_x =
229  size_t(feat.pt.x * occupied_grid_cell_size_inv);
230  const size_t section_idx_y =
231  size_t(feat.pt.y * occupied_grid_cell_size_inv);
232 
233  if (occupied_sections(section_idx_x, section_idx_y))
234  continue; // Already occupied! skip.
235 
236  // Mark section as occupied
237  occupied_sections.set_unsafe(section_idx_x, section_idx_y, true);
238  if (section_idx_x > 0)
239  occupied_sections.set_unsafe(
240  section_idx_x - 1, section_idx_y, true);
241  if (section_idx_y > 0)
242  occupied_sections.set_unsafe(
243  section_idx_x, section_idx_y - 1, true);
244  if (section_idx_x < grid_lx - 1)
245  occupied_sections.set_unsafe(
246  section_idx_x + 1, section_idx_y, true);
247  if (section_idx_y < grid_ly - 1)
248  occupied_sections.set_unsafe(
249  section_idx_x, section_idx_y + 1, true);
250  }
251 
252  // All tests passed: add new feature:
253  CFeature::Ptr ft = mrpt::make_aligned_shared<CFeature>();
254  ft->type = type_of_this_feature;
255  ft->ID = nextID++;
256  ft->x = feat.pt.x;
257  ft->y = feat.pt.y;
258  ft->response = feat.response;
259  ft->orientation = 0;
260  ft->scale = 1;
261  ft->patchSize = options.patchSize; // The size of the feature patch
262 
263  if (options.patchSize > 0)
264  {
265  inImg.extract_patch(
266  ft->patch, round(ft->x) - offset, round(ft->y) - offset,
267  options.patchSize,
268  options.patchSize); // Image patch surronding the feature
269  }
270  feats.push_back(ft);
271  ++cont;
272  }
273 
274 #endif
275  MRPT_END
276 }
std::shared_ptr< CFeature > Ptr
Definition: CFeature.h:58
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
void fast_corner_detect_12(const IplImage *I, mrpt::vision::TSimpleFeatureList &corners, int barrier, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
Declares a matrix of booleans (non serializable).
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
FASTER-9 detector, Edward Rosten&#39;s libcvd implementation optimized for SSE2.
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
#define THROW_EXCEPTION(msg)
GLintptr offset
Definition: glext.h:3925
void extractFeaturesFASTER_N(const int N, const mrpt::utils::CImage &img, CFeatureList &feats, unsigned int init_ID=0, unsigned int nDesiredFeatures=0, const TImageROI &ROI=TImageROI()) const
Edward&#39;s "FASTER & Better" detector, N=9,10,12.
STL namespace.
static void detectFeatures_SSE2_FASTER12(const mrpt::utils::CImage &img, TSimpleFeatureList &corners, const int threshold=20, bool append_to_list=false, uint8_t octave=0, std::vector< size_t > *out_feats_index_by_row=nullptr)
Just like detectFeatures_SSE2_FASTER9() for another version of the detector.
void fast_corner_detect_9(const IplImage *I, mrpt::vision::TSimpleFeatureList &corners, int barrier, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
unsigned char uint8_t
Definition: rptypes.h:41
A helper struct to sort keypoints by their response: It can be used with these types: ...
A structure for defining a ROI within an image.
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
#define MRPT_END
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
static void detectFeatures_SSE2_FASTER10(const mrpt::utils::CImage &img, TSimpleFeatureList &corners, const int threshold=20, bool append_to_list=false, uint8_t octave=0, std::vector< size_t > *out_feats_index_by_row=nullptr)
Just like detectFeatures_SSE2_FASTER9() for another version of the detector.
GLint GLvoid * img
Definition: glext.h:3763
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
FASTER-9 detector, Edward Rosten&#39;s libcvd implementation optimized for SSE2.
Classes for computer vision, detectors, features, etc.
FASTER-9 detector, Edward Rosten&#39;s libcvd implementation optimized for SSE2.
uint64_t TFeatureID
Definition of a feature ID.
void set_unsafe(size_t row, size_t col, const T &v)
Fast but unsafe method to write a value in the matrix.
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:305
static void detectFeatures_SSE2_FASTER9(const mrpt::utils::CImage &img, TSimpleFeatureList &corners, const int threshold=20, bool append_to_list=false, uint8_t octave=0, std::vector< size_t > *out_feats_index_by_row=nullptr)
A SSE2-optimized implementation of FASTER-9 (requires img to be grayscale).
TFeatureType
Types of features - This means that the point has been detected with this algorithm, which is independent of additional descriptors a feature may also have.
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
pixel_coords_t pt
Coordinates in the image.
float response
A measure of the "goodness" of the feature (typically, the KLT_response value)
void extract_patch(CImage &patch, const unsigned int col=0, const unsigned int row=0, const unsigned int width=1, const unsigned int height=1) const
Extract a patch from this image, saveing it into "patch" (its previous contents will be overwritten)...
Definition: CImage.cpp:1367
A simple structure for representing one image feature (without descriptor nor patch) - This is the te...
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLint x
Definition: glext.h:3538
void fast_corner_detect_10(const IplImage *I, mrpt::vision::TSimpleFeatureList &corners, int barrier, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
void push_back(const CFeature::Ptr &f)
Definition: CFeature.h:399
void fillAll(const T &val)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019