Main MRPT website > C++ reference for MRPT 1.9.9
CFeatureExtraction_harris_KLT.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 using namespace mrpt;
18 using namespace mrpt::vision;
19 using namespace mrpt::system;
20 using namespace mrpt::utils;
21 using namespace std;
22 
23 /************************************************************************************************
24 * extractFeaturesKLT
25 ************************************************************************************************/
27  const mrpt::utils::CImage& inImg, CFeatureList& feats, unsigned int init_ID,
28  unsigned int nDesiredFeatures, const TImageROI& ROI) const
29 {
30 //#define VERBOSE_TIMING
31 
32 #ifdef VERBOSE_TIMING
33  CTicTac tictac;
34 #endif
36 
37 #if MRPT_HAS_OPENCV
38  const unsigned int MAX_COUNT = 300;
39 
40  // -----------------------------------------------------------------
41  // Create OpenCV Local Variables
42  // -----------------------------------------------------------------
43  int count = 0;
44  int nPts;
45 
46 #ifdef VERBOSE_TIMING
47  tictac.Tic();
48 #endif
49  const cv::Mat img(cv::cvarrToMat(inImg.getAs<IplImage>()));
50 
51 #ifdef VERBOSE_TIMING
52  cout << "[KLT] Attach: " << tictac.Tac() * 1000.0f << endl;
53 #endif
54  const CImage inImg_gray(inImg, FAST_REF_OR_CONVERT_TO_GRAY);
55  const cv::Mat cGrey(cv::cvarrToMat(inImg_gray.getAs<IplImage>()));
56 
57  nDesiredFeatures <= 0 ? nPts = MAX_COUNT : nPts = nDesiredFeatures;
58 
59 #ifdef VERBOSE_TIMING
60  tictac.Tic();
61 #endif
62 
63 #ifdef VERBOSE_TIMING
64  cout << "[KLT] Create: " << tictac.Tac() * 1000.0f << endl;
65 #endif
66  count = nPts; // Number of points to find
67 
68  // -----------------------------------------------------------------
69  // Select good features with subpixel accuracy (USING HARRIS OR KLT)
70  // -----------------------------------------------------------------
71  const bool use_harris = (options.featsType == featHarris);
72 
73 #ifdef VERBOSE_TIMING
74  tictac.Tic();
75 #endif
76  std::vector<cv::Point2f> points;
77  cv::goodFeaturesToTrack(
78  cGrey, points, nPts,
79  (double)options.harrisOptions.threshold, // for rejecting weak local
80  // maxima ( with min_eig <
81  // threshold*max(eig_image) )
82  (double)options.harrisOptions
83  .min_distance, // minimum distance between features
84  cv::noArray(), // mask
85  3, // blocksize
86  use_harris, /* harris */
87  options.harrisOptions.k);
88 #ifdef VERBOSE_TIMING
89  cout << "[KLT] Find feats: " << tictac.Tac() * 1000.0f << endl;
90 #endif
91 
92  if (nDesiredFeatures > 0 && count < nPts)
93  cout << "\n[WARNING][selectGoodFeaturesKLT]: Only " << count << " of "
94  << nDesiredFeatures << " points could be extracted in the image."
95  << endl;
96 
97  if (options.FIND_SUBPIXEL)
98  {
99 #ifdef VERBOSE_TIMING
100  tictac.Tic();
101 #endif
102  // Subpixel interpolation
103  cv::cornerSubPix(
104  cGrey, points, cv::Size(3, 3), cv::Size(-1, -1),
105  cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10, 0.05));
106 
107 #ifdef VERBOSE_TIMING
108  cout << "[KLT] subpixel: " << tictac.Tac() * 1000.0f << endl;
109 #endif
110  }
111 
112 // -----------------------------------------------------------------
113 // Fill output structure
114 // -----------------------------------------------------------------
115 #ifdef VERBOSE_TIMING
116  tictac.Tic();
117 #endif
118 
119  feats.clear();
120  unsigned int borderFeats = 0;
121  unsigned int nCFeats = init_ID;
122  int i = 0;
123  const int limit = min(nPts, count);
124  int offset = (int)this->options.patchSize / 2 + 1;
125  unsigned int imgH = inImg.getHeight();
126  unsigned int imgW = inImg.getWidth();
127 
128  while (i < limit)
129  {
130  const int xBorderInf = (int)floor(points[i].x - options.patchSize / 2);
131  const int xBorderSup = (int)floor(points[i].x + options.patchSize / 2);
132  const int yBorderInf = (int)floor(points[i].y - options.patchSize / 2);
133  const int yBorderSup = (int)floor(points[i].y + options.patchSize / 2);
134 
135  if (options.patchSize == 0 ||
136  ((xBorderSup < (int)imgW) && (xBorderInf > 0) &&
137  (yBorderSup < (int)imgH) && (yBorderInf > 0)))
138  {
139  CFeature::Ptr ft = mrpt::make_aligned_shared<CFeature>();
140 
141  ft->type = featKLT;
142  ft->x = points[i].x; // X position
143  ft->y = points[i].y; // Y position
144  ft->track_status = status_TRACKED; // Feature Status
145  ft->response = 0.0; // A value proportional to the quality of the
146  // feature (unused yet)
147  ft->ID = nCFeats++; // Feature ID into extraction
148  ft->patchSize = options.patchSize; // The size of the feature patch
149 
150  if (options.patchSize > 0)
151  {
152  inImg.extract_patch(
153  ft->patch, round(ft->x) - offset, round(ft->y) - offset,
154  options.patchSize,
155  options.patchSize); // Image patch surronding the feature
156  }
157 
158  feats.push_back(ft);
159 
160  } // end if
161  else
162  borderFeats++;
163 
164  i++;
165  } // end while
166 
167 #ifdef VERBOSE_TIMING
168  cout << "[KLT] Create output: " << tictac.Tac() * 1000.0f << endl;
169 #endif
170 
171 #else
172  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
173 #endif
174 
175  MRPT_END
176 
177 } // end of function
178 
179 MRPT_TODO("Delete? Refactor / join to mrpt::vision::CGenericFeatureTracker?")
180 #if 0
181 /*------------------------------------------------------------
182  findMoreFeatures
183 -------------------------------------------------------------*/
184 void CFeatureExtraction::findMoreFeatures( const mrpt::utils::CImage &img,
185  const CFeatureList &inList,
186  CFeatureList &outList,
187  unsigned int nDesiredFeats) const
188 {
189 #if MRPT_HAS_OPENCV
190  MRPT_START
191 
192  if( options.featsType == featHarris || options.featsType == featKLT )
193  {
194  // Mask the points already stored in the list
195  cv::Mat mask = cv::Mat::ones(img.getHeight(), img.getWidth(), CV_8UC1 ); // Set the whole mask to 1 initially
196 
198 
199  TFeatureID mxID = 0;
200 
201  for( itKLT = inList.begin(); itKLT != inList.end(); itKLT++ )
202  {
203  int cx = (int)(*itKLT)->x;
204  int cy = (int)(*itKLT)->y;
205 
206  // Mask surronding pixels
207  size_t xxI = max( 0, cx - 15 );
208  size_t xxE = min( cx + 15, mask.cols()-1 );
209  size_t yyI = max( 0, cy - 15 );
210  size_t yyE = min( cy + 15, (int)mask.rows()-1 );
211 
212  for(size_t yy = yyI; yy < yyE; yy++)
213  for(size_t xx = xxI; xx < xxE; xx++)
214  cvSet2D( mask, yy, xx, zero );
215 
216  if( (*itKLT)->ID > mxID )
217  mxID = (*itKLT)->ID;
218 
219  }
220  selectGoodFeaturesKLT( img, outList, mxID + 1, nDesiredFeats, &mask );
221  }
222  else if( options.featsType == featFAST )
223  {
224  TFeatureID mxID = inList.getMaxID();
225  extractFeaturesFAST( img, outList, mxID+1 ); // Find all the possible FAST features
226 
227  // Delete all that are too close to the current ones
228  CFeatureList::iterator itOutList;
230  for( itInList = inList.begin(); itInList != inList.end(); ++itInList )
231  {
232  for( itOutList = outList.begin(); itOutList != outList.end(); )
233  {
234  if( fabs((*itOutList)->x-(*itInList)->x) < 15 || fabs((*itOutList)->y-(*itInList)->y) < 15 )
235  itOutList = outList.erase( itOutList );
236  else
237  ++itOutList;
238  } // end-for
239  } // end-for
240 
241  if( nDesiredFeats != 0 && outList.size() > nDesiredFeats )
242  outList.resize( nDesiredFeats );
243  }
244  MRPT_END
245 #else
246  THROW_EXCEPTION("MRPT was compiled without OpenCV")
247 #endif
248 } // end findMoreFeatures
249 #endif
250 
251 MRPT_TODO("Delete? Is not this a duplicate of extractFeaturesKLT ()???")
252 #if 0
253 /************************************************************************************************
254 * selectGoodFeaturesKLT *
255 ************************************************************************************************/
256 void CFeatureExtraction::selectGoodFeaturesKLT(
257  const mrpt::utils::CImage &img,
258  CFeatureList &feats,
259  unsigned int init_ID,
260  unsigned int nDesiredFeatures) const
261 {
262 #if MRPT_HAS_OPENCV
263  // Get image size
264  size_t imgW = img.getWidth();
265  size_t imgH = img.getHeight();
266 
267  // Check image size and ROI limits
268  ASSERT_( imgH > 0 && imgW > 0 ); // Proper Image Size
269  ASSERT_( ROI.xMin >= 0 && ROI.yMin >= 0 && ROI.xMax < imgW && ROI.yMax < imgH ); // Proper TImageROI Limits
270 
271  // Mask
272  CvMatrix mask( imgH, imgW, CV_8UC1 );
273  CvScalar zero = cvRealScalar( 0.0 );
274  CvScalar one = cvRealScalar( 1.0 );
275 
276  if( ROI.xMin == 0 && ROI.xMax == 0 && ROI.yMin == 0 && ROI.yMax == 0 ) // Use the whole image (except the borders)
277  {
278  if( options.patchSize == 0 )
279  selectGoodFeaturesKLT( img, feats, init_ID, nDesiredFeatures, nullptr );
280  else
281  {
282  // We mask the borders of the image in order to get an appropiate patch (according to the patch size)
283  // ---------------------------------------------------------------------
284  // 00000000000000000000000000000000000
285  // 00000000000000000000000000000000000
286  // 00111111111111111111111111111111100
287  // 00111111111111111111111111111111100
288  // 00111111111111111111111111111111100
289  // 00111111111111111111111111111111100
290  // 00111111111111111111111111111111100
291  // 00111111111111111111111111111111100
292  // 00111111111111111111111111111111100
293  // 00000000000000000000000000000000000
294  // 00000000000000000000000000000000000
295 
296  cvSet( mask, one ); // Set the whole mask to 1 initially
297 
298  size_t border = (options.patchSize-1)/2 + 1;
299  size_t xx,yy; // Put outside of the "for"s to avoid errors in VC6
300  for( xx = 0; xx < imgW; xx++ )
301  for( yy = 0; yy < border; yy++ )
302  cvSet2D( mask, yy, xx, zero ); // Set to 0 the pixels not to be processed
303 
304  for( xx = 0; xx < imgW; xx++ )
305  for( yy = imgH - border; yy < imgH; yy++ )
306  cvSet2D( mask, yy, xx, zero ); // Set to 0 the pixels not to be processed
307 
308  for( xx = 0; xx < border; xx++ )
309  for( yy = border; yy < imgH - border; yy++ )
310  cvSet2D( mask, yy, xx, zero ) ; // Set to 0 the pixels not to be processed
311 
312  for( xx = imgW - border; xx < imgW; xx++ )
313  for( yy = border; yy < imgH - border; yy++ )
314  cvSet2D( mask, yy, xx, zero ) ; // Set to 0 the pixels not to be processed
315 
316  selectGoodFeaturesKLT( img, feats, init_ID, nDesiredFeatures, &mask );
317  } // end if-else patchSize == 0
318  } // end if ROI does not exist
319  else
320  {
321  cvSet( mask, zero ); // Set the whole mask to 0 initially
322  for( unsigned int xx = ROI.xMin; xx < ROI.xMax; xx++ )
323  for( unsigned int yy = ROI.yMin; yy < ROI.yMax; yy++ )
324  cvSet2D( mask, yy, xx, one) ; // Set to 1 the pixels to be processed
325 
326  selectGoodFeaturesKLT( img, feats, init_ID, nDesiredFeatures, &mask );
327  } // end if-else there exists a ROI
328 #else
329  THROW_EXCEPTION("MRPT was compiled without OpenCV")
330 #endif
331 }
332 
333 #endif
std::shared_ptr< CFeature > Ptr
Definition: CFeature.h:58
GLuint GLuint GLsizei count
Definition: glext.h:3528
GLenum GLint GLuint mask
Definition: glext.h:4050
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define min(a, b)
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
size_t size() const
Definition: CFeature.h:387
#define THROW_EXCEPTION(msg)
GLintptr offset
Definition: glext.h:3925
TInternalFeatList::const_iterator const_iterator
Definition: CFeature.h:367
STL namespace.
void Tic()
Starts the stopwatch.
Definition: CTicTac.cpp:82
GLint limit
Definition: glext.h:8188
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&#39;s headers.
Definition: CImage.h:587
#define MRPT_TODO(x)
GLsizei const GLfloat * points
Definition: glext.h:5339
FAST feature detector, OpenCV&#39;s implementation ("Faster and better: A machine learning approac...
A structure for defining a ROI within an image.
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: glext.h:3600
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
void resize(size_t N)
Definition: CFeature.h:393
#define MRPT_END
void extractFeaturesKLT(const mrpt::utils::CImage &img, CFeatureList &feats, unsigned int init_ID=0, unsigned int nDesiredFeatures=0, const TImageROI &ROI=TImageROI()) const
Extract features from the image based on the KLT method.
GLint GLvoid * img
Definition: glext.h:3763
Harris border and corner detector [HARRIS].
This class implements a high-performance stopwatch.
Definition: CTicTac.h:23
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
Classes for computer vision, detectors, features, etc.
iterator erase(const iterator &it)
Definition: CFeature.h:380
uint64_t TFeatureID
Definition of a feature ID.
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:305
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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
double Tac()
Stops the stopwatch.
Definition: CTicTac.cpp:97
#define ASSERT_(f)
TFeatureID getMaxID() const
Get the maximum ID into the list.
Definition: CFeature.cpp:1324
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
TInternalFeatList::iterator iterator
Definition: CFeature.h:366
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLint x
Definition: glext.h:3538
EIGEN_STRONG_INLINE void ones(const size_t row, const size_t col)
Resize matrix and set all elements to one.
Definition: eigen_plugins.h:86
Kanade-Lucas-Tomasi feature [SHI&#39;94].
void push_back(const CFeature::Ptr &f)
Definition: CFeature.h:399



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