MRPT  1.9.9
CFeatureExtraction_FAST.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://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 using namespace mrpt;
18 using namespace mrpt::vision;
19 using namespace mrpt::img;
20 using namespace mrpt::system;
21 using namespace mrpt::img;
22 using namespace mrpt::math;
23 using namespace std;
24 
26  const mrpt::img::CImage& inImg, CFeatureList& feats, unsigned int init_ID,
27  unsigned int nDesiredFeatures)
28 {
30 
31  mrpt::system::CTimeLoggerEntry tle(profiler, "extractFeaturesFAST");
32 
33 #if MRPT_HAS_OPENCV
34  using namespace cv;
35 
36  vector<KeyPoint> cv_feats; // The opencv keypoint output vector
37 
38  // Make sure we operate on a gray-scale version of the image:
39  const CImage inImg_gray(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
40  const Mat theImg = inImg_gray.asCvMat<cv::Mat>(SHALLOW_COPY);
41 
42 #if MRPT_OPENCV_VERSION_NUM < 0x300
43  FastFeatureDetector fastDetector(
44  options.FASTOptions.threshold, options.FASTOptions.nonmax_suppression);
45  fastDetector.detect(theImg, cv_feats);
46 #else
47  Ptr<cv::FastFeatureDetector> fastDetector = cv::FastFeatureDetector::create(
48  options.FASTOptions.threshold, options.FASTOptions.nonmax_suppression);
49  fastDetector->detect(theImg, cv_feats);
50 #endif
51 
52  // *All* the features have been extracted.
53  const size_t N = cv_feats.size();
54 
55  // Use KLT response instead of the OpenCV's original "response" field:
56  if (options.FASTOptions.use_KLT_response)
57  {
58  const unsigned int KLT_half_win = 4;
59  const unsigned int max_x = inImg_gray.getWidth() - 1 - KLT_half_win;
60  const unsigned int max_y = inImg_gray.getHeight() - 1 - KLT_half_win;
61  for (size_t i = 0; i < N; i++)
62  {
63  const unsigned int x = cv_feats[i].pt.x;
64  const unsigned int y = cv_feats[i].pt.y;
65  if (x > KLT_half_win && y > KLT_half_win && x <= max_x &&
66  y <= max_y)
67  cv_feats[i].response =
68  inImg_gray.KLT_response(x, y, KLT_half_win);
69  else
70  cv_feats[i].response = -100;
71  }
72  }
73 
74  // Now:
75  // 1) Sort them by "response": It's ~100 times faster to sort a list of
76  // indices "sorted_indices" than sorting directly the actual list of
77  // features "cv_feats"
78  std::vector<size_t> sorted_indices(N);
79  for (size_t i = 0; i < N; i++) sorted_indices[i] = i;
80  std::sort(
81  sorted_indices.begin(), sorted_indices.end(),
83 
84  // 2) Filter by "min-distance" (in options.FASTOptions.min_distance)
85  // 3) Convert to MRPT CFeatureList format.
86  // Steps 2 & 3 are done together in the while() below.
87  // The "min-distance" filter is done by means of a 2D binary matrix where
88  // each cell is marked when one
89  // feature falls within it. This is not exactly the same than a pure
90  // "min-distance" but is pretty close
91  // and for large numbers of features is much faster than brute force search
92  // of kd-trees.
93  // (An intermediate approach would be the creation of a mask image updated
94  // for each accepted feature, etc.)
95 
96  const bool do_filter_min_dist = options.FASTOptions.min_distance > 1;
97 
98  // Used half the min-distance since we'll later mark as occupied the ranges
99  // [i-1,i+1] for a feature at "i"
100  const unsigned int occupied_grid_cell_size =
101  options.FASTOptions.min_distance / 2.0;
102  const float occupied_grid_cell_size_inv = 1.0f / occupied_grid_cell_size;
103 
104  unsigned int grid_lx =
105  !do_filter_min_dist
106  ? 1
107  : (unsigned int)(1 + inImg.getWidth() * occupied_grid_cell_size_inv);
108  unsigned int grid_ly =
109  !do_filter_min_dist
110  ? 1
111  : (unsigned int)(1 + inImg.getHeight() * occupied_grid_cell_size_inv);
112 
113  mrpt::math::CMatrixBool occupied_sections(grid_lx, grid_ly);
114  occupied_sections.fill(false);
115 
116  unsigned int nMax =
117  (nDesiredFeatures != 0 && N > nDesiredFeatures) ? nDesiredFeatures : N;
118  const int offset = (int)this->options.patchSize / 2 + 1;
119  const size_t size_2 = options.patchSize / 2;
120  const size_t imgH = inImg.getHeight();
121  const size_t imgW = inImg.getWidth();
122  unsigned int i = 0;
123  unsigned int cont = 0;
124  TFeatureID nextID = init_ID;
125 
126  if (!options.addNewFeatures) feats.clear();
127 
128  while (cont != nMax && i != N)
129  {
130  // Take the next feature fromt the ordered list of good features:
131  const KeyPoint& kp = cv_feats[sorted_indices[i]];
132  i++;
133 
134  // Patch out of the image??
135  const int xBorderInf = (int)floor(kp.pt.x - size_2);
136  const int xBorderSup = (int)floor(kp.pt.x + size_2);
137  const int yBorderInf = (int)floor(kp.pt.y - size_2);
138  const int yBorderSup = (int)floor(kp.pt.y + size_2);
139 
140  if (!(xBorderSup < (int)imgW && xBorderInf > 0 &&
141  yBorderSup < (int)imgH && yBorderInf > 0))
142  continue; // nope, skip.
143 
144  if (do_filter_min_dist)
145  {
146  // Check the min-distance:
147  const auto sect_ix = size_t(kp.pt.x * occupied_grid_cell_size_inv);
148  const auto sect_iy = size_t(kp.pt.y * occupied_grid_cell_size_inv);
149 
150  if (occupied_sections(sect_ix, sect_iy))
151  continue; // Already occupied! skip.
152 
153  // Mark section as occupied
154  occupied_sections(sect_ix, sect_iy) = true;
155  if (sect_ix > 0) occupied_sections(sect_ix - 1, sect_iy) = true;
156  if (sect_iy > 0) occupied_sections(sect_ix, sect_iy - 1) = true;
157  if (sect_ix < grid_lx - 1)
158  occupied_sections(sect_ix + 1, sect_iy) = true;
159  if (sect_iy < grid_ly - 1)
160  occupied_sections(sect_ix, sect_iy + 1) = true;
161  }
162 
163  // All tests passed: add new feature:
164  CFeature ft;
165  ft.type = featFAST;
166  ft.keypoint.ID = nextID++;
167  ft.keypoint.pt.x = kp.pt.x;
168  ft.keypoint.pt.y = kp.pt.y;
169  ft.response = kp.response;
170  ft.orientation = kp.angle;
171  ft.keypoint.octave = kp.octave;
172  ft.patchSize = options.patchSize; // The size of the feature patch
173 
174  if (options.patchSize > 0)
175  {
176  ft.patch.emplace();
177  inImg.extract_patch(
178  *ft.patch, round(ft.keypoint.pt.x) - offset,
179  round(ft.keypoint.pt.y) - offset, options.patchSize,
180  options.patchSize); // Image patch surronding the feature
181  }
182  feats.emplace_back(std::move(ft));
183  ++cont;
184  }
185 
186 #endif
187  MRPT_END
188 }
Shallow copy: the copied object is a reference to the original one.
Definition: img/CImage.h:74
#define MRPT_START
Definition: exceptions.h:241
uint64_t TFeatureID
Definition of a feature ID.
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
TKeyPointMethod type
Keypoint method used to detect this feature.
Definition: CFeature.h:73
void fill(const Scalar &val)
GLintptr offset
Definition: glext.h:3936
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:877
STL namespace.
TFeatureID ID
ID of the feature.
Definition: TKeyPoint.h:39
Definition: img/CImage.h:22
void asCvMat(cv::Mat &out_img, copy_type_t copy_type) const
Makes a shallow or deep copy of this image into the provided cv::Mat.
Definition: CImage.cpp:223
A helper struct to sort keypoints by their response: It can be used with these types: ...
Definition: TKeyPoint.h:288
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:846
float KLT_response(const unsigned int x, const unsigned int y, const unsigned int half_window_size) const
Compute the KLT response at a given pixel (x,y) - Only for grayscale images (for efficiency it avoids...
Definition: CImage.cpp:1911
TKeyPointf keypoint
Definition: CFeature.h:64
std::optional< mrpt::img::CImage > patch
A patch of the image surrounding the feature.
Definition: CFeature.h:67
Classes for computer vision, detectors, features, etc.
Definition: CDifodo.h:17
A generic 2D feature from an image, extracted with CFeatureExtraction Each feature may have one or mo...
Definition: CFeature.h:53
FAST feature detector, OpenCV&#39;s implementation ("Faster and better: A machine learning approach to...
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:275
float response
A measure of the "goodness" of the feature.
Definition: CFeature.h:79
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define MRPT_END
Definition: exceptions.h:245
uint8_t octave
The image octave the image was found in: 0=original image, 1=1/2 image, 2=1/4 image, etc.
Definition: TKeyPoint.h:49
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:1192
GLenum GLint GLint y
Definition: glext.h:3542
void extractFeaturesFAST(const mrpt::img::CImage &img, CFeatureList &feats, unsigned int init_ID=0, unsigned int nDesiredFeatures=0)
Extract features from the image based on the FAST method (OpenCV impl.)
float orientation
Main orientation of the feature.
Definition: CFeature.h:81
GLenum GLint x
Definition: glext.h:3542
This template class provides the basic functionality for a general 2D any-size, resizable container o...
uint16_t patchSize
Size of the patch (patchSize x patchSize) (it must be an odd number)
Definition: CFeature.h:70
void emplace_back(CFeature &&f)
Definition: CFeature.h:364
pixel_coords_t pt
Coordinates in the image.
Definition: TKeyPoint.h:36
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:147
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:23



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 479715d5b Tue Nov 12 07:26:21 2019 +0100 at mar nov 12 07:30:12 CET 2019