Main MRPT website > C++ reference for MRPT 1.5.6
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 
18 #if MRPT_HAS_OPENCV
20 #endif
21 
22 using namespace mrpt;
23 using namespace mrpt::vision;
24 using namespace mrpt::system;
25 using namespace mrpt::utils;
26 using namespace std;
27 
28 
29 // ------------ SSE2-optimized implementations of FASTER -------------
30 void CFeatureExtraction::detectFeatures_SSE2_FASTER9(const CImage &img, TSimpleFeatureList & corners, const int threshold, bool append_to_list, uint8_t octave,std::vector<size_t> * out_feats_index_by_row)
31 {
32 #if MRPT_HAS_OPENCV
33  const IplImage *IPL = img.getAs<IplImage>();
34  ASSERTDEB_(IPL && IPL->nChannels==1)
35  if (!append_to_list) corners.clear();
36 
37  fast_corner_detect_9 (IPL,corners,threshold,octave,out_feats_index_by_row);
38 #else
39  THROW_EXCEPTION("MRPT built without OpenCV support!")
40 #endif
41 }
42 void CFeatureExtraction::detectFeatures_SSE2_FASTER10(const CImage &img, TSimpleFeatureList & corners, const int threshold, bool append_to_list, uint8_t octave,std::vector<size_t> * out_feats_index_by_row)
43 {
44 #if MRPT_HAS_OPENCV
45  const IplImage *IPL = img.getAs<IplImage>();
46  ASSERTDEB_(IPL && IPL->nChannels==1)
47  if (!append_to_list) corners.clear();
48 
49  fast_corner_detect_10 (IPL,corners,threshold,octave,out_feats_index_by_row);
50 #else
51  THROW_EXCEPTION("MRPT built without OpenCV support!")
52 #endif
53 }
54 void CFeatureExtraction::detectFeatures_SSE2_FASTER12(const CImage &img, TSimpleFeatureList & corners, const int threshold, bool append_to_list, uint8_t octave,std::vector<size_t> * out_feats_index_by_row)
55 {
56 #if MRPT_HAS_OPENCV
57  const IplImage *IPL = img.getAs<IplImage>();
58  ASSERTDEB_(IPL && IPL->nChannels==1)
59  if (!append_to_list) corners.clear();
60 
61  fast_corner_detect_12 (IPL,corners,threshold,octave,out_feats_index_by_row);
62 #else
63  THROW_EXCEPTION("MRPT built without OpenCV support!")
64 #endif
65 }
66 
67 /************************************************************************************************
68 * extractFeaturesFASTER *
69 ************************************************************************************************/
70 // N_fast = 9, 10, 12
72  const int N_fast,
73  const mrpt::utils::CImage & inImg,
74  CFeatureList & feats,
75  unsigned int init_ID,
76  unsigned int nDesiredFeatures,
77  const TImageROI & ROI ) const
78 {
79  MRPT_UNUSED_PARAM(ROI);
81 
82 #if MRPT_HAS_OPENCV
83  // Make sure we operate on a gray-scale version of the image:
84  const CImage inImg_gray( inImg, FAST_REF_OR_CONVERT_TO_GRAY );
85 
86  const IplImage *IPL = inImg_gray.getAs<IplImage>();
87 
88  TSimpleFeatureList corners;
89  TFeatureType type_of_this_feature;
90 
91  switch (N_fast)
92  {
93  case 9: fast_corner_detect_9 (IPL,corners, options.FASTOptions.threshold, 0, NULL); type_of_this_feature=featFASTER9; break;
94  case 10: fast_corner_detect_10(IPL,corners, options.FASTOptions.threshold, 0, NULL); type_of_this_feature=featFASTER10; break;
95  case 12: fast_corner_detect_12(IPL,corners, options.FASTOptions.threshold, 0, NULL); type_of_this_feature=featFASTER12; break;
96  default:
97  THROW_EXCEPTION("Only the 9,10,12 FASTER detectors are implemented.")
98  break;
99  };
100 
101  // *All* the features have been extracted.
102  const size_t N = corners.size();
103 
104  // Now:
105  // 1) Sort them by "response": It's ~100 times faster to sort a list of
106  // indices "sorted_indices" than sorting directly the actual list of features "corners"
107  std::vector<size_t> sorted_indices(N);
108  for (size_t i=0;i<N;i++) sorted_indices[i]=i;
109 
110  // Use KLT response
111  if (options.FASTOptions.use_KLT_response ||
112  nDesiredFeatures!=0 // If the user wants us to limit the number of features, we need to do it according to some quality measure
113  )
114  {
115  const int KLT_half_win = 4;
116  const int max_x = inImg_gray.getWidth() - 1 - KLT_half_win;
117  const int max_y = inImg_gray.getHeight() - 1 - KLT_half_win;
118 
119  for (size_t i=0;i<N;i++)
120  {
121  const int x = corners[i].pt.x;
122  const int y = corners[i].pt.y;
123  if (x>KLT_half_win && y>KLT_half_win && x<=max_x && y<=max_y)
124  corners[i].response = inImg_gray.KLT_response(x,y,KLT_half_win);
125  else corners[i].response = -100;
126  }
127 
128  std::sort( sorted_indices.begin(), sorted_indices.end(), KeypointResponseSorter<TSimpleFeatureList>(corners) );
129  }
130  else
131  {
132  for (size_t i=0;i<N;i++)
133  corners[i].response = 0;
134  }
135 
136  // 2) Filter by "min-distance" (in options.FASTOptions.min_distance)
137  // 3) Convert to MRPT CFeatureList format.
138  // Steps 2 & 3 are done together in the while() below.
139  // The "min-distance" filter is done by means of a 2D binary matrix where each cell is marked when one
140  // feature falls within it. This is not exactly the same than a pure "min-distance" but is pretty close
141  // and for large numbers of features is much faster than brute force search of kd-trees.
142  // (An intermediate approach would be the creation of a mask image updated for each accepted feature, etc.)
143 
144  const bool do_filter_min_dist = options.FASTOptions.min_distance>1;
145 
146  // Used half the min-distance since we'll later mark as occupied the ranges [i-1,i+1] for a feature at "i"
147  const unsigned int occupied_grid_cell_size = options.FASTOptions.min_distance/2.0;
148  const float occupied_grid_cell_size_inv = 1.0f/occupied_grid_cell_size;
149 
150  unsigned int grid_lx = !do_filter_min_dist ? 1 : (unsigned int)(1 + inImg.getWidth() * occupied_grid_cell_size_inv);
151  unsigned int grid_ly = !do_filter_min_dist ? 1 : (unsigned int)(1 + inImg.getHeight() * occupied_grid_cell_size_inv );
152 
153  mrpt::math::CMatrixBool occupied_sections(grid_lx,grid_ly); // See the comments above for an explanation.
154  occupied_sections.fillAll(false);
155 
156 
157  unsigned int nMax = (nDesiredFeatures!=0 && N > nDesiredFeatures) ? nDesiredFeatures : N;
158  const int offset = (int)this->options.patchSize/2 + 1;
159  const int size_2 = options.patchSize/2;
160  const size_t imgH = inImg.getHeight();
161  const size_t imgW = inImg.getWidth();
162  unsigned int i = 0;
163  unsigned int cont = 0;
164  TFeatureID nextID = init_ID;
165 
166  if( !options.addNewFeatures )
167  feats.clear();
168 
169  while( cont != nMax && i!=N )
170  {
171  // Take the next feature fromt the ordered list of good features:
172  const TSimpleFeature &feat = corners[ sorted_indices[i] ];
173  i++;
174 
175  // Patch out of the image??
176  const int xBorderInf = feat.pt.x - size_2;
177  const int xBorderSup = feat.pt.x + size_2;
178  const int yBorderInf = feat.pt.y - size_2;
179  const int yBorderSup = feat.pt.y + size_2;
180 
181  if (!( xBorderSup < (int)imgW && xBorderInf > 0 && yBorderSup < (int)imgH && yBorderInf > 0 ))
182  continue; // nope, skip.
183 
184  if (do_filter_min_dist)
185  {
186  // Check the min-distance:
187  const size_t section_idx_x = size_t(feat.pt.x * occupied_grid_cell_size_inv);
188  const size_t section_idx_y = size_t(feat.pt.y * occupied_grid_cell_size_inv);
189 
190  if (occupied_sections(section_idx_x,section_idx_y))
191  continue; // Already occupied! skip.
192 
193  // Mark section as occupied
194  occupied_sections.set_unsafe(section_idx_x,section_idx_y, true);
195  if (section_idx_x>0) occupied_sections.set_unsafe(section_idx_x-1,section_idx_y, true);
196  if (section_idx_y>0) occupied_sections.set_unsafe(section_idx_x,section_idx_y-1, true);
197  if (section_idx_x<grid_lx-1) occupied_sections.set_unsafe(section_idx_x+1,section_idx_y, true);
198  if (section_idx_y<grid_ly-1) occupied_sections.set_unsafe(section_idx_x,section_idx_y+1, true);
199  }
200 
201  // All tests passed: add new feature:
202  CFeaturePtr ft = CFeature::Create();
203  ft->type = type_of_this_feature;
204  ft->ID = nextID++;
205  ft->x = feat.pt.x;
206  ft->y = feat.pt.y;
207  ft->response = feat.response;
208  ft->orientation = 0;
209  ft->scale = 1;
210  ft->patchSize = options.patchSize; // The size of the feature patch
211 
212  if( options.patchSize > 0 )
213  {
214  inImg.extract_patch(
215  ft->patch,
216  round( ft->x ) - offset,
217  round( ft->y ) - offset,
218  options.patchSize,
219  options.patchSize ); // Image patch surronding the feature
220  }
221  feats.push_back( ft );
222  ++cont;
223  }
224 
225 #endif
226  MRPT_END
227 }
228 
229 
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's "FASTER & Better" detector, N=9,10,12.
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1166
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).
FASTER-9 detector, Edward Rosten's libcvd implementation optimized for SSE2.
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:101
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=NULL)
Just like detectFeatures_SSE2_FASTER9() for another version of the detector.
#define THROW_EXCEPTION(msg)
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:43
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.
GLint GLvoid * img
Definition: glew.h:1290
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=NULL)
Just like detectFeatures_SSE2_FASTER9() for another version of the detector.
#define MRPT_END
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
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:1368
GLint GLint GLint GLint GLint x
Definition: glew.h:1166
FASTER-9 detector, Edward Rosten's libcvd implementation optimized for SSE2.
void push_back(const CFeaturePtr &f)
Definition: CFeature.h:285
FASTER-9 detector, Edward Rosten's libcvd implementation optimized for SSE2.
uint64_t TFeatureID
Definition of a feature ID.
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
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:211
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
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
pixel_coords_t pt
Coordinates in the image.
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img.getAs<IplImage>()" so we can avoid here including OpenCV's headers.
Definition: CImage.h:517
float response
A measure of the "goodness" of the feature (typically, the KLT_response value)
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:26
static CFeaturePtr Create()
GLintptr offset
Definition: glew.h:1587
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
Definition: CImage.cpp:855
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)
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
Definition: CImage.cpp:884
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=NULL)
A SSE2-optimized implementation of FASTER-9 (requires img to be grayscale).
void fillAll(const T &val)



Page generated by Doxygen 1.8.6 for MRPT 1.5.6 Git: 4c65e84 Tue Apr 24 08:18:17 2018 +0200 at mar abr 24 08:26:17 CEST 2018