Features2d.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of the Universite de Sherbrooke nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
29 #include "rtabmap/core/util3d.h"
31 #include "rtabmap/core/Stereo.h"
32 #include "rtabmap/core/util2d.h"
33 #include "rtabmap/utilite/UStl.h"
36 #include "rtabmap/utilite/UMath.h"
38 #include "rtabmap/utilite/UTimer.h"
39 #include <opencv2/imgproc/imgproc_c.h>
40 #include <opencv2/core/version.hpp>
41 #include <opencv2/opencv_modules.hpp>
42 
43 #ifdef RTABMAP_ORB_OCTREE
44 #include "opencv/ORBextractor.h"
45 #endif
46 
47 #ifdef RTABMAP_SUPERPOINT_TORCH
49 #endif
50 
51 #if CV_MAJOR_VERSION < 3
52 #include "opencv/Orb.h"
53 #ifdef HAVE_OPENCV_GPU
54 #include <opencv2/gpu/gpu.hpp>
55 #endif
56 #else
57 #include <opencv2/core/cuda.hpp>
58 #endif
59 
60 #ifdef HAVE_OPENCV_NONFREE
61  #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4
62  #include <opencv2/nonfree/gpu.hpp>
63  #include <opencv2/nonfree/features2d.hpp>
64  #endif
65 #endif
66 #ifdef HAVE_OPENCV_XFEATURES2D
67  #include <opencv2/xfeatures2d.hpp>
68  #include <opencv2/xfeatures2d/nonfree.hpp>
69  #include <opencv2/xfeatures2d/cuda.hpp>
70 #endif
71 #ifdef HAVE_OPENCV_CUDAFEATURES2D
72  #include <opencv2/cudafeatures2d.hpp>
73 #endif
74 
75 #ifdef RTABMAP_FASTCV
76 #include <fastcv.h>
77 #endif
78 
79 namespace rtabmap {
80 
82  std::vector<cv::KeyPoint> & keypoints,
83  const cv::Mat & depth,
84  float minDepth,
85  float maxDepth)
86 {
87  cv::Mat descriptors;
88  filterKeypointsByDepth(keypoints, descriptors, depth, minDepth, maxDepth);
89 }
90 
92  std::vector<cv::KeyPoint> & keypoints,
93  cv::Mat & descriptors,
94  const cv::Mat & depth,
95  float minDepth,
96  float maxDepth)
97 {
98  UASSERT(minDepth >= 0.0f);
99  UASSERT(maxDepth <= 0.0f || maxDepth > minDepth);
100  if(!depth.empty() && (descriptors.empty() || descriptors.rows == (int)keypoints.size()))
101  {
102  std::vector<cv::KeyPoint> output(keypoints.size());
103  std::vector<int> indexes(keypoints.size(), 0);
104  int oi=0;
105  bool isInMM = depth.type() == CV_16UC1;
106  for(unsigned int i=0; i<keypoints.size(); ++i)
107  {
108  int u = int(keypoints[i].pt.x+0.5f);
109  int v = int(keypoints[i].pt.y+0.5f);
110  if(u >=0 && u<depth.cols && v >=0 && v<depth.rows)
111  {
112  float d = isInMM?(float)depth.at<uint16_t>(v,u)*0.001f:depth.at<float>(v,u);
113  if(uIsFinite(d) && d>minDepth && (maxDepth <= 0.0f || d < maxDepth))
114  {
115  output[oi++] = keypoints[i];
116  indexes[i] = 1;
117  }
118  }
119  }
120  output.resize(oi);
121  keypoints = output;
122 
123  if(!descriptors.empty() && (int)keypoints.size() != descriptors.rows)
124  {
125  if(keypoints.size() == 0)
126  {
127  descriptors = cv::Mat();
128  }
129  else
130  {
131  cv::Mat newDescriptors((int)keypoints.size(), descriptors.cols, descriptors.type());
132  int di = 0;
133  for(unsigned int i=0; i<indexes.size(); ++i)
134  {
135  if(indexes[i] == 1)
136  {
137  if(descriptors.type() == CV_32FC1)
138  {
139  memcpy(newDescriptors.ptr<float>(di++), descriptors.ptr<float>(i), descriptors.cols*sizeof(float));
140  }
141  else // CV_8UC1
142  {
143  memcpy(newDescriptors.ptr<char>(di++), descriptors.ptr<char>(i), descriptors.cols*sizeof(char));
144  }
145  }
146  }
147  descriptors = newDescriptors;
148  }
149  }
150  }
151 }
152 
154  std::vector<cv::KeyPoint> & keypoints,
155  cv::Mat & descriptors,
156  std::vector<cv::Point3f> & keypoints3D,
157  float minDepth,
158  float maxDepth)
159 {
160  UDEBUG("");
161  //remove all keypoints/descriptors with no valid 3D points
162  UASSERT(((int)keypoints.size() == descriptors.rows || descriptors.empty()) &&
163  keypoints3D.size() == keypoints.size());
164  std::vector<cv::KeyPoint> validKeypoints(keypoints.size());
165  std::vector<cv::Point3f> validKeypoints3D(keypoints.size());
166  cv::Mat validDescriptors(descriptors.size(), descriptors.type());
167 
168  int oi=0;
169  float minDepthSqr = minDepth * minDepth;
170  float maxDepthSqr = maxDepth * maxDepth;
171  for(unsigned int i=0; i<keypoints3D.size(); ++i)
172  {
173  cv::Point3f & pt = keypoints3D[i];
174  if(util3d::isFinite(pt))
175  {
176  float distSqr = pt.x*pt.x+pt.y*pt.y+pt.z*pt.z;
177  if(distSqr >= minDepthSqr && (maxDepthSqr==0.0f || distSqr <= maxDepthSqr))
178  {
179  validKeypoints[oi] = keypoints[i];
180  validKeypoints3D[oi] = pt;
181  if(!descriptors.empty())
182  {
183  descriptors.row(i).copyTo(validDescriptors.row(oi));
184  }
185  ++oi;
186  }
187  }
188  }
189  UDEBUG("Removed %d invalid 3D points", (int)keypoints3D.size()-oi);
190  validKeypoints.resize(oi);
191  validKeypoints3D.resize(oi);
192  keypoints = validKeypoints;
193  keypoints3D = validKeypoints3D;
194  if(!descriptors.empty())
195  {
196  descriptors = validDescriptors.rowRange(0, oi).clone();
197  }
198 }
199 
201  std::vector<cv::KeyPoint> & keypoints,
202  const cv::Mat & disparity,
203  float minDisparity)
204 {
205  cv::Mat descriptors;
206  filterKeypointsByDisparity(keypoints, descriptors, disparity, minDisparity);
207 }
208 
210  std::vector<cv::KeyPoint> & keypoints,
211  cv::Mat & descriptors,
212  const cv::Mat & disparity,
213  float minDisparity)
214 {
215  if(!disparity.empty() && minDisparity > 0.0f && (descriptors.empty() || descriptors.rows == (int)keypoints.size()))
216  {
217  std::vector<cv::KeyPoint> output(keypoints.size());
218  std::vector<int> indexes(keypoints.size(), 0);
219  int oi=0;
220  for(unsigned int i=0; i<keypoints.size(); ++i)
221  {
222  int u = int(keypoints[i].pt.x+0.5f);
223  int v = int(keypoints[i].pt.y+0.5f);
224  if(u >=0 && u<disparity.cols && v >=0 && v<disparity.rows)
225  {
226  float d = disparity.type() == CV_16SC1?float(disparity.at<short>(v,u))/16.0f:disparity.at<float>(v,u);
227  if(d!=0.0f && uIsFinite(d) && d >= minDisparity)
228  {
229  output[oi++] = keypoints[i];
230  indexes[i] = 1;
231  }
232  }
233  }
234  output.resize(oi);
235  keypoints = output;
236 
237  if(!descriptors.empty() && (int)keypoints.size() != descriptors.rows)
238  {
239  if(keypoints.size() == 0)
240  {
241  descriptors = cv::Mat();
242  }
243  else
244  {
245  cv::Mat newDescriptors((int)keypoints.size(), descriptors.cols, descriptors.type());
246  int di = 0;
247  for(unsigned int i=0; i<indexes.size(); ++i)
248  {
249  if(indexes[i] == 1)
250  {
251  if(descriptors.type() == CV_32FC1)
252  {
253  memcpy(newDescriptors.ptr<float>(di++), descriptors.ptr<float>(i), descriptors.cols*sizeof(float));
254  }
255  else // CV_8UC1
256  {
257  memcpy(newDescriptors.ptr<char>(di++), descriptors.ptr<char>(i), descriptors.cols*sizeof(char));
258  }
259  }
260  }
261  descriptors = newDescriptors;
262  }
263  }
264  }
265 }
266 
267 void Feature2D::limitKeypoints(std::vector<cv::KeyPoint> & keypoints, int maxKeypoints)
268 {
269  cv::Mat descriptors;
270  limitKeypoints(keypoints, descriptors, maxKeypoints);
271 }
272 
273 void Feature2D::limitKeypoints(std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors, int maxKeypoints)
274 {
275  std::vector<cv::Point3f> keypoints3D;
276  limitKeypoints(keypoints, keypoints3D, descriptors, maxKeypoints);
277 }
278 
279 void Feature2D::limitKeypoints(std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & keypoints3D, cv::Mat & descriptors, int maxKeypoints)
280 {
281  UASSERT_MSG((int)keypoints.size() == descriptors.rows || descriptors.rows == 0, uFormat("keypoints=%d descriptors=%d", (int)keypoints.size(), descriptors.rows).c_str());
282  UASSERT_MSG(keypoints.size() == keypoints3D.size() || keypoints3D.size() == 0, uFormat("keypoints=%d keypoints3D=%d", (int)keypoints.size(), (int)keypoints3D.size()).c_str());
283  if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints)
284  {
285  UTimer timer;
286  ULOGGER_DEBUG("too much words (%d), removing words with the hessian threshold", keypoints.size());
287  // Remove words under the new hessian threshold
288 
289  // Sort words by hessian
290  std::multimap<float, int> hessianMap; // <hessian,id>
291  for(unsigned int i = 0; i <keypoints.size(); ++i)
292  {
293  //Keep track of the data, to be easier to manage the data in the next step
294  hessianMap.insert(std::pair<float, int>(fabs(keypoints[i].response), i));
295  }
296 
297  // Remove them from the signature
298  int removed = (int)hessianMap.size()-maxKeypoints;
299  std::multimap<float, int>::reverse_iterator iter = hessianMap.rbegin();
300  std::vector<cv::KeyPoint> kptsTmp(maxKeypoints);
301  std::vector<cv::Point3f> kpts3DTmp(maxKeypoints);
302  cv::Mat descriptorsTmp;
303  if(descriptors.rows)
304  {
305  descriptorsTmp = cv::Mat(maxKeypoints, descriptors.cols, descriptors.type());
306  }
307  for(unsigned int k=0; k < kptsTmp.size() && iter!=hessianMap.rend(); ++k, ++iter)
308  {
309  kptsTmp[k] = keypoints[iter->second];
310  if(keypoints3D.size())
311  {
312  kpts3DTmp[k] = keypoints3D[iter->second];
313  }
314  if(descriptors.rows)
315  {
316  if(descriptors.type() == CV_32FC1)
317  {
318  memcpy(descriptorsTmp.ptr<float>(k), descriptors.ptr<float>(iter->second), descriptors.cols*sizeof(float));
319  }
320  else
321  {
322  memcpy(descriptorsTmp.ptr<char>(k), descriptors.ptr<char>(iter->second), descriptors.cols*sizeof(char));
323  }
324  }
325  }
326  ULOGGER_DEBUG("%d keypoints removed, (kept %d), minimum response=%f", removed, (int)kptsTmp.size(), kptsTmp.size()?kptsTmp.back().response:0.0f);
327  ULOGGER_DEBUG("removing words time = %f s", timer.ticks());
328  keypoints = kptsTmp;
329  keypoints3D = kpts3DTmp;
330  if(descriptors.rows)
331  {
332  descriptors = descriptorsTmp;
333  }
334  }
335 }
336 
337 void Feature2D::limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints)
338 {
339  if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints)
340  {
341  UTimer timer;
342  ULOGGER_DEBUG("too much words (%d), removing words with the hessian threshold", (int)keypoints.size());
343  // Remove words under the new hessian threshold
344 
345  // Sort words by hessian
346  std::multimap<float, int> hessianMap; // <hessian,id>
347  for(unsigned int i = 0; i <keypoints.size(); ++i)
348  {
349  //Keep track of the data, to be easier to manage the data in the next step
350  hessianMap.insert(std::pair<float, int>(fabs(keypoints[i].response), i));
351  }
352 
353  // Keep keypoints with highest response
354  int removed = (int)hessianMap.size()-maxKeypoints;
355  std::multimap<float, int>::reverse_iterator iter = hessianMap.rbegin();
356  inliers.resize(keypoints.size(), false);
357  float minimumHessian = 0.0f;
358  for(int k=0; k < maxKeypoints && iter!=hessianMap.rend(); ++k, ++iter)
359  {
360  inliers[iter->second] = true;
361  minimumHessian = iter->first;
362  }
363  ULOGGER_DEBUG("%d keypoints removed, (kept %d), minimum response=%f", removed, maxKeypoints, minimumHessian);
364  ULOGGER_DEBUG("filter keypoints time = %f s", timer.ticks());
365  }
366  else
367  {
368  ULOGGER_DEBUG("keeping all %d keypoints", (int)keypoints.size());
369  inliers.resize(keypoints.size(), true);
370  }
371 }
372 
373 void Feature2D::limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints, const cv::Size & imageSize, int gridRows, int gridCols)
374 {
375  if(maxKeypoints <= 0 || (int)keypoints.size() <= maxKeypoints)
376  {
377  inliers.resize(keypoints.size(), true);
378  return;
379  }
380  UASSERT(gridCols>=1 && gridRows >=1);
381  UASSERT(imageSize.height>gridRows && imageSize.width>gridCols);
382  int rowSize = imageSize.height / gridRows;
383  int colSize = imageSize.width / gridCols;
384  int maxKeypointsPerCell = maxKeypoints / (gridRows * gridCols);
385  std::vector<std::vector<cv::KeyPoint> > keypointsPerCell(gridRows * gridCols);
386  std::vector<std::vector<int> > indexesPerCell(gridRows * gridCols);
387  for(size_t i=0; i<keypoints.size(); ++i)
388  {
389  int cellRow = int(keypoints[i].pt.y)/rowSize;
390  int cellCol = int(keypoints[i].pt.x)/colSize;
391  UASSERT(cellRow >=0 && cellRow < gridRows);
392  UASSERT(cellCol >=0 && cellCol < gridCols);
393 
394  keypointsPerCell[cellRow*gridCols + cellCol].push_back(keypoints[i]);
395  indexesPerCell[cellRow*gridCols + cellCol].push_back(i);
396  }
397  inliers.resize(keypoints.size(), false);
398  for(size_t i=0; i<keypointsPerCell.size(); ++i)
399  {
400  std::vector<bool> inliersCell;
401  limitKeypoints(keypointsPerCell[i], inliersCell, maxKeypointsPerCell);
402  for(size_t j=0; j<inliersCell.size(); ++j)
403  {
404  if(inliersCell[j])
405  {
406  inliers.at(indexesPerCell[i][j]) = true;
407  }
408  }
409  }
410 }
411 
412 cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::string & roiRatios)
413 {
414  return util2d::computeRoi(image, roiRatios);
415 }
416 
417 cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::vector<float> & roiRatios)
418 {
419  return util2d::computeRoi(image, roiRatios);
420 }
421 
423 // Feature2D
425 Feature2D::Feature2D(const ParametersMap & parameters) :
426  maxFeatures_(Parameters::defaultKpMaxFeatures()),
427  _maxDepth(Parameters::defaultKpMaxDepth()),
428  _minDepth(Parameters::defaultKpMinDepth()),
429  _roiRatios(std::vector<float>(4, 0.0f)),
430  _subPixWinSize(Parameters::defaultKpSubPixWinSize()),
431  _subPixIterations(Parameters::defaultKpSubPixIterations()),
432  _subPixEps(Parameters::defaultKpSubPixEps()),
433  gridRows_(Parameters::defaultKpGridRows()),
434  gridCols_(Parameters::defaultKpGridCols())
435 {
436  _stereo = new Stereo(parameters);
437  this->parseParameters(parameters);
438 }
440 {
441  delete _stereo;
442 }
444 {
445  uInsert(parameters_, parameters);
446 
447  Parameters::parse(parameters, Parameters::kKpMaxFeatures(), maxFeatures_);
448  Parameters::parse(parameters, Parameters::kKpMaxDepth(), _maxDepth);
449  Parameters::parse(parameters, Parameters::kKpMinDepth(), _minDepth);
450  Parameters::parse(parameters, Parameters::kKpSubPixWinSize(), _subPixWinSize);
451  Parameters::parse(parameters, Parameters::kKpSubPixIterations(), _subPixIterations);
452  Parameters::parse(parameters, Parameters::kKpSubPixEps(), _subPixEps);
453  Parameters::parse(parameters, Parameters::kKpGridRows(), gridRows_);
454  Parameters::parse(parameters, Parameters::kKpGridCols(), gridCols_);
455 
456  UASSERT(gridRows_ >= 1 && gridCols_>=1);
457 
458  // convert ROI from string to vector
459  ParametersMap::const_iterator iter;
460  if((iter=parameters.find(Parameters::kKpRoiRatios())) != parameters.end())
461  {
462  std::list<std::string> strValues = uSplit(iter->second, ' ');
463  if(strValues.size() != 4)
464  {
465  ULOGGER_ERROR("The number of values must be 4 (roi=\"%s\")", iter->second.c_str());
466  }
467  else
468  {
469  std::vector<float> tmpValues(4);
470  unsigned int i=0;
471  for(std::list<std::string>::iterator jter = strValues.begin(); jter!=strValues.end(); ++jter)
472  {
473  tmpValues[i] = uStr2Float(*jter);
474  ++i;
475  }
476 
477  if(tmpValues[0] >= 0 && tmpValues[0] < 1 && tmpValues[0] < 1.0f-tmpValues[1] &&
478  tmpValues[1] >= 0 && tmpValues[1] < 1 && tmpValues[1] < 1.0f-tmpValues[0] &&
479  tmpValues[2] >= 0 && tmpValues[2] < 1 && tmpValues[2] < 1.0f-tmpValues[3] &&
480  tmpValues[3] >= 0 && tmpValues[3] < 1 && tmpValues[3] < 1.0f-tmpValues[2])
481  {
482  _roiRatios = tmpValues;
483  }
484  else
485  {
486  ULOGGER_ERROR("The roi ratios are not valid (roi=\"%s\")", iter->second.c_str());
487  }
488  }
489  }
490 
491  //stereo
492  UASSERT(_stereo != 0);
493  if((iter=parameters.find(Parameters::kStereoOpticalFlow())) != parameters.end())
494  {
495  delete _stereo;
497  }
498  else
499  {
500  _stereo->parseParameters(parameters);
501  }
502 }
504 {
505  int type = Parameters::defaultKpDetectorStrategy();
506  Parameters::parse(parameters, Parameters::kKpDetectorStrategy(), type);
507  return create((Feature2D::Type)type, parameters);
508 }
510 {
511 
512 // NONFREE checks
513 #if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
514 
515  #ifndef RTABMAP_NONFREE
517  {
518  #if CV_MAJOR_VERSION < 3
519  UWARN("SURF and SIFT features cannot be used because OpenCV was not built with nonfree module. GFTT/ORB is used instead.");
520  #else
521  UWARN("SURF and SIFT features cannot be used because OpenCV was not built with xfeatures2d module. GFTT/ORB is used instead.");
522  #endif
524  }
525  #endif
526 
527 #else // >= 4.4.0 >= 3.4.11
528 
529  #ifndef RTABMAP_NONFREE
530  if(type == Feature2D::kFeatureSurf)
531  {
532  UWARN("SURF features cannot be used because OpenCV was not built with nonfree module. SIFT is used instead.");
534  }
536  {
537  UWARN("SURF detector cannot be used because OpenCV was not built with nonfree module. GFTT/ORB is used instead.");
539  }
540  #endif
541 
542 #endif // >= 4.4.0 >= 3.4.11
543 
544 #if !defined(HAVE_OPENCV_XFEATURES2D) && CV_MAJOR_VERSION >= 3
545  if(type == Feature2D::kFeatureFastBrief ||
552  {
553  UWARN("BRIEF, FREAK and DAISY features cannot be used because OpenCV was not built with xfeatures2d module. GFTT/ORB is used instead.");
555  }
556 #elif CV_MAJOR_VERSION < 3
557  if(type == Feature2D::kFeatureKaze)
558  {
559  #ifdef RTABMAP_NONFREE
560  UWARN("KAZE detector/descriptor can be used only with OpenCV3. SURF is used instead.");
562  #else
563  UWARN("KAZE detector/descriptor can be used only with OpenCV3. GFTT/ORB is used instead.");
565  #endif
566  }
568  {
569  UWARN("DAISY detector/descriptor can be used only with OpenCV3. GFTT/BRIEF is used instead.");
571  }
572 #endif
573 
574 
575 #ifndef RTABMAP_ORB_OCTREE
576  if(type == Feature2D::kFeatureOrbOctree)
577  {
578  UWARN("ORB OcTree feature cannot be used as RTAB-Map is not built with the option enabled. GFTT/ORB is used instead.");
580  }
581 #endif
582 
583 #ifndef RTABMAP_SUPERPOINT_TORCH
585  {
586  UWARN("SupertPoint Torch feature cannot be used as RTAB-Map is not built with the option enabled. GFTT/ORB is used instead.");
588  }
589 #endif
590 
591  Feature2D * feature2D = 0;
592  switch(type)
593  {
595  feature2D = new SURF(parameters);
596  break;
598  feature2D = new SIFT(parameters);
599  break;
601  feature2D = new ORB(parameters);
602  break;
604  feature2D = new FAST_BRIEF(parameters);
605  break;
607  feature2D = new FAST_FREAK(parameters);
608  break;
610  feature2D = new GFTT_FREAK(parameters);
611  break;
613  feature2D = new GFTT_BRIEF(parameters);
614  break;
616  feature2D = new GFTT_ORB(parameters);
617  break;
619  feature2D = new BRISK(parameters);
620  break;
622  feature2D = new KAZE(parameters);
623  break;
625  feature2D = new ORBOctree(parameters);
626  break;
627 #ifdef RTABMAP_SUPERPOINT_TORCH
629  feature2D = new SuperPointTorch(parameters);
630  break;
631 #endif
633  feature2D = new SURF_FREAK(parameters);
634  break;
636  feature2D = new GFTT_DAISY(parameters);
637  break;
639  feature2D = new SURF_DAISY(parameters);
640  break;
641 #ifdef RTABMAP_NONFREE
642  default:
643  feature2D = new SURF(parameters);
645  break;
646 #else
647  default:
648  feature2D = new ORB(parameters);
650  break;
651 #endif
652 
653  }
654  return feature2D;
655 }
656 
657 std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, const cv::Mat & maskIn)
658 {
659  UASSERT(!image.empty());
660  UASSERT(image.type() == CV_8UC1);
661 
662  cv::Mat mask;
663  if(!maskIn.empty())
664  {
665  if(maskIn.type()==CV_16UC1 || maskIn.type() == CV_32FC1)
666  {
667  mask = cv::Mat::zeros(maskIn.rows, maskIn.cols, CV_8UC1);
668  for(int i=0; i<(int)mask.total(); ++i)
669  {
670  float value = 0.0f;
671  if(maskIn.type()==CV_16UC1)
672  {
673  if(((unsigned short*)maskIn.data)[i] > 0 &&
674  ((unsigned short*)maskIn.data)[i] < std::numeric_limits<unsigned short>::max())
675  {
676  value = float(((unsigned short*)maskIn.data)[i])*0.001f;
677  }
678  }
679  else
680  {
681  value = ((float*)maskIn.data)[i];
682  }
683 
684  if(value>_minDepth &&
685  (_maxDepth == 0.0f || value <= _maxDepth) &&
686  uIsFinite(value))
687  {
688  ((unsigned char*)mask.data)[i] = 255; // ORB uses 255 to handle pyramids
689  }
690  }
691  }
692  else if(maskIn.type()==CV_8UC1)
693  {
694  // assume a standard mask
695  mask = maskIn;
696  }
697  else
698  {
699  UERROR("Wrong mask type (%d)! Should be 8UC1, 16UC1 or 32FC1.", maskIn.type());
700  }
701  }
702 
703  UASSERT(mask.empty() || (mask.cols == image.cols && mask.rows == image.rows));
704 
705  std::vector<cv::KeyPoint> keypoints;
706  UTimer timer;
707  cv::Rect globalRoi = Feature2D::computeRoi(image, _roiRatios);
708  if(!(globalRoi.width && globalRoi.height))
709  {
710  globalRoi = cv::Rect(0,0,image.cols, image.rows);
711  }
712 
713  // Get keypoints
714  int rowSize = globalRoi.height / gridRows_;
715  int colSize = globalRoi.width / gridCols_;
716  int maxFeatures = maxFeatures_ / (gridRows_ * gridCols_);
717  for (int i = 0; i<gridRows_; ++i)
718  {
719  for (int j = 0; j<gridCols_; ++j)
720  {
721  cv::Rect roi(globalRoi.x + j*colSize, globalRoi.y + i*rowSize, colSize, rowSize);
722  std::vector<cv::KeyPoint> sub_keypoints;
723  sub_keypoints = this->generateKeypointsImpl(image, roi, mask);
724  limitKeypoints(sub_keypoints, maxFeatures);
725  if(roi.x || roi.y)
726  {
727  // Adjust keypoint position to raw image
728  for(std::vector<cv::KeyPoint>::iterator iter=sub_keypoints.begin(); iter!=sub_keypoints.end(); ++iter)
729  {
730  iter->pt.x += roi.x;
731  iter->pt.y += roi.y;
732  }
733  }
734  keypoints.insert( keypoints.end(), sub_keypoints.begin(), sub_keypoints.end() );
735  }
736  }
737  UDEBUG("Keypoints extraction time = %f s, keypoints extracted = %d (grid=%dx%d, mask empty=%d)",
738  timer.ticks(), keypoints.size(), gridCols_, gridRows_, mask.empty()?1:0);
739 
740  if(keypoints.size() && _subPixWinSize > 0 && _subPixIterations > 0)
741  {
742  std::vector<cv::Point2f> corners;
743  cv::KeyPoint::convert(keypoints, corners);
744  cv::cornerSubPix( image, corners,
745  cv::Size( _subPixWinSize, _subPixWinSize ),
746  cv::Size( -1, -1 ),
747  cv::TermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, _subPixIterations, _subPixEps ) );
748 
749  for(unsigned int i=0;i<corners.size(); ++i)
750  {
751  keypoints[i].pt = corners[i];
752  }
753  UDEBUG("subpixel time = %f s", timer.ticks());
754  }
755 
756  return keypoints;
757 }
758 
760  const cv::Mat & image,
761  std::vector<cv::KeyPoint> & keypoints) const
762 {
763  cv::Mat descriptors;
764  if(keypoints.size())
765  {
766  UASSERT(!image.empty());
767  UASSERT(image.type() == CV_8UC1);
768  descriptors = generateDescriptorsImpl(image, keypoints);
769  UASSERT_MSG(descriptors.rows == (int)keypoints.size(), uFormat("descriptors=%d, keypoints=%d", descriptors.rows, (int)keypoints.size()).c_str());
770  UDEBUG("Descriptors extracted = %d, remaining kpts=%d", descriptors.rows, (int)keypoints.size());
771  }
772  return descriptors;
773 }
774 
775 std::vector<cv::Point3f> Feature2D::generateKeypoints3D(
776  const SensorData & data,
777  const std::vector<cv::KeyPoint> & keypoints) const
778 {
779  std::vector<cv::Point3f> keypoints3D;
780  if(keypoints.size())
781  {
782  if(!data.rightRaw().empty() && !data.imageRaw().empty() && data.stereoCameraModel().isValidForProjection())
783  {
784  //stereo
785  cv::Mat imageMono;
786  // convert to grayscale
787  if(data.imageRaw().channels() > 1)
788  {
789  cv::cvtColor(data.imageRaw(), imageMono, cv::COLOR_BGR2GRAY);
790  }
791  else
792  {
793  imageMono = data.imageRaw();
794  }
795 
796  std::vector<cv::Point2f> leftCorners;
797  cv::KeyPoint::convert(keypoints, leftCorners);
798  std::vector<unsigned char> status;
799 
800  std::vector<cv::Point2f> rightCorners;
801  rightCorners = _stereo->computeCorrespondences(
802  imageMono,
803  data.rightRaw(),
804  leftCorners,
805  status);
806 
807  keypoints3D = util3d::generateKeypoints3DStereo(
808  leftCorners,
809  rightCorners,
810  data.stereoCameraModel(),
811  status,
812  _minDepth,
813  _maxDepth);
814  }
815  else if(!data.depthRaw().empty() && data.cameraModels().size())
816  {
817  keypoints3D = util3d::generateKeypoints3DDepth(
818  keypoints,
819  data.depthOrRightRaw(),
820  data.cameraModels(),
821  _minDepth,
822  _maxDepth);
823  }
824  }
825 
826  return keypoints3D;
827 }
828 
830 //SURF
832 SURF::SURF(const ParametersMap & parameters) :
833  hessianThreshold_(Parameters::defaultSURFHessianThreshold()),
834  nOctaves_(Parameters::defaultSURFOctaves()),
835  nOctaveLayers_(Parameters::defaultSURFOctaveLayers()),
836  extended_(Parameters::defaultSURFExtended()),
837  upright_(Parameters::defaultSURFUpright()),
838  gpuKeypointsRatio_(Parameters::defaultSURFGpuKeypointsRatio()),
839  gpuVersion_(Parameters::defaultSURFGpuVersion())
840 {
841  parseParameters(parameters);
842 }
843 
845 {
846 }
847 
848 void SURF::parseParameters(const ParametersMap & parameters)
849 {
850  Feature2D::parseParameters(parameters);
851 
852  Parameters::parse(parameters, Parameters::kSURFExtended(), extended_);
853  Parameters::parse(parameters, Parameters::kSURFHessianThreshold(), hessianThreshold_);
854  Parameters::parse(parameters, Parameters::kSURFOctaveLayers(), nOctaveLayers_);
855  Parameters::parse(parameters, Parameters::kSURFOctaves(), nOctaves_);
856  Parameters::parse(parameters, Parameters::kSURFUpright(), upright_);
857  Parameters::parse(parameters, Parameters::kSURFGpuKeypointsRatio(), gpuKeypointsRatio_);
858  Parameters::parse(parameters, Parameters::kSURFGpuVersion(), gpuVersion_);
859 
860 #ifdef RTABMAP_NONFREE
861 #if CV_MAJOR_VERSION < 3
862  if(gpuVersion_ && cv::gpu::getCudaEnabledDeviceCount() == 0)
863  {
864  UWARN("GPU version of SURF not available! Using CPU version instead...");
865  gpuVersion_ = false;
866  }
867 #else
868  if(gpuVersion_ && cv::cuda::getCudaEnabledDeviceCount() == 0)
869  {
870  UWARN("GPU version of SURF not available! Using CPU version instead...");
871  gpuVersion_ = false;
872  }
873 #endif
874  if(gpuVersion_)
875  {
877  }
878  else
879  {
880 #if CV_MAJOR_VERSION < 3
882 #else
884 #endif
885  }
886 #else
887  UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
888 #endif
889 }
890 
891 std::vector<cv::KeyPoint> SURF::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
892 {
893  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
894  std::vector<cv::KeyPoint> keypoints;
895 
896 #ifdef RTABMAP_NONFREE
897  cv::Mat imgRoi(image, roi);
898  cv::Mat maskRoi;
899  if(!mask.empty())
900  {
901  maskRoi = cv::Mat(mask, roi);
902  }
903  if(gpuVersion_)
904  {
905 #if CV_MAJOR_VERSION < 3
906  cv::gpu::GpuMat imgGpu(imgRoi);
907  cv::gpu::GpuMat maskGpu(maskRoi);
908  (*_gpuSurf.obj)(imgGpu, maskGpu, keypoints);
909 #else
910  cv::cuda::GpuMat imgGpu(imgRoi);
911  cv::cuda::GpuMat maskGpu(maskRoi);
912  (*_gpuSurf.get())(imgGpu, maskGpu, keypoints);
913 #endif
914  }
915  else
916  {
917  _surf->detect(imgRoi, keypoints, maskRoi);
918  }
919 #else
920  UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
921 #endif
922  return keypoints;
923 }
924 
925 cv::Mat SURF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
926 {
927  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
928  cv::Mat descriptors;
929 #ifdef RTABMAP_NONFREE
930  if(gpuVersion_)
931  {
932 #if CV_MAJOR_VERSION < 3
933  cv::gpu::GpuMat imgGpu(image);
934  cv::gpu::GpuMat descriptorsGPU;
935  (*_gpuSurf.obj)(imgGpu, cv::gpu::GpuMat(), keypoints, descriptorsGPU, true);
936 #else
937  cv::cuda::GpuMat imgGpu(image);
938  cv::cuda::GpuMat descriptorsGPU;
939  (*_gpuSurf.get())(imgGpu, cv::cuda::GpuMat(), keypoints, descriptorsGPU, true);
940 #endif
941 
942  // Download descriptors
943  if (descriptorsGPU.empty())
944  descriptors = cv::Mat();
945  else
946  {
947  UASSERT(descriptorsGPU.type() == CV_32F);
948  descriptors = cv::Mat(descriptorsGPU.size(), CV_32F);
949  descriptorsGPU.download(descriptors);
950  }
951  }
952  else
953  {
954  _surf->compute(image, keypoints, descriptors);
955  }
956 #else
957  UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
958 #endif
959 
960  return descriptors;
961 }
962 
964 //SIFT
966 SIFT::SIFT(const ParametersMap & parameters) :
967  nOctaveLayers_(Parameters::defaultSIFTNOctaveLayers()),
968  contrastThreshold_(Parameters::defaultSIFTContrastThreshold()),
969  edgeThreshold_(Parameters::defaultSIFTEdgeThreshold()),
970  sigma_(Parameters::defaultSIFTSigma()),
971  rootSIFT_(Parameters::defaultSIFTRootSIFT())
972 {
973  parseParameters(parameters);
974 }
975 
977 {
978 }
979 
980 void SIFT::parseParameters(const ParametersMap & parameters)
981 {
982  Feature2D::parseParameters(parameters);
983 
984  Parameters::parse(parameters, Parameters::kSIFTContrastThreshold(), contrastThreshold_);
985  Parameters::parse(parameters, Parameters::kSIFTEdgeThreshold(), edgeThreshold_);
986  Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_);
987  Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_);
988  Parameters::parse(parameters, Parameters::kSIFTRootSIFT(), rootSIFT_);
989 
990 #if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
991 #ifdef RTABMAP_NONFREE
992 #if CV_MAJOR_VERSION < 3
994 #else
996 #endif
997 #else
998  UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
999 #endif
1000 #else // >=4.4, >=3.4.11
1001  _sift = CV_SIFT::create(this->getMaxFeatures(), nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_);
1002 #endif
1003 }
1004 
1005 std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1006 {
1007  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1008  std::vector<cv::KeyPoint> keypoints;
1009  cv::Mat imgRoi(image, roi);
1010  cv::Mat maskRoi;
1011  if(!mask.empty())
1012  {
1013  maskRoi = cv::Mat(mask, roi);
1014  }
1015 #if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
1016 #ifdef RTABMAP_NONFREE
1017  _sift->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1018 #else
1019  UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
1020 #endif
1021 #else // >=4.4, >=3.4.11
1022  _sift->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1023 #endif
1024  return keypoints;
1025 }
1026 
1027 cv::Mat SIFT::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1028 {
1029  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1030  cv::Mat descriptors;
1031 #if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
1032 #ifdef RTABMAP_NONFREE
1033  _sift->compute(image, keypoints, descriptors);
1034 #else
1035  UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
1036 #endif
1037 #else // >=4.4, >=3.4.11
1038  _sift->compute(image, keypoints, descriptors);
1039 #endif
1040  if( rootSIFT_ && !descriptors.empty())
1041  {
1042  UDEBUG("Performing RootSIFT...");
1043  // see http://www.pyimagesearch.com/2015/04/13/implementing-rootsift-in-python-and-opencv/
1044  // apply the Hellinger kernel by first L1-normalizing and taking the
1045  // square-root
1046  for(int i=0; i<descriptors.rows; ++i)
1047  {
1048  // By taking the L1 norm, followed by the square-root, we have
1049  // already L2 normalized the feature vector and further normalization
1050  // is not needed.
1051  descriptors.row(i) = descriptors.row(i) / cv::sum(descriptors.row(i))[0];
1052  cv::sqrt(descriptors.row(i), descriptors.row(i));
1053  }
1054  }
1055  return descriptors;
1056 }
1057 
1059 //ORB
1061 ORB::ORB(const ParametersMap & parameters) :
1062  scaleFactor_(Parameters::defaultORBScaleFactor()),
1063  nLevels_(Parameters::defaultORBNLevels()),
1064  edgeThreshold_(Parameters::defaultORBEdgeThreshold()),
1065  firstLevel_(Parameters::defaultORBFirstLevel()),
1066  WTA_K_(Parameters::defaultORBWTA_K()),
1067  scoreType_(Parameters::defaultORBScoreType()),
1068  patchSize_(Parameters::defaultORBPatchSize()),
1069  gpu_(Parameters::defaultORBGpu()),
1070  fastThreshold_(Parameters::defaultFASTThreshold()),
1071  nonmaxSuppresion_(Parameters::defaultFASTNonmaxSuppression())
1072 {
1073  parseParameters(parameters);
1074 }
1075 
1077 {
1078 }
1079 
1080 void ORB::parseParameters(const ParametersMap & parameters)
1081 {
1082  Feature2D::parseParameters(parameters);
1083 
1084  Parameters::parse(parameters, Parameters::kORBScaleFactor(), scaleFactor_);
1085  Parameters::parse(parameters, Parameters::kORBNLevels(), nLevels_);
1086  Parameters::parse(parameters, Parameters::kORBEdgeThreshold(), edgeThreshold_);
1087  Parameters::parse(parameters, Parameters::kORBFirstLevel(), firstLevel_);
1088  Parameters::parse(parameters, Parameters::kORBWTA_K(), WTA_K_);
1089  Parameters::parse(parameters, Parameters::kORBScoreType(), scoreType_);
1090  Parameters::parse(parameters, Parameters::kORBPatchSize(), patchSize_);
1091  Parameters::parse(parameters, Parameters::kORBGpu(), gpu_);
1092 
1093  Parameters::parse(parameters, Parameters::kFASTThreshold(), fastThreshold_);
1094  Parameters::parse(parameters, Parameters::kFASTNonmaxSuppression(), nonmaxSuppresion_);
1095 
1096 #if CV_MAJOR_VERSION < 3
1097 #ifdef HAVE_OPENCV_GPU
1098  if(gpu_ && cv::gpu::getCudaEnabledDeviceCount() == 0)
1099  {
1100  UWARN("GPU version of ORB not available! Using CPU version instead...");
1101  gpu_ = false;
1102  }
1103 #else
1104  if(gpu_)
1105  {
1106  UWARN("GPU version of ORB not available (OpenCV not built with gpu/cuda module)! Using CPU version instead...");
1107  gpu_ = false;
1108  }
1109 #endif
1110 #else
1111 #ifndef HAVE_OPENCV_CUDAFEATURES2D
1112  if(gpu_)
1113  {
1114  UWARN("GPU version of ORB not available (OpenCV cudafeatures2d module)! Using CPU version instead...");
1115  gpu_ = false;
1116  }
1117 #endif
1118  if(gpu_ && cv::cuda::getCudaEnabledDeviceCount() == 0)
1119  {
1120  UWARN("GPU version of ORB not available (no GPU found)! Using CPU version instead...");
1121  gpu_ = false;
1122  }
1123 #endif
1124  if(gpu_)
1125  {
1126 #if CV_MAJOR_VERSION < 3
1127 #ifdef HAVE_OPENCV_GPU
1129  _gpuOrb->setFastParams(fastThreshold_, nonmaxSuppresion_);
1130 #else
1131  UFATAL("not supposed to be here");
1132 #endif
1133 #else
1134 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1136 #endif
1137 #endif
1138  }
1139  else
1140  {
1141 #if CV_MAJOR_VERSION < 3
1142  _orb = cv::Ptr<CV_ORB>(new CV_ORB(this->getMaxFeatures(), scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, scoreType_, patchSize_, parameters));
1143 #elif CV_MAJOR_VERSION > 3
1144  _orb = CV_ORB::create(this->getMaxFeatures(), scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, (cv::ORB::ScoreType)scoreType_, patchSize_, fastThreshold_);
1145 #else
1146  _orb = CV_ORB::create(this->getMaxFeatures(), scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, scoreType_, patchSize_, fastThreshold_);
1147 #endif
1148  }
1149 }
1150 
1151 std::vector<cv::KeyPoint> ORB::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1152 {
1153  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1154  std::vector<cv::KeyPoint> keypoints;
1155  cv::Mat imgRoi(image, roi);
1156  cv::Mat maskRoi;
1157  if(!mask.empty())
1158  {
1159  maskRoi = cv::Mat(mask, roi);
1160  }
1161 
1162  if(gpu_)
1163  {
1164 #if CV_MAJOR_VERSION < 3
1165 #ifdef HAVE_OPENCV_GPU
1166  cv::gpu::GpuMat imgGpu(imgRoi);
1167  cv::gpu::GpuMat maskGpu(maskRoi);
1168  (*_gpuOrb.obj)(imgGpu, maskGpu, keypoints);
1169 #else
1170  UERROR("Cannot use ORBGPU because OpenCV is not built with gpu module.");
1171 #endif
1172 #else
1173 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1174  cv::cuda::GpuMat d_image(imgRoi);
1175  cv::cuda::GpuMat d_mask(maskRoi);
1176  try {
1177  _gpuOrb->detectAndCompute(d_image, d_mask, keypoints, cv::cuda::GpuMat(), false);
1178  } catch (cv::Exception& e) {
1179  const char* err_msg = e.what();
1180  UWARN("OpenCV exception caught: %s", err_msg);
1181  }
1182 #endif
1183 #endif
1184  }
1185  else
1186  {
1187  _orb->detect(imgRoi, keypoints, maskRoi);
1188  }
1189 
1190  return keypoints;
1191 }
1192 
1193 cv::Mat ORB::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1194 {
1195  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1196  cv::Mat descriptors;
1197  if(image.empty())
1198  {
1199  ULOGGER_ERROR("Image is null ?!?");
1200  return descriptors;
1201  }
1202  if(gpu_)
1203  {
1204 #if CV_MAJOR_VERSION < 3
1205 #ifdef HAVE_OPENCV_GPU
1206  cv::gpu::GpuMat imgGpu(image);
1207  cv::gpu::GpuMat descriptorsGPU;
1208  (*_gpuOrb.obj)(imgGpu, cv::gpu::GpuMat(), keypoints, descriptorsGPU);
1209  // Download descriptors
1210  if (descriptorsGPU.empty())
1211  descriptors = cv::Mat();
1212  else
1213  {
1214  UASSERT(descriptorsGPU.type() == CV_32F);
1215  descriptors = cv::Mat(descriptorsGPU.size(), CV_32F);
1216  descriptorsGPU.download(descriptors);
1217  }
1218 #else
1219  UERROR("GPU version of ORB not available (OpenCV not built with gpu/cuda module)! Using CPU version instead...");
1220 #endif
1221 #else
1222 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1223  cv::cuda::GpuMat d_image(image);
1224  cv::cuda::GpuMat d_descriptors;
1225  try {
1226  _gpuOrb->detectAndCompute(d_image, cv::cuda::GpuMat(), keypoints, d_descriptors, true);
1227  } catch (cv::Exception& e) {
1228  const char* err_msg = e.what();
1229  UWARN("OpenCV exception caught: %s", err_msg);
1230  }
1231  // Download descriptors
1232  if (d_descriptors.empty())
1233  descriptors = cv::Mat();
1234  else
1235  {
1236  UASSERT(d_descriptors.type() == CV_32F || d_descriptors.type() == CV_8U);
1237  d_descriptors.download(descriptors);
1238  }
1239 #endif
1240 #endif
1241  }
1242  else
1243  {
1244  _orb->compute(image, keypoints, descriptors);
1245  }
1246 
1247  return descriptors;
1248 }
1249 
1251 //FAST
1253 FAST::FAST(const ParametersMap & parameters) :
1254  threshold_(Parameters::defaultFASTThreshold()),
1255  nonmaxSuppression_(Parameters::defaultFASTNonmaxSuppression()),
1256  gpu_(Parameters::defaultFASTGpu()),
1257  gpuKeypointsRatio_(Parameters::defaultFASTGpuKeypointsRatio()),
1258  minThreshold_(Parameters::defaultFASTMinThreshold()),
1259  maxThreshold_(Parameters::defaultFASTMaxThreshold()),
1260  gridRows_(Parameters::defaultFASTGridRows()),
1261  gridCols_(Parameters::defaultFASTGridCols()),
1262  fastCV_(Parameters::defaultFASTCV()),
1263  fastCVinit_(false),
1264  fastCVMaxFeatures_(10000),
1265  fastCVLastImageHeight_(0)
1266 {
1267 #ifdef RTABMAP_FASTCV
1268  char sVersion[128] = { 0 };
1269  fcvGetVersion(sVersion, 128);
1270  UINFO("fastcv version = %s", sVersion);
1271  int ix;
1272  if ((ix = fcvSetOperationMode(FASTCV_OP_PERFORMANCE)))
1273  {
1274  UERROR("fcvSetOperationMode return=%d, OpenCV FAST will be used instead!", ix);
1275  fastCV_ = 0;
1276  }
1277  else
1278  {
1279  fcvMemInit();
1280 
1281  if (!(fastCVCorners_ = (uint32_t*)fcvMemAlloc(fastCVMaxFeatures_ * sizeof(uint32_t) * 2, 16)) ||
1282  !(fastCVCornerScores_ = (uint32_t*)fcvMemAlloc( fastCVMaxFeatures_ * sizeof(uint32_t), 16 )))
1283  {
1284  UERROR("could not alloc fastcv mem, using opencv fast instead!");
1285 
1286  if (fastCVCorners_)
1287  {
1288  fcvMemFree(fastCVCorners_);
1289  fastCVCorners_ = NULL;
1290  }
1291  if (fastCVCornerScores_)
1292  {
1293  fcvMemFree(fastCVCornerScores_);
1295  }
1296  }
1297  else
1298  {
1299  fastCVinit_ = true;
1300  }
1301  }
1302  #endif
1303  parseParameters(parameters);
1304 }
1305 
1307 {
1308 #ifdef RTABMAP_FASTCV
1309  if(fastCVinit_)
1310  {
1311  fcvMemDeInit();
1312 
1313  if (fastCVCorners_)
1314  fcvMemFree(fastCVCorners_);
1315  if (fastCVCornerScores_)
1316  fcvMemFree(fastCVCornerScores_);
1317  if (fastCVTempBuf_)
1318  fcvMemFree(fastCVTempBuf_);
1319  }
1320 #endif
1321 }
1322 
1323 void FAST::parseParameters(const ParametersMap & parameters)
1324 {
1325  Feature2D::parseParameters(parameters);
1326 
1327  Parameters::parse(parameters, Parameters::kFASTThreshold(), threshold_);
1328  Parameters::parse(parameters, Parameters::kFASTNonmaxSuppression(), nonmaxSuppression_);
1329  Parameters::parse(parameters, Parameters::kFASTGpu(), gpu_);
1330  Parameters::parse(parameters, Parameters::kFASTGpuKeypointsRatio(), gpuKeypointsRatio_);
1331 
1332  Parameters::parse(parameters, Parameters::kFASTMinThreshold(), minThreshold_);
1333  Parameters::parse(parameters, Parameters::kFASTMaxThreshold(), maxThreshold_);
1334  Parameters::parse(parameters, Parameters::kFASTGridRows(), gridRows_);
1335  Parameters::parse(parameters, Parameters::kFASTGridCols(), gridCols_);
1336 
1337  Parameters::parse(parameters, Parameters::kFASTCV(), fastCV_);
1338  UASSERT(fastCV_ == 0 || fastCV_ == 9 || fastCV_ == 10);
1339 
1342 
1343 #if CV_MAJOR_VERSION < 3
1344 #ifdef HAVE_OPENCV_GPU
1345  if(gpu_ && cv::gpu::getCudaEnabledDeviceCount() == 0)
1346  {
1347  UWARN("GPU version of FAST not available! Using CPU version instead...");
1348  gpu_ = false;
1349  }
1350 #else
1351  if(gpu_)
1352  {
1353  UWARN("GPU version of FAST not available (OpenCV not built with gpu/cuda module)! Using CPU version instead...");
1354  gpu_ = false;
1355  }
1356 #endif
1357 #else
1358 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1359  if(gpu_ && cv::cuda::getCudaEnabledDeviceCount() == 0)
1360  {
1361  UWARN("GPU version of FAST not available! Using CPU version instead...");
1362  gpu_ = false;
1363  }
1364 #else
1365  if(gpu_)
1366  {
1367  UWARN("GPU version of FAST not available (OpenCV cudafeatures2d module)! Using CPU version instead...");
1368  gpu_ = false;
1369  }
1370 #endif
1371 #endif
1372  if(gpu_)
1373  {
1374 #if CV_MAJOR_VERSION < 3
1375 #ifdef HAVE_OPENCV_GPU
1377 #else
1378  UFATAL("not supposed to be here!");
1379 #endif
1380 #else
1381 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1382  UFATAL("not implemented");
1383 #endif
1384 #endif
1385  }
1386  else
1387  {
1388 #if CV_MAJOR_VERSION < 3
1389  if(gridRows_ > 0 && gridCols_ > 0)
1390  {
1391  UDEBUG("grid max features = %d", this->getMaxFeatures());
1392  cv::Ptr<cv::FeatureDetector> fastAdjuster = cv::Ptr<cv::FastAdjuster>(new cv::FastAdjuster(threshold_, nonmaxSuppression_, minThreshold_, maxThreshold_));
1393  _fast = cv::Ptr<cv::FeatureDetector>(new cv::GridAdaptedFeatureDetector(fastAdjuster, this->getMaxFeatures(), gridRows_, gridCols_));
1394  }
1395  else
1396  {
1397  if(gridRows_ > 0)
1398  {
1399  UWARN("Parameter \"%s\" is set (value=%d) but not \"%s\"! Grid adaptor will not be added.",
1400  Parameters::kFASTGridRows().c_str(), gridRows_, Parameters::kFASTGridCols().c_str());
1401  }
1402  else if(gridCols_ > 0)
1403  {
1404  UWARN("Parameter \"%s\" is set (value=%d) but not \"%s\"! Grid adaptor will not be added.",
1405  Parameters::kFASTGridCols().c_str(), gridCols_, Parameters::kFASTGridRows().c_str());
1406  }
1407  _fast = cv::Ptr<cv::FeatureDetector>(new CV_FAST(threshold_, nonmaxSuppression_));
1408  }
1409 #else
1410  _fast = CV_FAST::create(threshold_, nonmaxSuppression_);
1411 #endif
1412  }
1413 }
1414 
1415 std::vector<cv::KeyPoint> FAST::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1416 {
1417  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1418  std::vector<cv::KeyPoint> keypoints;
1419 
1420 #ifdef RTABMAP_FASTCV
1421  if(fastCV_>0)
1422  {
1423  // Note: mask not supported, it should be the inverse of the current mask used (0=where to extract)
1424  uint32_t nCorners = 0;
1425 
1427  if (nonmaxSuppression_)
1428  {
1429  if(fastCVTempBuf_==NULL || (fastCVTempBuf_!= NULL && fastCVLastImageHeight_!= image.rows))
1430  {
1431  if (fastCVTempBuf_)
1432  {
1433  fcvMemFree(fastCVTempBuf_);
1434  fastCVTempBuf_ = NULL;
1435  }
1436  if(!(fastCVTempBuf_ = (uint32_t*)fcvMemAlloc( (3*fastCVMaxFeatures_+image.rows+1)*4, 16 )))
1437  {
1438  UERROR("could not alloc fastcv mem for temp buf (%s=true)", Parameters::kFASTNonmaxSuppression().c_str());
1440  return keypoints;
1441  }
1442  fastCVLastImageHeight_ = image.rows;
1443  }
1444  }
1445 
1446  // image.data should be 128 bits aligned
1447  UDEBUG("%dx%d (step=%d) thr=%d maxFeatures=%d", image.cols, image.rows, image.step1(), threshold_, fastCVMaxFeatures_);
1448  if(fastCV_ == 10)
1449  {
1450  fcvCornerFast10Scoreu8(image.data, image.cols, image.rows, 0, threshold_, 0, fastCVCorners_, fastCVCornerScores_, fastCVMaxFeatures_, &nCorners, nonmaxSuppression_?1:0, fastCVTempBuf_);
1451  }
1452  else
1453  {
1454  fcvCornerFast9Scoreu8_v2(image.data, image.cols, image.rows, image.step1(), threshold_, 0, fastCVCorners_, fastCVCornerScores_, fastCVMaxFeatures_, &nCorners, nonmaxSuppression_?1:0, fastCVTempBuf_);
1455  }
1456  UDEBUG("number of corners found = %d:", nCorners);
1457  keypoints.resize(nCorners);
1458  for (uint32_t i = 0; i < nCorners; i++)
1459  {
1460  keypoints[i].pt.x = fastCVCorners_[i * 2];
1461  keypoints[i].pt.y = fastCVCorners_[(i * 2) + 1];
1462  keypoints[i].size = 3;
1463  keypoints[i].response = fastCVCornerScores_[i];
1464  }
1465 
1466  if(this->getMaxFeatures() > 0)
1467  {
1468  this->limitKeypoints(keypoints, this->getMaxFeatures());
1469  }
1470  return keypoints;
1471  }
1472 #endif
1473 
1474  if(fastCV_>0)
1475  {
1476  UWARN( "RTAB-Map is not built with FastCV support. OpenCV's FAST is used instead. "
1477  "Please set %s to 0. This message will only appear once.",
1478  Parameters::kFASTCV().c_str());
1479  fastCV_ = 0;
1480  }
1481 
1482  cv::Mat imgRoi(image, roi);
1483  cv::Mat maskRoi;
1484  if(!mask.empty())
1485  {
1486  maskRoi = cv::Mat(mask, roi);
1487  }
1488  if(gpu_)
1489  {
1490 #if CV_MAJOR_VERSION < 3
1491 #ifdef HAVE_OPENCV_GPU
1492  cv::gpu::GpuMat imgGpu(imgRoi);
1493  cv::gpu::GpuMat maskGpu(maskRoi);
1494  (*_gpuFast.obj)(imgGpu, maskGpu, keypoints);
1495 #else
1496  UERROR("Cannot use FAST GPU because OpenCV is not built with gpu module.");
1497 #endif
1498 #else
1499 #ifdef HAVE_OPENCV_CUDAFEATURES2D
1500  UFATAL("not implemented");
1501 #endif
1502 #endif
1503  }
1504  else
1505  {
1506  _fast->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1507  }
1508  return keypoints;
1509 }
1510 
1512 //FAST-BRIEF
1515  FAST(parameters),
1516  bytes_(Parameters::defaultBRIEFBytes())
1517 {
1518  parseParameters(parameters);
1519 }
1520 
1522 {
1523 }
1524 
1526 {
1527  FAST::parseParameters(parameters);
1528 
1529  Parameters::parse(parameters, Parameters::kBRIEFBytes(), bytes_);
1530 #if CV_MAJOR_VERSION < 3
1531  _brief = cv::Ptr<CV_BRIEF>(new CV_BRIEF(bytes_));
1532 #else
1533 #ifdef HAVE_OPENCV_XFEATURES2D
1534  _brief = CV_BRIEF::create(bytes_);
1535 #else
1536  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Brief cannot be used!");
1537 #endif
1538 #endif
1539 }
1540 
1541 cv::Mat FAST_BRIEF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1542 {
1543  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1544  cv::Mat descriptors;
1545 #if CV_MAJOR_VERSION < 3
1546  _brief->compute(image, keypoints, descriptors);
1547 #else
1548 #ifdef HAVE_OPENCV_XFEATURES2D
1549  _brief->compute(image, keypoints, descriptors);
1550 #else
1551  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Brief cannot be used!");
1552 #endif
1553 #endif
1554  return descriptors;
1555 }
1556 
1558 //FAST-FREAK
1561  FAST(parameters),
1562  orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
1563  scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
1564  patternScale_(Parameters::defaultFREAKPatternScale()),
1565  nOctaves_(Parameters::defaultFREAKNOctaves())
1566 {
1567  parseParameters(parameters);
1568 }
1569 
1571 {
1572 }
1573 
1575 {
1576  FAST::parseParameters(parameters);
1577 
1578  Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
1579  Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
1580  Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
1581  Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
1582 
1583 #if CV_MAJOR_VERSION < 3
1585 #else
1586 #ifdef HAVE_OPENCV_XFEATURES2D
1588 #else
1589  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1590 #endif
1591 #endif
1592 }
1593 
1594 cv::Mat FAST_FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1595 {
1596  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1597  cv::Mat descriptors;
1598 #if CV_MAJOR_VERSION < 3
1599  _freak->compute(image, keypoints, descriptors);
1600 #else
1601 #ifdef HAVE_OPENCV_XFEATURES2D
1602  _freak->compute(image, keypoints, descriptors);
1603 #else
1604  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1605 #endif
1606 #endif
1607  return descriptors;
1608 }
1609 
1611 //GFTT
1613 GFTT::GFTT(const ParametersMap & parameters) :
1614  _qualityLevel(Parameters::defaultGFTTQualityLevel()),
1615  _minDistance(Parameters::defaultGFTTMinDistance()),
1616  _blockSize(Parameters::defaultGFTTBlockSize()),
1617  _useHarrisDetector(Parameters::defaultGFTTUseHarrisDetector()),
1618  _k(Parameters::defaultGFTTK())
1619 {
1620  parseParameters(parameters);
1621 }
1622 
1624 {
1625 }
1626 
1627 void GFTT::parseParameters(const ParametersMap & parameters)
1628 {
1629  Feature2D::parseParameters(parameters);
1630 
1631  Parameters::parse(parameters, Parameters::kGFTTQualityLevel(), _qualityLevel);
1632  Parameters::parse(parameters, Parameters::kGFTTMinDistance(), _minDistance);
1633  Parameters::parse(parameters, Parameters::kGFTTBlockSize(), _blockSize);
1634  Parameters::parse(parameters, Parameters::kGFTTUseHarrisDetector(), _useHarrisDetector);
1635  Parameters::parse(parameters, Parameters::kGFTTK(), _k);
1636 
1637 #if CV_MAJOR_VERSION < 3
1638  _gftt = cv::Ptr<CV_GFTT>(new CV_GFTT(this->getMaxFeatures(), _qualityLevel, _minDistance, _blockSize, _useHarrisDetector ,_k));
1639 #else
1641 #endif
1642 }
1643 
1644 std::vector<cv::KeyPoint> GFTT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1645 {
1646  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1647  std::vector<cv::KeyPoint> keypoints;
1648  cv::Mat imgRoi(image, roi);
1649  cv::Mat maskRoi;
1650  if(!mask.empty())
1651  {
1652  maskRoi = cv::Mat(mask, roi);
1653  }
1654  _gftt->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1655  return keypoints;
1656 }
1657 
1659 //FAST-BRIEF
1662  GFTT(parameters),
1663  bytes_(Parameters::defaultBRIEFBytes())
1664 {
1665  parseParameters(parameters);
1666 }
1667 
1669 {
1670 }
1671 
1673 {
1674  GFTT::parseParameters(parameters);
1675 
1676  Parameters::parse(parameters, Parameters::kBRIEFBytes(), bytes_);
1677 #if CV_MAJOR_VERSION < 3
1678  _brief = cv::Ptr<CV_BRIEF>(new CV_BRIEF(bytes_));
1679 #else
1680 #ifdef HAVE_OPENCV_XFEATURES2D
1681  _brief = CV_BRIEF::create(bytes_);
1682 #else
1683  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Brief cannot be used!");
1684 #endif
1685 #endif
1686 }
1687 
1688 cv::Mat GFTT_BRIEF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1689 {
1690  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1691  cv::Mat descriptors;
1692 #if CV_MAJOR_VERSION < 3
1693  _brief->compute(image, keypoints, descriptors);
1694 #else
1695 #ifdef HAVE_OPENCV_XFEATURES2D
1696  _brief->compute(image, keypoints, descriptors);
1697 #else
1698  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Brief cannot be used!");
1699 #endif
1700 #endif
1701  return descriptors;
1702 }
1703 
1705 //GFTT-FREAK
1708  GFTT(parameters),
1709  orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
1710  scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
1711  patternScale_(Parameters::defaultFREAKPatternScale()),
1712  nOctaves_(Parameters::defaultFREAKNOctaves())
1713 {
1714  parseParameters(parameters);
1715 }
1716 
1718 {
1719 }
1720 
1722 {
1723  GFTT::parseParameters(parameters);
1724 
1725  Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
1726  Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
1727  Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
1728  Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
1729 
1730 #if CV_MAJOR_VERSION < 3
1732 #else
1733 #ifdef HAVE_OPENCV_XFEATURES2D
1735 #else
1736  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1737 #endif
1738 #endif
1739 }
1740 
1741 cv::Mat GFTT_FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1742 {
1743  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1744  cv::Mat descriptors;
1745 #if CV_MAJOR_VERSION < 3
1746  _freak->compute(image, keypoints, descriptors);
1747 #else
1748 #ifdef HAVE_OPENCV_XFEATURES2D
1749  _freak->compute(image, keypoints, descriptors);
1750 #else
1751  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1752 #endif
1753 #endif
1754  return descriptors;
1755 }
1756 
1758 //SURF-FREAK
1761  SURF(parameters),
1762  orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
1763  scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
1764  patternScale_(Parameters::defaultFREAKPatternScale()),
1765  nOctaves_(Parameters::defaultFREAKNOctaves())
1766 {
1767  parseParameters(parameters);
1768 }
1769 
1771 {
1772 }
1773 
1775 {
1776  SURF::parseParameters(parameters);
1777 
1778  Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
1779  Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
1780  Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
1781  Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
1782 
1783 #if CV_MAJOR_VERSION < 3
1785 #else
1786 #ifdef HAVE_OPENCV_XFEATURES2D
1788 #else
1789  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1790 #endif
1791 #endif
1792 }
1793 
1794 cv::Mat SURF_FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1795 {
1796  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1797  cv::Mat descriptors;
1798 #if CV_MAJOR_VERSION < 3
1799  _freak->compute(image, keypoints, descriptors);
1800 #else
1801 #ifdef HAVE_OPENCV_XFEATURES2D
1802  _freak->compute(image, keypoints, descriptors);
1803 #else
1804  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
1805 #endif
1806 #endif
1807  return descriptors;
1808 }
1809 
1811 //GFTT-ORB
1813 GFTT_ORB::GFTT_ORB(const ParametersMap & parameters) :
1814  GFTT(parameters),
1815  _orb(parameters)
1816 {
1817  parseParameters(parameters);
1818 }
1819 
1821 {
1822 }
1823 
1825 {
1826  GFTT::parseParameters(parameters);
1827  _orb.parseParameters(parameters);
1828 }
1829 
1830 cv::Mat GFTT_ORB::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1831 {
1832  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1833  return _orb.generateDescriptors(image, keypoints);
1834 }
1835 
1837 //BRISK
1839 BRISK::BRISK(const ParametersMap & parameters) :
1840  thresh_(Parameters::defaultBRISKThresh()),
1841  octaves_(Parameters::defaultBRISKOctaves()),
1842  patternScale_(Parameters::defaultBRISKPatternScale())
1843 {
1844  parseParameters(parameters);
1845 }
1846 
1848 {
1849 }
1850 
1851 void BRISK::parseParameters(const ParametersMap & parameters)
1852 {
1853  Feature2D::parseParameters(parameters);
1854 
1855  Parameters::parse(parameters, Parameters::kBRISKThresh(), thresh_);
1856  Parameters::parse(parameters, Parameters::kBRISKOctaves(), octaves_);
1857  Parameters::parse(parameters, Parameters::kBRISKPatternScale(), patternScale_);
1858 
1859 #if CV_MAJOR_VERSION < 3
1860  brisk_ = cv::Ptr<CV_BRISK>(new CV_BRISK(thresh_, octaves_, patternScale_));
1861 #else
1862  brisk_ = CV_BRISK::create(thresh_, octaves_, patternScale_);
1863 #endif
1864 }
1865 
1866 std::vector<cv::KeyPoint> BRISK::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1867 {
1868  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1869  std::vector<cv::KeyPoint> keypoints;
1870  cv::Mat imgRoi(image, roi);
1871  cv::Mat maskRoi;
1872  if(!mask.empty())
1873  {
1874  maskRoi = cv::Mat(mask, roi);
1875  }
1876  brisk_->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1877  return keypoints;
1878 }
1879 
1880 cv::Mat BRISK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1881 {
1882  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1883  cv::Mat descriptors;
1884  brisk_->compute(image, keypoints, descriptors);
1885  return descriptors;
1886 }
1887 
1889 //KAZE
1891 KAZE::KAZE(const ParametersMap & parameters) :
1892  extended_(Parameters::defaultKAZEExtended()),
1893  upright_(Parameters::defaultKAZEUpright()),
1894  threshold_(Parameters::defaultKAZEThreshold()),
1895  nOctaves_(Parameters::defaultKAZENOctaves()),
1896  nOctaveLayers_(Parameters::defaultKAZENOctaveLayers()),
1897  diffusivity_(Parameters::defaultKAZEDiffusivity())
1898 {
1899  parseParameters(parameters);
1900 }
1901 
1903 {
1904 }
1905 
1906 void KAZE::parseParameters(const ParametersMap & parameters)
1907 {
1908  Feature2D::parseParameters(parameters);
1909 
1910  Parameters::parse(parameters, Parameters::kKAZEExtended(), extended_);
1911  Parameters::parse(parameters, Parameters::kKAZEUpright(), upright_);
1912  Parameters::parse(parameters, Parameters::kKAZEThreshold(), threshold_);
1913  Parameters::parse(parameters, Parameters::kKAZENOctaves(), nOctaves_);
1914  Parameters::parse(parameters, Parameters::kKAZENOctaveLayers(), nOctaveLayers_);
1915  Parameters::parse(parameters, Parameters::kKAZEDiffusivity(), diffusivity_);
1916 
1917 #if CV_MAJOR_VERSION > 3
1918  kaze_ = cv::KAZE::create(extended_, upright_, threshold_, nOctaves_, nOctaveLayers_, (cv::KAZE::DiffusivityType)diffusivity_);
1919 #elif CV_MAJOR_VERSION > 2
1920  kaze_ = cv::KAZE::create(extended_, upright_, threshold_, nOctaves_, nOctaveLayers_, diffusivity_);
1921 #else
1922  UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
1923 #endif
1924 }
1925 
1926 std::vector<cv::KeyPoint> KAZE::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1927 {
1928  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1929  std::vector<cv::KeyPoint> keypoints;
1930 #if CV_MAJOR_VERSION > 2
1931  cv::Mat imgRoi(image, roi);
1932  cv::Mat maskRoi;
1933  if (!mask.empty())
1934  {
1935  maskRoi = cv::Mat(mask, roi);
1936  }
1937  kaze_->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
1938 #else
1939  UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
1940 #endif
1941  return keypoints;
1942 }
1943 
1944 cv::Mat KAZE::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
1945 {
1946  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1947  cv::Mat descriptors;
1948 #if CV_MAJOR_VERSION > 2
1949  kaze_->compute(image, keypoints, descriptors);
1950 #else
1951  UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
1952 #endif
1953  return descriptors;
1954 }
1955 
1957 //ORBOctree
1960  scaleFactor_(Parameters::defaultORBScaleFactor()),
1961  nLevels_(Parameters::defaultORBNLevels()),
1962  patchSize_(Parameters::defaultORBPatchSize()),
1963  edgeThreshold_(Parameters::defaultORBEdgeThreshold()),
1964  fastThreshold_(Parameters::defaultFASTThreshold()),
1965  fastMinThreshold_(Parameters::defaultFASTMinThreshold())
1966 {
1967  parseParameters(parameters);
1968 }
1969 
1971 {
1972 }
1973 
1975 {
1976  Feature2D::parseParameters(parameters);
1977 
1978  Parameters::parse(parameters, Parameters::kORBScaleFactor(), scaleFactor_);
1979  Parameters::parse(parameters, Parameters::kORBNLevels(), nLevels_);
1980  Parameters::parse(parameters, Parameters::kORBPatchSize(), patchSize_);
1981  Parameters::parse(parameters, Parameters::kORBEdgeThreshold(), edgeThreshold_);
1982 
1983  Parameters::parse(parameters, Parameters::kFASTThreshold(), fastThreshold_);
1984  Parameters::parse(parameters, Parameters::kFASTMinThreshold(), fastMinThreshold_);
1985 
1986 #ifdef RTABMAP_ORB_OCTREE
1988 #else
1989  UWARN("RTAB-Map is not built with ORB OcTree option enabled so ORB OcTree feature cannot be used!");
1990 #endif
1991 }
1992 
1993 std::vector<cv::KeyPoint> ORBOctree::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
1994 {
1995  std::vector<cv::KeyPoint> keypoints;
1996  descriptors_ = cv::Mat();
1997 #ifdef RTABMAP_ORB_OCTREE
1998  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
1999  cv::Mat imgRoi(image, roi);
2000  cv::Mat maskRoi;
2001  if(!mask.empty())
2002  {
2003  maskRoi = cv::Mat(mask, roi);
2004  }
2005 
2006  (*_orb)(imgRoi, maskRoi, keypoints, descriptors_);
2007 
2008  if((int)keypoints.size() > this->getMaxFeatures())
2009  {
2010  limitKeypoints(keypoints, descriptors_, this->getMaxFeatures());
2011  }
2012 #else
2013  UWARN("RTAB-Map is not built with ORB OcTree option enabled so ORB OcTree feature cannot be used!");
2014 #endif
2015  return keypoints;
2016 }
2017 
2018 cv::Mat ORBOctree::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
2019 {
2020 #ifdef RTABMAP_ORB_OCTREE
2021  UASSERT_MSG((int)keypoints.size() == descriptors_.rows, uFormat("keypoints=%d descriptors=%d", (int)keypoints.size(), descriptors_.rows).c_str());
2022 #else
2023  UWARN("RTAB-Map is not built with ORB OcTree option enabled so ORB OcTree feature cannot be used!");
2024 #endif
2025  return descriptors_;
2026 }
2027 
2029 //SuperPointTorch
2032  path_(Parameters::defaultSuperPointModelPath()),
2033  threshold_(Parameters::defaultSuperPointThreshold()),
2034  nms_(Parameters::defaultSuperPointNMS()),
2035  minDistance_(Parameters::defaultSuperPointNMSRadius()),
2036  cuda_(Parameters::defaultSuperPointCuda())
2037 {
2038  parseParameters(parameters);
2039 }
2040 
2042 {
2043 }
2044 
2046 {
2047  Feature2D::parseParameters(parameters);
2048 
2049  std::string previousPath = path_;
2050 #ifdef RTABMAP_SUPERPOINT_TORCH
2051  bool previousCuda = cuda_;
2052 #endif
2053  Parameters::parse(parameters, Parameters::kSuperPointModelPath(), path_);
2054  Parameters::parse(parameters, Parameters::kSuperPointThreshold(), threshold_);
2055  Parameters::parse(parameters, Parameters::kSuperPointNMS(), nms_);
2056  Parameters::parse(parameters, Parameters::kSuperPointNMSRadius(), minDistance_);
2057  Parameters::parse(parameters, Parameters::kSuperPointCuda(), cuda_);
2058 
2059 #ifdef RTABMAP_SUPERPOINT_TORCH
2060  if(superPoint_.get() == 0 || path_.compare(previousPath) != 0 || previousCuda != cuda_)
2061  {
2062  superPoint_ = cv::Ptr<SPDetector>(new SPDetector(path_, threshold_, nms_, minDistance_, cuda_));
2063  }
2064  else
2065  {
2066  superPoint_->setThreshold(threshold_);
2067  superPoint_->SetNMS(nms_);
2068  superPoint_->setMinDistance(minDistance_);
2069  }
2070 #else
2071  UWARN("RTAB-Map is not built with SuperPoint Torch support so SuperPoint Torch feature cannot be used!");
2072 #endif
2073 }
2074 
2075 std::vector<cv::KeyPoint> SuperPointTorch::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask)
2076 {
2077 #ifdef RTABMAP_SUPERPOINT_TORCH
2078  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
2079  UASSERT_MSG(roi.x==0 && roi.y ==0, "Not supporting ROI");
2080  return superPoint_->detect(image, mask);
2081 #else
2082  UWARN("RTAB-Map is not built with SuperPoint Torch support so SuperPoint Torch feature cannot be used!");
2083  return std::vector<cv::KeyPoint>();
2084 #endif
2085 }
2086 
2087 cv::Mat SuperPointTorch::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
2088 {
2089 #ifdef RTABMAP_SUPERPOINT_TORCH
2090  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
2091  return superPoint_->compute(keypoints);
2092 #else
2093  UWARN("RTAB-Map is not built with SuperPoint Torch support so SuperPoint Torch feature cannot be used!");
2094  return cv::Mat();
2095 #endif
2096 }
2097 
2098 
2100 //GFTT-DAISY
2103  GFTT(parameters),
2104  orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
2105  scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
2106  patternScale_(Parameters::defaultFREAKPatternScale()),
2107  nOctaves_(Parameters::defaultFREAKNOctaves())
2108 {
2109  parseParameters(parameters);
2110 }
2111 
2113 {
2114 }
2115 
2117 {
2118  GFTT::parseParameters(parameters);
2119 
2120  Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
2121  Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
2122  Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
2123  Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
2124 
2125 #ifdef HAVE_OPENCV_XFEATURES2D
2126  _daisy = CV_DAISY::create();
2127 #else
2128  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so DAISY cannot be used!");
2129 #endif
2130 }
2131 
2132 cv::Mat GFTT_DAISY::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
2133 {
2134  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
2135  cv::Mat descriptors;
2136 #ifdef HAVE_OPENCV_XFEATURES2D
2137  _daisy->compute(image, keypoints, descriptors);
2138 #else
2139  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so DAISY cannot be used!");
2140 #endif
2141  return descriptors;
2142 }
2143 
2145 //SURF-DAISY
2148  SURF(parameters),
2149  orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
2150  scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
2151  patternScale_(Parameters::defaultFREAKPatternScale()),
2152  nOctaves_(Parameters::defaultFREAKNOctaves())
2153 {
2154  parseParameters(parameters);
2155 }
2156 
2158 {
2159 }
2160 
2162 {
2163  SURF::parseParameters(parameters);
2164 
2165  Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
2166  Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
2167  Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
2168  Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
2169 
2170 #ifdef HAVE_OPENCV_XFEATURES2D
2171  _daisy = CV_DAISY::create();
2172 #else
2173  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so DAISY cannot be used!");
2174 #endif
2175 }
2176 
2177 cv::Mat SURF_DAISY::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
2178 {
2179  UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
2180  cv::Mat descriptors;
2181 #ifdef HAVE_OPENCV_XFEATURES2D
2182  _daisy->compute(image, keypoints, descriptors);
2183 #else
2184  UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so DAISY cannot be used!");
2185 #endif
2186  return descriptors;
2187 }
2188 
2189 }
d
GLM_FUNC_DECL genIType mask(genIType const &count)
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
Definition: util3d.cpp:3108
#define NULL
int fastCVLastImageHeight_
Definition: Features2d.h:357
static bool parse(const ParametersMap &parameters, const std::string &key, bool &value)
Definition: Parameters.cpp:476
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual ~BRISK()
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const =0
int nOctaveLayers_
Definition: Features2d.h:550
virtual void parseParameters(const ParametersMap &parameters)
Definition: UTimer.h:46
static void limitKeypoints(std::vector< cv::KeyPoint > &keypoints, int maxKeypoints)
Definition: Features2d.cpp:267
virtual ~SIFT()
Definition: Features2d.cpp:976
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
std::vector< cv::Point3f > generateKeypoints3D(const SensorData &data, const std::vector< cv::KeyPoint > &keypoints) const
Definition: Features2d.cpp:775
double gpuKeypointsRatio_
Definition: Features2d.h:348
FAST_BRIEF(const ParametersMap &parameters=ParametersMap())
GFTT_DAISY(const ParametersMap &parameters=ParametersMap())
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual void parseParameters(const ParametersMap &parameters)
f
SURF_DAISY(const ParametersMap &parameters=ParametersMap())
cv::Mat generateDescriptors(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
Definition: Features2d.cpp:759
virtual void parseParameters(const ParametersMap &parameters)
Definition: Features2d.cpp:443
double _qualityLevel
Definition: Features2d.h:420
cv::Ptr< CV_FREAK > _freak
Definition: Features2d.h:404
GFTT_FREAK(const ParametersMap &parameters=ParametersMap())
cv::SIFT CV_SIFT
Definition: Features2d.h:50
double edgeThreshold_
Definition: Features2d.h:292
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
uint32_t * fastCVCornerScores_
Definition: Features2d.h:359
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual void parseParameters(const ParametersMap &parameters)
Definition: Features2d.cpp:848
void * fastCVTempBuf_
Definition: Features2d.h:360
cv::Ptr< CV_ORB > _orb
Definition: Features2d.h:326
virtual void parseParameters(const ParametersMap &parameters)
cv::Ptr< CV_FREAK > _freak
Definition: Features2d.h:467
float scaleFactor_
Definition: Features2d.h:314
cv::BriefDescriptorExtractor CV_BRIEF
Definition: Features2d.h:55
cv::Ptr< ORBextractor > _orb
Definition: Features2d.h:580
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
GLM_FUNC_DECL genType e()
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
virtual ~SURF()
Definition: Features2d.cpp:844
float UTILITE_EXP uStr2Float(const std::string &str)
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
Definition: Features2d.cpp:925
uint32_t * fastCVCorners_
Definition: Features2d.h:358
bool nonmaxSuppression_
Definition: Features2d.h:346
std::map< std::string, std::string > ParametersMap
Definition: Parameters.h:43
double contrastThreshold_
Definition: Features2d.h:291
std::vector< float > _roiRatios
Definition: Features2d.h:238
int nOctaveLayers_
Definition: Features2d.h:290
Basic mathematics functions.
cv::Ptr< CV_BRISK > brisk_
Definition: Features2d.h:528
cv::Ptr< CV_ORB_GPU > _gpuOrb
Definition: Features2d.h:327
Some conversion functions.
cv::FastFeatureDetector CV_FAST
Definition: Features2d.h:52
const cv::Mat & imageRaw() const
Definition: SensorData.h:164
virtual ~Feature2D()
Definition: Features2d.cpp:439
Feature2D(const ParametersMap &parameters=ParametersMap())
Definition: Features2d.cpp:425
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
detail::uint16 uint16_t
Definition: fwd.hpp:912
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat())
Definition: Features2d.cpp:657
#define UFATAL(...)
int getMaxFeatures() const
Definition: Features2d.h:203
cv::Mat rightRaw() const
Definition: SensorData.h:190
cv::SURF CV_SURF
Definition: Features2d.h:51
SuperPointTorch(const ParametersMap &parameters=ParametersMap())
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
Definition: UStl.h:566
bool uIsFinite(const T &value)
Definition: UMath.h:55
cv::Ptr< CV_FAST_GPU > _gpuFast
Definition: Features2d.h:363
#define UASSERT(condition)
virtual void parseParameters(const ParametersMap &parameters)
Definition: Features2d.cpp:980
virtual ~ORB()
Wrappers of STL for convenient functions.
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
static void filterKeypointsByDisparity(std::vector< cv::KeyPoint > &keypoints, const cv::Mat &disparity, float minDisparity)
Definition: Features2d.cpp:200
virtual std::vector< cv::Point2f > computeCorrespondences(const cv::Mat &leftImage, const cv::Mat &rightImage, const std::vector< cv::Point2f > &leftCorners, std::vector< unsigned char > &status) const
Definition: Stereo.cpp:72
BRISK(const ParametersMap &parameters=ParametersMap())
cv::BRISK CV_BRISK
Definition: Features2d.h:56
cv::Ptr< SPDetector > superPoint_
Definition: Features2d.h:598
virtual ~FAST()
static Feature2D * create(const ParametersMap &parameters=ParametersMap())
Definition: Features2d.cpp:503
#define ULOGGER_DEBUG(...)
Definition: ULogger.h:53
virtual void parseParameters(const ParametersMap &parameters)
#define UASSERT_MSG(condition, msg_str)
Definition: ULogger.h:67
virtual ~GFTT()
virtual void parseParameters(const ParametersMap &parameters)
cv::Ptr< CV_FREAK > _freak
Definition: Features2d.h:489
SURF_FREAK(const ParametersMap &parameters=ParametersMap())
cv::Rect RTABMAP_EXP computeRoi(const cv::Mat &image, const std::string &roiRatios)
Definition: util2d.cpp:1113
FAST(const ParametersMap &parameters=ParametersMap())
virtual void parseParameters(const ParametersMap &parameters)
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual void parseParameters(const ParametersMap &parameters)
Definition: Stereo.cpp:61
virtual void parseParameters(const ParametersMap &parameters)
static void filterKeypointsByDepth(std::vector< cv::KeyPoint > &keypoints, const cv::Mat &depth, float minDepth, float maxDepth)
Definition: Features2d.cpp:81
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
virtual void parseParameters(const ParametersMap &parameters)
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
KAZE(const ParametersMap &parameters=ParametersMap())
const cv::Mat & depthOrRightRaw() const
Definition: SensorData.h:165
cv::gpu::SURF_GPU CV_SURF_GPU
Definition: Features2d.h:57
int fastThreshold_
Definition: Features2d.h:323
float patternScale_
Definition: Features2d.h:526
static cv::Rect computeRoi(const cv::Mat &image, const std::string &roiRatios)
Definition: Features2d.cpp:412
SIFT(const ParametersMap &parameters=ParametersMap())
Definition: Features2d.cpp:966
static Stereo * create(const ParametersMap &parameters=ParametersMap())
Definition: Stereo.cpp:35
double sigma_
Definition: Features2d.h:293
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
cv::Ptr< CV_BRIEF > _brief
Definition: Features2d.h:382
detail::uint32 uint32_t
Definition: fwd.hpp:916
#define false
Definition: ConvertUTF.c:56
cv::Mat descriptors_
Definition: Features2d.h:581
cv::Ptr< CV_SURF > _surf
Definition: Features2d.h:271
virtual ~KAZE()
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
const std::vector< CameraModel > & cameraModels() const
Definition: SensorData.h:215
FAST_FREAK(const ParametersMap &parameters=ParametersMap())
int nOctaveLayers_
Definition: Features2d.h:265
float gpuKeypointsRatio_
Definition: Features2d.h:268
cv::FREAK CV_FREAK
Definition: Features2d.h:53
#define UDEBUG(...)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
virtual void parseParameters(const ParametersMap &parameters)
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
ORBOctree(const ParametersMap &parameters=ParametersMap())
ORB(const ParametersMap &parameters=ParametersMap())
cv::Ptr< CV_BRIEF > _brief
Definition: Features2d.h:445
cv::Ptr< CV_SIFT > _sift
Definition: Features2d.h:296
#define UERROR(...)
virtual void parseParameters(const ParametersMap &parameters)
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual void parseParameters(const ParametersMap &parameters)
GFTT(const ParametersMap &parameters=ParametersMap())
int fastCVMaxFeatures_
Definition: Features2d.h:356
float threshold_
Definition: Features2d.h:548
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
Definition: SensorData.h:216
SURF(const ParametersMap &parameters=ParametersMap())
Definition: Features2d.cpp:832
#define UWARN(...)
bool fastCVinit_
Definition: Features2d.h:355
virtual void parseParameters(const ParametersMap &parameters)
double ticks()
Definition: UTimer.cpp:117
double _minDistance
Definition: Features2d.h:421
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
bool gpuVersion_
Definition: Features2d.h:269
GFTT_BRIEF(const ParametersMap &parameters=ParametersMap())
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
Definition: Features2d.cpp:891
int edgeThreshold_
Definition: Features2d.h:316
cv::gpu::ORB_GPU CV_ORB_GPU
Definition: Features2d.h:58
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())=0
virtual void parseParameters(const ParametersMap &parameters)
GFTT_ORB(const ParametersMap &parameters=ParametersMap())
cv::GFTTDetector CV_GFTT
Definition: Features2d.h:54
cv::gpu::FAST_GPU CV_FAST_GPU
Definition: Features2d.h:59
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
virtual std::vector< cv::KeyPoint > generateKeypointsImpl(const cv::Mat &image, const cv::Rect &roi, const cv::Mat &mask=cv::Mat())
#define ULOGGER_ERROR(...)
Definition: ULogger.h:56
bool nonmaxSuppresion_
Definition: Features2d.h:324
std::vector< cv::Point3f > RTABMAP_EXP generateKeypoints3DDepth(const std::vector< cv::KeyPoint > &keypoints, const cv::Mat &depth, const CameraModel &cameraModel, float minDepth=0, float maxDepth=0)
cv::Ptr< cv::FeatureDetector > _fast
Definition: Features2d.h:362
double hessianThreshold_
Definition: Features2d.h:263
std::string UTILITE_EXP uFormat(const char *fmt,...)
cv::Ptr< CV_GFTT > _gftt
Definition: Features2d.h:426
cv::Mat depthRaw() const
Definition: SensorData.h:189
ParametersMap parameters_
Definition: Features2d.h:234
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
Definition: UStl.h:443
virtual void parseParameters(const ParametersMap &parameters)
virtual void parseParameters(const ParametersMap &parameters)
std::vector< cv::Point3f > RTABMAP_EXP generateKeypoints3DStereo(const std::vector< cv::Point2f > &leftCorners, const std::vector< cv::Point2f > &rightCorners, const StereoCameraModel &model, const std::vector< unsigned char > &mask=std::vector< unsigned char >(), float minDepth=0, float maxDepth=0)
bool _useHarrisDetector
Definition: Features2d.h:423
cv::Ptr< CV_SURF_GPU > _gpuSurf
Definition: Features2d.h:272
#define UINFO(...)


rtabmap
Author(s): Mathieu Labbe
autogenerated on Mon Dec 14 2020 03:34:58