Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
vpKeyPoint.h
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Key point functionalities.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37  *****************************************************************************/
38 #ifndef _vpKeyPoint_h_
39 #define _vpKeyPoint_h_
40 
41 #include <algorithm> // std::transform
42 #include <float.h> // DBL_MAX
43 #include <fstream> // std::ofstream
44 #include <limits>
45 #include <map> // std::map
46 #include <numeric> // std::accumulate
47 #include <stdlib.h> // srand, rand
48 #include <time.h> // time
49 #include <vector> // std::vector
50 
51 #include <visp3/core/vpConfig.h>
52 #include <visp3/core/vpDisplay.h>
53 #include <visp3/core/vpImageConvert.h>
54 #include <visp3/core/vpPixelMeterConversion.h>
55 #include <visp3/core/vpPlane.h>
56 #include <visp3/core/vpPoint.h>
57 #include <visp3/vision/vpBasicKeyPoint.h>
58 #include <visp3/vision/vpPose.h>
59 #ifdef VISP_HAVE_MODULE_IO
60 # include <visp3/io/vpImageIo.h>
61 #endif
62 #include <visp3/core/vpConvert.h>
63 #include <visp3/core/vpCylinder.h>
64 #include <visp3/core/vpMeterPixelConversion.h>
65 #include <visp3/core/vpPolygon.h>
66 #include <visp3/vision/vpXmlConfigParserKeyPoint.h>
67 
68 // Require at least OpenCV >= 2.1.1
69 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
70 
71 # include <opencv2/calib3d/calib3d.hpp>
72 # include <opencv2/features2d/features2d.hpp>
73 # include <opencv2/imgproc/imgproc.hpp>
74 
75 # if (VISP_HAVE_OPENCV_VERSION >= 0x040000) // Require opencv >= 4.0.0
76 # include <opencv2/imgproc/imgproc_c.h>
77 # include <opencv2/imgproc.hpp>
78 # endif
79 
80 # if defined(VISP_HAVE_OPENCV_XFEATURES2D) // OpenCV >= 3.0.0
81 # include <opencv2/xfeatures2d.hpp>
82 # elif defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION >= 0x020400) && \
83  (VISP_HAVE_OPENCV_VERSION < 0x030000)
84 # include <opencv2/nonfree/nonfree.hpp>
85 # endif
86 
222 class VISP_EXPORT vpKeyPoint : public vpBasicKeyPoint
223 {
224 
225 public:
228  constantFactorDistanceThreshold,
230  stdDistanceThreshold,
232  ratioDistanceThreshold,
235  stdAndRatioDistanceThreshold,
237  noFilterMatching
238  };
239 
242  detectionThreshold,
244  detectionScore
247  };
248 
250  typedef enum {
254  pgmImageFormat
256 
259 #if (VISP_HAVE_OPENCV_VERSION >= 0x020403)
266 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) || (defined(VISP_HAVE_OPENCV_XFEATURES2D))
267  DETECTOR_STAR,
268 #endif
269 #if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
272 #endif
273 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
277 #endif
278 #if (VISP_HAVE_OPENCV_VERSION >= 0x030100) && defined(VISP_HAVE_OPENCV_XFEATURES2D)
279  DETECTOR_MSD,
280 #endif
281 #endif
282  DETECTOR_TYPE_SIZE
283  };
284 
287 #if (VISP_HAVE_OPENCV_VERSION >= 0x020403)
290 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) || (defined(VISP_HAVE_OPENCV_XFEATURES2D))
291  DESCRIPTOR_FREAK,
292  DESCRIPTOR_BRIEF,
293 #endif
294 #if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
297 #endif
298 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
301 #if defined(VISP_HAVE_OPENCV_XFEATURES2D)
302  DESCRIPTOR_DAISY,
303  DESCRIPTOR_LATCH,
304 #endif
305 #endif
306 #if (VISP_HAVE_OPENCV_VERSION >= 0x030200) && defined(VISP_HAVE_OPENCV_XFEATURES2D)
307  DESCRIPTOR_VGG,
308  DESCRIPTOR_BoostDesc,
309 #endif
310 #endif
311  DESCRIPTOR_TYPE_SIZE
312  };
313 
314  vpKeyPoint(const vpFeatureDetectorType &detectorType, const vpFeatureDescriptorType &descriptorType,
315  const std::string &matcherName, const vpFilterMatchingType &filterType = ratioDistanceThreshold);
316  vpKeyPoint(const std::string &detectorName = "ORB", const std::string &extractorName = "ORB",
317  const std::string &matcherName = "BruteForce-Hamming",
318  const vpFilterMatchingType &filterType = ratioDistanceThreshold);
319  vpKeyPoint(const std::vector<std::string> &detectorNames, const std::vector<std::string> &extractorNames,
320  const std::string &matcherName = "BruteForce",
321  const vpFilterMatchingType &filterType = ratioDistanceThreshold);
322 
323  unsigned int buildReference(const vpImage<unsigned char> &I);
324  unsigned int buildReference(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height,
325  unsigned int width);
326  unsigned int buildReference(const vpImage<unsigned char> &I, const vpRect &rectangle);
327 
328  void buildReference(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &trainKeyPoint,
329  std::vector<cv::Point3f> &points3f, bool append = false, int class_id = -1);
330  void buildReference(const vpImage<unsigned char> &I, const std::vector<cv::KeyPoint> &trainKeyPoint,
331  const cv::Mat &trainDescriptors, const std::vector<cv::Point3f> &points3f,
332  bool append = false, int class_id = -1);
333 
334  unsigned int buildReference(const vpImage<vpRGBa> &I_color);
335  unsigned int buildReference(const vpImage<vpRGBa> &I_color, const vpImagePoint &iP, unsigned int height,
336  unsigned int width);
337  unsigned int buildReference(const vpImage<vpRGBa> &I_color, const vpRect &rectangle);
338 
339  void buildReference(const vpImage<vpRGBa> &I_color, std::vector<cv::KeyPoint> &trainKeyPoint,
340  std::vector<cv::Point3f> &points3f, bool append = false, int class_id = -1);
341  void buildReference(const vpImage<vpRGBa> &I, const std::vector<cv::KeyPoint> &trainKeyPoint,
342  const cv::Mat &trainDescriptors, const std::vector<cv::Point3f> &points3f,
343  bool append = false, int class_id = -1);
344 
345  static void compute3D(const cv::KeyPoint &candidate, const std::vector<vpPoint> &roi, const vpCameraParameters &cam,
346  const vpHomogeneousMatrix &cMo, cv::Point3f &point);
347 
348  static void compute3D(const vpImagePoint &candidate, const std::vector<vpPoint> &roi, const vpCameraParameters &cam,
349  const vpHomogeneousMatrix &cMo, vpPoint &point);
350 
351  static void compute3DForPointsInPolygons(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
352  std::vector<cv::KeyPoint> &candidates,
353  const std::vector<vpPolygon> &polygons,
354  const std::vector<std::vector<vpPoint> > &roisPt,
355  std::vector<cv::Point3f> &points, cv::Mat *descriptors = NULL);
356 
357  static void compute3DForPointsInPolygons(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
358  std::vector<vpImagePoint> &candidates,
359  const std::vector<vpPolygon> &polygons,
360  const std::vector<std::vector<vpPoint> > &roisPt,
361  std::vector<vpPoint> &points, cv::Mat *descriptors = NULL);
362 
363  static void
364  compute3DForPointsOnCylinders(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
365  std::vector<cv::KeyPoint> &candidates, const std::vector<vpCylinder> &cylinders,
366  const std::vector<std::vector<std::vector<vpImagePoint> > > &vectorOfCylinderRois,
367  std::vector<cv::Point3f> &points, cv::Mat *descriptors = NULL);
368 
369  static void
370  compute3DForPointsOnCylinders(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
371  std::vector<vpImagePoint> &candidates, const std::vector<vpCylinder> &cylinders,
372  const std::vector<std::vector<std::vector<vpImagePoint> > > &vectorOfCylinderRois,
373  std::vector<vpPoint> &points, cv::Mat *descriptors = NULL);
374 
375  bool computePose(const std::vector<cv::Point2f> &imagePoints, const std::vector<cv::Point3f> &objectPoints,
376  const vpCameraParameters &cam, vpHomogeneousMatrix &cMo, std::vector<int> &inlierIndex,
377  double &elapsedTime, bool (*func)(const vpHomogeneousMatrix &) = NULL);
378 
379  bool computePose(const std::vector<vpPoint> &objectVpPoints, vpHomogeneousMatrix &cMo, std::vector<vpPoint> &inliers,
380  double &elapsedTime, bool (*func)(const vpHomogeneousMatrix &) = NULL);
381 
382  bool computePose(const std::vector<vpPoint> &objectVpPoints, vpHomogeneousMatrix &cMo, std::vector<vpPoint> &inliers,
383  std::vector<unsigned int> &inlierIndex, double &elapsedTime,
384  bool (*func)(const vpHomogeneousMatrix &) = NULL);
385 
386  void createImageMatching(vpImage<unsigned char> &IRef, vpImage<unsigned char> &ICurrent,
387  vpImage<unsigned char> &IMatching);
388  void createImageMatching(vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching);
389 
390  void createImageMatching(vpImage<unsigned char> &IRef, vpImage<vpRGBa> &ICurrent,
391  vpImage<vpRGBa> &IMatching);
392  void createImageMatching(vpImage<vpRGBa> &ICurrent, vpImage<vpRGBa> &IMatching);
393 
394  void detect(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints,
395  const vpRect &rectangle = vpRect());
396  void detect(const vpImage<vpRGBa> &I_color, std::vector<cv::KeyPoint> &keyPoints,
397  const vpRect &rectangle = vpRect());
398  void detect(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, const cv::Mat &mask = cv::Mat());
399  void detect(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, double &elapsedTime,
400  const vpRect &rectangle = vpRect());
401  void detect(const vpImage<vpRGBa> &I_color, std::vector<cv::KeyPoint> &keyPoints, double &elapsedTime,
402  const vpRect &rectangle = vpRect());
403  void detect(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, double &elapsedTime,
404  const cv::Mat &mask = cv::Mat());
405 
406  void detectExtractAffine(const vpImage<unsigned char> &I, std::vector<std::vector<cv::KeyPoint> > &listOfKeypoints,
407  std::vector<cv::Mat> &listOfDescriptors,
408  std::vector<vpImage<unsigned char> > *listOfAffineI = NULL);
409 
410  void display(const vpImage<unsigned char> &IRef, const vpImage<unsigned char> &ICurrent, unsigned int size = 3);
411  void display(const vpImage<unsigned char> &ICurrent, unsigned int size = 3, const vpColor &color = vpColor::green);
412  void display(const vpImage<vpRGBa> &IRef, const vpImage<vpRGBa> &ICurrent, unsigned int size = 3);
413  void display(const vpImage<vpRGBa> &ICurrent, unsigned int size = 3, const vpColor &color = vpColor::green);
414 
415  void displayMatching(const vpImage<unsigned char> &IRef, vpImage<unsigned char> &IMatching, unsigned int crossSize,
416  unsigned int lineThickness = 1, const vpColor &color = vpColor::green);
417  void displayMatching(const vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching,
418  const std::vector<vpImagePoint> &ransacInliers = std::vector<vpImagePoint>(),
419  unsigned int crossSize = 3, unsigned int lineThickness = 1);
420  void displayMatching(const vpImage<unsigned char> &IRef, vpImage<vpRGBa> &IMatching, unsigned int crossSize,
421  unsigned int lineThickness = 1, const vpColor &color = vpColor::green);
422  void displayMatching(const vpImage<vpRGBa> &IRef, vpImage<vpRGBa> &IMatching, unsigned int crossSize,
423  unsigned int lineThickness = 1, const vpColor &color = vpColor::green);
424  void displayMatching(const vpImage<vpRGBa> &ICurrent, vpImage<vpRGBa> &IMatching,
425  const std::vector<vpImagePoint> &ransacInliers = std::vector<vpImagePoint>(),
426  unsigned int crossSize = 3, unsigned int lineThickness = 1);
427 
428  void extract(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
429  std::vector<cv::Point3f> *trainPoints = NULL);
430  void extract(const vpImage<vpRGBa> &I_color, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
431  std::vector<cv::Point3f> *trainPoints = NULL);
432  void extract(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
433  std::vector<cv::Point3f> *trainPoints = NULL);
434  void extract(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
435  double &elapsedTime, std::vector<cv::Point3f> *trainPoints = NULL);
436  void extract(const vpImage<vpRGBa> &I_color, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
437  double &elapsedTime, std::vector<cv::Point3f> *trainPoints = NULL);
438  void extract(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors, double &elapsedTime,
439  std::vector<cv::Point3f> *trainPoints = NULL);
440 
451  {
452  if (!m_computeCovariance) {
453  std::cout << "Warning : The covariance matrix has not been computed. "
454  "See setCovarianceComputation() to do it."
455  << std::endl;
456  return vpMatrix();
457  }
458 
459  if (m_computeCovariance && !m_useRansacVVS) {
460  std::cout << "Warning : The covariance matrix can only be computed "
461  "with a Virtual Visual Servoing approach."
462  << std::endl
463  << "Use setUseRansacVVS(true) to choose to use a pose "
464  "estimation method based on a Virtual Visual Servoing "
465  "approach."
466  << std::endl;
467  return vpMatrix();
468  }
469 
470  return m_covarianceMatrix;
471  }
472 
478  inline double getDetectionTime() const { return m_detectionTime; }
479 
487  inline cv::Ptr<cv::FeatureDetector> getDetector(const vpFeatureDetectorType &type) const
488  {
489  std::map<vpFeatureDetectorType, std::string>::const_iterator it_name = m_mapOfDetectorNames.find(type);
490  if (it_name == m_mapOfDetectorNames.end()) {
491  std::cerr << "Internal problem with the feature type and the "
492  "corresponding name!"
493  << std::endl;
494  }
495 
496  std::map<std::string, cv::Ptr<cv::FeatureDetector> >::const_iterator findDetector =
497  m_detectors.find(it_name->second);
498  if (findDetector != m_detectors.end()) {
499  return findDetector->second;
500  }
501 
502  std::cerr << "Cannot find: " << it_name->second << std::endl;
503  return cv::Ptr<cv::FeatureDetector>();
504  }
505 
513  inline cv::Ptr<cv::FeatureDetector> getDetector(const std::string &name) const
514  {
515  std::map<std::string, cv::Ptr<cv::FeatureDetector> >::const_iterator findDetector = m_detectors.find(name);
516  if (findDetector != m_detectors.end()) {
517  return findDetector->second;
518  }
519 
520  std::cerr << "Cannot find: " << name << std::endl;
521  return cv::Ptr<cv::FeatureDetector>();
522  }
523 
527  inline std::map<vpFeatureDetectorType, std::string> getDetectorNames() const { return m_mapOfDetectorNames; }
528 
534  inline double getExtractionTime() const { return m_extractionTime; }
535 
543  inline cv::Ptr<cv::DescriptorExtractor> getExtractor(const vpFeatureDescriptorType &type) const
544  {
545  std::map<vpFeatureDescriptorType, std::string>::const_iterator it_name = m_mapOfDescriptorNames.find(type);
546  if (it_name == m_mapOfDescriptorNames.end()) {
547  std::cerr << "Internal problem with the feature type and the "
548  "corresponding name!"
549  << std::endl;
550  }
551 
552  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> >::const_iterator findExtractor =
553  m_extractors.find(it_name->second);
554  if (findExtractor != m_extractors.end()) {
555  return findExtractor->second;
556  }
557 
558  std::cerr << "Cannot find: " << it_name->second << std::endl;
559  return cv::Ptr<cv::DescriptorExtractor>();
560  }
561 
569  inline cv::Ptr<cv::DescriptorExtractor> getExtractor(const std::string &name) const
570  {
571  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> >::const_iterator findExtractor = m_extractors.find(name);
572  if (findExtractor != m_extractors.end()) {
573  return findExtractor->second;
574  }
575 
576  std::cerr << "Cannot find: " << name << std::endl;
577  return cv::Ptr<cv::DescriptorExtractor>();
578  }
579 
583  inline std::map<vpFeatureDescriptorType, std::string> getExtractorNames() const { return m_mapOfDescriptorNames; }
584 
590  inline vpImageFormatType getImageFormat() const { return m_imageFormat; }
591 
597  inline double getMatchingTime() const { return m_matchingTime; }
598 
604  inline cv::Ptr<cv::DescriptorMatcher> getMatcher() const { return m_matcher; }
605 
612  inline std::vector<cv::DMatch> getMatches() const { return m_filteredMatches; }
613 
621  inline std::vector<std::pair<cv::KeyPoint, cv::KeyPoint> > getMatchQueryToTrainKeyPoints() const
622  {
623  std::vector<std::pair<cv::KeyPoint, cv::KeyPoint> > matchQueryToTrainKeyPoints(m_filteredMatches.size());
624  for (size_t i = 0; i < m_filteredMatches.size(); i++) {
625  matchQueryToTrainKeyPoints.push_back(
626  std::pair<cv::KeyPoint, cv::KeyPoint>(m_queryFilteredKeyPoints[(size_t)m_filteredMatches[i].queryIdx],
627  m_trainKeyPoints[(size_t)m_filteredMatches[i].trainIdx]));
628  }
629  return matchQueryToTrainKeyPoints;
630  }
631 
637  inline unsigned int getNbImages() const {
638  return static_cast<unsigned int>(m_mapOfImages.size());
639  }
640 
641  void getObjectPoints(std::vector<cv::Point3f> &objectPoints) const;
642  void getObjectPoints(std::vector<vpPoint> &objectPoints) const;
643 
649  inline double getPoseTime() const { return m_poseTime; }
650 
657  inline cv::Mat getQueryDescriptors() const { return m_queryDescriptors; }
658 
659  void getQueryKeyPoints(std::vector<cv::KeyPoint> &keyPoints) const;
660  void getQueryKeyPoints(std::vector<vpImagePoint> &keyPoints) const;
661 
667  inline std::vector<vpImagePoint> getRansacInliers() const { return m_ransacInliers; }
668 
674  inline std::vector<vpImagePoint> getRansacOutliers() const { return m_ransacOutliers; }
675 
682  inline cv::Mat getTrainDescriptors() const { return m_trainDescriptors; }
683 
684  void getTrainKeyPoints(std::vector<cv::KeyPoint> &keyPoints) const;
685  void getTrainKeyPoints(std::vector<vpImagePoint> &keyPoints) const;
686 
687  void getTrainPoints(std::vector<cv::Point3f> &points) const;
688  void getTrainPoints(std::vector<vpPoint> &points) const;
689 
690  void initMatcher(const std::string &matcherName);
691 
692  void insertImageMatching(const vpImage<unsigned char> &IRef, const vpImage<unsigned char> &ICurrent,
693  vpImage<unsigned char> &IMatching);
694  void insertImageMatching(const vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching);
695 
696  void insertImageMatching(const vpImage<vpRGBa> &IRef, const vpImage<vpRGBa> &ICurrent,
697  vpImage<vpRGBa> &IMatching);
698  void insertImageMatching(const vpImage<vpRGBa> &ICurrent, vpImage<vpRGBa> &IMatching);
699 
700 #ifdef VISP_HAVE_PUGIXML
701  void loadConfigFile(const std::string &configFile);
702 #endif
703 
704  void loadLearningData(const std::string &filename, bool binaryMode = false, bool append = false);
705 
706  void match(const cv::Mat &trainDescriptors, const cv::Mat &queryDescriptors, std::vector<cv::DMatch> &matches,
707  double &elapsedTime);
708 
709  unsigned int matchPoint(const vpImage<unsigned char> &I);
710  unsigned int matchPoint(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height,
711  unsigned int width);
712  unsigned int matchPoint(const vpImage<unsigned char> &I, const vpRect &rectangle);
713 
715  bool (*func)(const vpHomogeneousMatrix &) = NULL, const vpRect &rectangle = vpRect());
717  double &error, double &elapsedTime, bool (*func)(const vpHomogeneousMatrix &) = NULL,
718  const vpRect &rectangle = vpRect());
719 
720  bool matchPointAndDetect(const vpImage<unsigned char> &I, vpRect &boundingBox, vpImagePoint &centerOfGravity,
721  const bool isPlanarObject = true, std::vector<vpImagePoint> *imPts1 = NULL,
722  std::vector<vpImagePoint> *imPts2 = NULL, double *meanDescriptorDistance = NULL,
723  double *detectionScore = NULL, const vpRect &rectangle = vpRect());
724 
725  bool matchPointAndDetect(const vpImage<unsigned char> &I, const vpCameraParameters &cam, vpHomogeneousMatrix &cMo,
726  double &error, double &elapsedTime, vpRect &boundingBox, vpImagePoint &centerOfGravity,
727  bool (*func)(const vpHomogeneousMatrix &) = NULL, const vpRect &rectangle = vpRect());
728 
729  unsigned int matchPoint(const vpImage<vpRGBa> &I_color);
730  unsigned int matchPoint(const vpImage<vpRGBa> &I_color, const vpImagePoint &iP, unsigned int height,
731  unsigned int width);
732  unsigned int matchPoint(const vpImage<vpRGBa> &I_color, const vpRect &rectangle);
733 
734  bool matchPoint(const vpImage<vpRGBa> &I_color, const vpCameraParameters &cam, vpHomogeneousMatrix &cMo,
735  bool (*func)(const vpHomogeneousMatrix &) = NULL, const vpRect &rectangle = vpRect());
736  bool matchPoint(const vpImage<vpRGBa> &I_color, const vpCameraParameters &cam, vpHomogeneousMatrix &cMo,
737  double &error, double &elapsedTime, bool (*func)(const vpHomogeneousMatrix &) = NULL,
738  const vpRect &rectangle = vpRect());
739 
740  void reset();
741 
742  void saveLearningData(const std::string &filename, bool binaryMode = false,
743  bool saveTrainingImages = true);
744 
751  inline void setCovarianceComputation(const bool &flag)
752  {
753  m_computeCovariance = flag;
754  if (!m_useRansacVVS) {
755  std::cout << "Warning : The covariance matrix can only be computed "
756  "with a Virtual Visual Servoing approach."
757  << std::endl
758  << "Use setUseRansacVVS(true) to choose to use a pose "
759  "estimation method based on a Virtual "
760  "Visual Servoing approach."
761  << std::endl;
762  }
763  }
764 
770  inline void setDetectionMethod(const vpDetectionMethodType &method) { m_detectionMethod = method; }
771 
777  inline void setDetector(const vpFeatureDetectorType &detectorType)
778  {
779  m_detectorNames.clear();
780  m_detectorNames.push_back(m_mapOfDetectorNames[detectorType]);
781  m_detectors.clear();
782  initDetector(m_mapOfDetectorNames[detectorType]);
783  }
784 
790  inline void setDetector(const std::string &detectorName)
791  {
792  m_detectorNames.clear();
793  m_detectorNames.push_back(detectorName);
794  m_detectors.clear();
795  initDetector(detectorName);
796  }
797 
798 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
799 
807  template <typename T1, typename T2, typename T3>
808  inline void setDetectorParameter(const T1 detectorName, const T2 parameterName, const T3 value)
809  {
810  if (m_detectors.find(detectorName) != m_detectors.end()) {
811  m_detectors[detectorName]->set(parameterName, value);
812  }
813  }
814 #endif
815 
822  inline void setDetectors(const std::vector<std::string> &detectorNames)
823  {
824  m_detectorNames.clear();
825  m_detectors.clear();
826  m_detectorNames = detectorNames;
827  initDetectors(m_detectorNames);
828  }
829 
835  inline void setExtractor(const vpFeatureDescriptorType &extractorType)
836  {
837  m_extractorNames.clear();
838  m_extractorNames.push_back(m_mapOfDescriptorNames[extractorType]);
839  m_extractors.clear();
840  initExtractor(m_mapOfDescriptorNames[extractorType]);
841  }
842 
849  inline void setExtractor(const std::string &extractorName)
850  {
851  m_extractorNames.clear();
852  m_extractorNames.push_back(extractorName);
853  m_extractors.clear();
854  initExtractor(extractorName);
855  }
856 
857 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
858 
866  template <typename T1, typename T2, typename T3>
867  inline void setExtractorParameter(const T1 extractorName, const T2 parameterName, const T3 value)
868  {
869  if (m_extractors.find(extractorName) != m_extractors.end()) {
870  m_extractors[extractorName]->set(parameterName, value);
871  }
872  }
873 #endif
874 
881  inline void setExtractors(const std::vector<std::string> &extractorNames)
882  {
883  m_extractorNames.clear();
884  m_extractorNames = extractorNames;
885  m_extractors.clear();
886  initExtractors(m_extractorNames);
887  }
888 
894  inline void setImageFormat(const vpImageFormatType &imageFormat) { m_imageFormat = imageFormat; }
895 
911  inline void setMatcher(const std::string &matcherName)
912  {
913  m_matcherName = matcherName;
914  initMatcher(m_matcherName);
915  }
916 
932  inline void setFilterMatchingType(const vpFilterMatchingType &filterType)
933  {
934  m_filterType = filterType;
935 
936  // Use k-nearest neighbors (knn) to retrieve the two best matches for a
937  // keypoint So this is useful only for ratioDistanceThreshold method
938  if (filterType == ratioDistanceThreshold || filterType == stdAndRatioDistanceThreshold) {
939  m_useKnn = true;
940 
941 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
942  if (m_matcher != NULL && m_matcherName == "BruteForce") {
943  // if a matcher is already initialized, disable the crossCheck
944  // because it will not work with knnMatch
945  m_matcher->set("crossCheck", false);
946  }
947 #endif
948  } else {
949  m_useKnn = false;
950 
951 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
952  if (m_matcher != NULL && m_matcherName == "BruteForce") {
953  // if a matcher is already initialized, set the crossCheck mode if
954  // necessary
955  m_matcher->set("crossCheck", m_useBruteForceCrossCheck);
956  }
957 #endif
958  }
959  }
960 
967  inline void setMatchingFactorThreshold(const double factor)
968  {
969  if (factor > 0.0) {
970  m_matchingFactorThreshold = factor;
971  } else {
972  throw vpException(vpException::badValue, "The factor must be positive.");
973  }
974  }
975 
981  inline void setMatchingRatioThreshold(double ratio)
982  {
983  if (ratio > 0.0 && (ratio < 1.0 || std::fabs(ratio - 1.0) < std::numeric_limits<double>::epsilon())) {
984  m_matchingRatioThreshold = ratio;
985  } else {
986  throw vpException(vpException::badValue, "The ratio must be in the interval ]0 ; 1].");
987  }
988  }
989 
996  inline void setRansacConsensusPercentage(double percentage)
997  {
998  if (percentage > 0.0 &&
999  (percentage < 100.0 || std::fabs(percentage - 100.0) < std::numeric_limits<double>::epsilon())) {
1000  m_ransacConsensusPercentage = percentage;
1001  } else {
1002  throw vpException(vpException::badValue, "The percentage must be in the interval ]0 ; 100].");
1003  }
1004  }
1005 
1010  {
1011  m_ransacFilterFlag = flag;
1012  }
1013 
1020  inline void setRansacIteration(int nbIter)
1021  {
1022  if (nbIter > 0) {
1023  m_nbRansacIterations = nbIter;
1024  } else {
1025  throw vpException(vpException::badValue, "The number of iterations must be greater than zero.");
1026  }
1027  }
1028 
1034  inline void setRansacParallel(bool parallel)
1035  {
1036  m_ransacParallel = parallel;
1037  }
1038 
1045  inline void setRansacParallelNbThreads(unsigned int nthreads)
1046  {
1047  m_ransacParallelNbThreads = nthreads;
1048  }
1049 
1057  inline void setRansacReprojectionError(double reprojectionError)
1058  {
1059  if (reprojectionError > 0.0) {
1060  m_ransacReprojectionError = reprojectionError;
1061  } else {
1062  throw vpException(vpException::badValue, "The Ransac reprojection "
1063  "threshold must be positive "
1064  "as we deal with distance.");
1065  }
1066  }
1067 
1073  inline void setRansacMinInlierCount(int minCount)
1074  {
1075  if (minCount > 0) {
1076  m_nbRansacMinInlierCount = minCount;
1077  } else {
1078  throw vpException(vpException::badValue, "The minimum number of inliers must be greater than zero.");
1079  }
1080  }
1081 
1088  inline void setRansacThreshold(double threshold)
1089  {
1090  if (threshold > 0.0) {
1091  m_ransacThreshold = threshold;
1092  } else {
1093  throw vpException(vpException::badValue, "The Ransac threshold must be positive as we deal with distance.");
1094  }
1095  }
1096 
1104  inline void setUseAffineDetection(bool useAffine) { m_useAffineDetection = useAffine; }
1105 
1106 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
1107 
1113  inline void setUseBruteForceCrossCheck(bool useCrossCheck)
1114  {
1115  // Only available with BruteForce and with k=1 (i.e not used with a
1116  // ratioDistanceThreshold method)
1117  if (m_matcher != NULL && !m_useKnn && m_matcherName == "BruteForce") {
1118  m_matcher->set("crossCheck", useCrossCheck);
1119  } else if (m_matcher != NULL && m_useKnn && m_matcherName == "BruteForce") {
1120  std::cout << "Warning, you try to set the crossCheck parameter with a "
1121  "BruteForce matcher but knn is enabled";
1122  std::cout << " (the filtering method uses a ratio constraint)" << std::endl;
1123  }
1124  }
1125 #endif
1126 
1133  inline void setUseMatchTrainToQuery(bool useMatchTrainToQuery)
1134  {
1135  m_useMatchTrainToQuery = useMatchTrainToQuery;
1136  }
1137 
1145  inline void setUseRansacConsensusPercentage(bool usePercentage) { m_useConsensusPercentage = usePercentage; }
1146 
1154  inline void setUseRansacVVS(bool ransacVVS) { m_useRansacVVS = ransacVVS; }
1155 
1162  inline void setUseSingleMatchFilter(bool singleMatchFilter) { m_useSingleMatchFilter = singleMatchFilter; }
1163 
1164 private:
1167  bool m_computeCovariance;
1169  vpMatrix m_covarianceMatrix;
1171  int m_currentImageId;
1174  vpDetectionMethodType m_detectionMethod;
1176  double m_detectionScore;
1179  double m_detectionThreshold;
1181  double m_detectionTime;
1183  std::vector<std::string> m_detectorNames;
1186  // with a key based upon the detector name.
1187  std::map<std::string, cv::Ptr<cv::FeatureDetector> > m_detectors;
1189  double m_extractionTime;
1191  std::vector<std::string> m_extractorNames;
1194  // with a key based upon the extractor name.
1195  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> > m_extractors;
1197  std::vector<cv::DMatch> m_filteredMatches;
1199  vpFilterMatchingType m_filterType;
1201  vpImageFormatType m_imageFormat;
1204  std::vector<std::vector<cv::DMatch> > m_knnMatches;
1206  std::map<vpFeatureDescriptorType, std::string> m_mapOfDescriptorNames;
1208  std::map<vpFeatureDetectorType, std::string> m_mapOfDetectorNames;
1211  std::map<int, int> m_mapOfImageId;
1214  std::map<int, vpImage<unsigned char> > m_mapOfImages;
1217  cv::Ptr<cv::DescriptorMatcher> m_matcher;
1219  std::string m_matcherName;
1221  std::vector<cv::DMatch> m_matches;
1223  double m_matchingFactorThreshold;
1225  double m_matchingRatioThreshold;
1227  double m_matchingTime;
1229  std::vector<std::pair<cv::KeyPoint, cv::Point3f> > m_matchRansacKeyPointsToPoints;
1231  int m_nbRansacIterations;
1233  int m_nbRansacMinInlierCount;
1236  std::vector<cv::Point3f> m_objectFilteredPoints;
1238  double m_poseTime;
1241  cv::Mat m_queryDescriptors;
1243  std::vector<cv::KeyPoint> m_queryFilteredKeyPoints;
1245  std::vector<cv::KeyPoint> m_queryKeyPoints;
1248  double m_ransacConsensusPercentage;
1250  vpPose::RANSAC_FILTER_FLAGS m_ransacFilterFlag;
1252  std::vector<vpImagePoint> m_ransacInliers;
1254  std::vector<vpImagePoint> m_ransacOutliers;
1256  bool m_ransacParallel;
1258  unsigned int m_ransacParallelNbThreads;
1261  double m_ransacReprojectionError;
1264  double m_ransacThreshold;
1267  // detected in the train images).
1268  cv::Mat m_trainDescriptors;
1270  std::vector<cv::KeyPoint> m_trainKeyPoints;
1273  std::vector<cv::Point3f> m_trainPoints;
1276  std::vector<vpPoint> m_trainVpPoints;
1279  bool m_useAffineDetection;
1280 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
1281  bool m_useBruteForceCrossCheck;
1285 #endif
1286  bool m_useConsensusPercentage;
1290  bool m_useKnn;
1295  bool m_useMatchTrainToQuery;
1297  bool m_useRansacVVS;
1300  bool m_useSingleMatchFilter;
1303 
1304  void affineSkew(double tilt, double phi, cv::Mat &img, cv::Mat &mask, cv::Mat &Ai);
1305 
1306  double computePoseEstimationError(const std::vector<std::pair<cv::KeyPoint, cv::Point3f> > &matchKeyPoints,
1307  const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo_est);
1308 
1309  void filterMatches();
1310 
1311  void init();
1312  void initDetector(const std::string &detectorNames);
1313  void initDetectors(const std::vector<std::string> &detectorNames);
1314 
1315  void initExtractor(const std::string &extractorName);
1316  void initExtractors(const std::vector<std::string> &extractorNames);
1317 
1318  void initFeatureNames();
1319 
1320  inline size_t myKeypointHash(const cv::KeyPoint &kp)
1321  {
1322  size_t _Val = 2166136261U, scale = 16777619U;
1323  Cv32suf u;
1324  u.f = kp.pt.x;
1325  _Val = (scale * _Val) ^ u.u;
1326  u.f = kp.pt.y;
1327  _Val = (scale * _Val) ^ u.u;
1328  u.f = kp.size;
1329  _Val = (scale * _Val) ^ u.u;
1330  // As the keypoint angle can be computed for certain type of keypoint only
1331  // when extracting the corresponding descriptor, the angle field is not
1332  // taking into account for the hash
1333  // u.f = kp.angle; _Val = (scale * _Val) ^ u.u;
1334  u.f = kp.response;
1335  _Val = (scale * _Val) ^ u.u;
1336  _Val = (scale * _Val) ^ ((size_t)kp.octave);
1337  _Val = (scale * _Val) ^ ((size_t)kp.class_id);
1338  return _Val;
1339  }
1340 
1341 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
1342  /*
1343  * Adapts a detector to detect points over multiple levels of a Gaussian
1344  * pyramid. Useful for detectors that are not inherently scaled.
1345  * From OpenCV 2.4.11 source code.
1346  */
1347  class PyramidAdaptedFeatureDetector : public cv::FeatureDetector
1348  {
1349  public:
1350  // maxLevel - The 0-based index of the last pyramid layer
1351  PyramidAdaptedFeatureDetector(const cv::Ptr<cv::FeatureDetector> &detector, int maxLevel = 2);
1352 
1353  // TODO implement read/write
1354  virtual bool empty() const;
1355 
1356  protected:
1357  virtual void detect(cv::InputArray image, CV_OUT std::vector<cv::KeyPoint> &keypoints,
1358  cv::InputArray mask = cv::noArray());
1359  virtual void detectImpl(const cv::Mat &image, std::vector<cv::KeyPoint> &keypoints,
1360  const cv::Mat &mask = cv::Mat()) const;
1361 
1362  cv::Ptr<cv::FeatureDetector> detector;
1363  int maxLevel;
1364  };
1365 
1366  /*
1367  * A class filters a vector of keypoints.
1368  * Because now it is difficult to provide a convenient interface for all
1369  * usage scenarios of the keypoints filter class, it has only several needed
1370  * by now static methods.
1371  */
1372  class KeyPointsFilter
1373  {
1374  public:
1375  KeyPointsFilter() {}
1376 
1377  /*
1378  * Remove keypoints within borderPixels of an image edge.
1379  */
1380  static void runByImageBorder(std::vector<cv::KeyPoint> &keypoints, cv::Size imageSize, int borderSize);
1381  /*
1382  * Remove keypoints of sizes out of range.
1383  */
1384  static void runByKeypointSize(std::vector<cv::KeyPoint> &keypoints, float minSize, float maxSize = FLT_MAX);
1385  /*
1386  * Remove keypoints from some image by mask for pixels of this image.
1387  */
1388  static void runByPixelsMask(std::vector<cv::KeyPoint> &keypoints, const cv::Mat &mask);
1389  /*
1390  * Remove duplicated keypoints.
1391  */
1392  static void removeDuplicated(std::vector<cv::KeyPoint> &keypoints);
1393 
1394  /*
1395  * Retain the specified number of the best keypoints (according to the
1396  * response)
1397  */
1398  static void retainBest(std::vector<cv::KeyPoint> &keypoints, int npoints);
1399  };
1400 
1401 #endif
1402 };
1403 
1404 #endif
1405 #endif
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:97
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:164
cv::Ptr< cv::FeatureDetector > getDetector(const vpFeatureDetectorType &type) const
Definition: vpKeyPoint.h:487
class that defines what is a Keypoint. This class provides all the basic elements to implement classe...
void setUseMatchTrainToQuery(bool useMatchTrainToQuery)
Definition: vpKeyPoint.h:1133
void setUseRansacConsensusPercentage(bool usePercentage)
Definition: vpKeyPoint.h:1145
std::vector< std::pair< cv::KeyPoint, cv::KeyPoint > > getMatchQueryToTrainKeyPoints() const
Definition: vpKeyPoint.h:621
void setRansacIteration(int nbIter)
Definition: vpKeyPoint.h:1020
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setRansacMinInlierCount(int minCount)
Definition: vpKeyPoint.h:1073
cv::Ptr< cv::DescriptorMatcher > getMatcher() const
Definition: vpKeyPoint.h:604
void setExtractor(const std::string &extractorName)
Definition: vpKeyPoint.h:849
Class to define colors available for display functionnalities.
Definition: vpColor.h:119
std::map< vpFeatureDetectorType, std::string > getDetectorNames() const
Definition: vpKeyPoint.h:527
double getDetectionTime() const
Definition: vpKeyPoint.h:478
error that can be emited by ViSP classes.
Definition: vpException.h:71
void setDetectors(const std::vector< std::string > &detectorNames)
Definition: vpKeyPoint.h:822
cv::Mat getTrainDescriptors() const
Definition: vpKeyPoint.h:682
vpMatrix getCovarianceMatrix() const
Definition: vpKeyPoint.h:450
void setRansacParallel(bool parallel)
Definition: vpKeyPoint.h:1034
static const vpColor green
Definition: vpColor.h:182
Class that defines what is a point.
Definition: vpPoint.h:58
std::vector< vpImagePoint > getRansacOutliers() const
Definition: vpKeyPoint.h:674
void setExtractors(const std::vector< std::string > &extractorNames)
Definition: vpKeyPoint.h:881
void setMatcher(const std::string &matcherName)
Definition: vpKeyPoint.h:911
void setRansacFilterFlag(const vpPose::RANSAC_FILTER_FLAGS &flag)
Definition: vpKeyPoint.h:1009
cv::Mat getQueryDescriptors() const
Definition: vpKeyPoint.h:657
std::map< vpFeatureDescriptorType, std::string > getExtractorNames() const
Definition: vpKeyPoint.h:583
std::vector< vpImagePoint > getRansacInliers() const
Definition: vpKeyPoint.h:667
vpFeatureDetectorType
Definition: vpKeyPoint.h:258
virtual unsigned int buildReference(const vpImage< unsigned char > &I)=0
Generic class defining intrinsic camera parameters.
vpFeatureDescriptorType
Definition: vpKeyPoint.h:286
void setDetector(const vpFeatureDetectorType &detectorType)
Definition: vpKeyPoint.h:777
void setUseAffineDetection(bool useAffine)
Definition: vpKeyPoint.h:1104
double getPoseTime() const
Definition: vpKeyPoint.h:649
void setRansacConsensusPercentage(double percentage)
Definition: vpKeyPoint.h:996
unsigned int getNbImages() const
Definition: vpKeyPoint.h:637
void setDetectionMethod(const vpDetectionMethodType &method)
Definition: vpKeyPoint.h:770
void setMatchingRatioThreshold(double ratio)
Definition: vpKeyPoint.h:981
void setUseSingleMatchFilter(bool singleMatchFilter)
Definition: vpKeyPoint.h:1162
void setImageFormat(const vpImageFormatType &imageFormat)
Definition: vpKeyPoint.h:894
virtual void display(const vpImage< unsigned char > &Iref, const vpImage< unsigned char > &Icurrent, unsigned int size=3)=0
void setRansacParallelNbThreads(unsigned int nthreads)
Definition: vpKeyPoint.h:1045
void setUseRansacVVS(bool ransacVVS)
Definition: vpKeyPoint.h:1154
virtual unsigned int matchPoint(const vpImage< unsigned char > &I)=0
cv::Ptr< cv::DescriptorExtractor > getExtractor(const std::string &name) const
Definition: vpKeyPoint.h:569
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
Definition: vpKeyPoint.h:222
cv::Ptr< cv::FeatureDetector > getDetector(const std::string &name) const
Definition: vpKeyPoint.h:513
vpDetectionMethodType
Definition: vpKeyPoint.h:241
double getExtractionTime() const
Definition: vpKeyPoint.h:534
vpFilterMatchingType
Definition: vpKeyPoint.h:227
std::vector< cv::DMatch > getMatches() const
Definition: vpKeyPoint.h:612
double getMatchingTime() const
Definition: vpKeyPoint.h:597
cv::Ptr< cv::DescriptorExtractor > getExtractor(const vpFeatureDescriptorType &type) const
Definition: vpKeyPoint.h:543
void setDetector(const std::string &detectorName)
Definition: vpKeyPoint.h:790
Defines a rectangle in the plane.
Definition: vpRect.h:78
vpImageFormatType getImageFormat() const
Definition: vpKeyPoint.h:590
void setRansacThreshold(double threshold)
Definition: vpKeyPoint.h:1088
void setRansacReprojectionError(double reprojectionError)
Definition: vpKeyPoint.h:1057
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void setFilterMatchingType(const vpFilterMatchingType &filterType)
Definition: vpKeyPoint.h:932
void setMatchingFactorThreshold(const double factor)
Definition: vpKeyPoint.h:967
void setExtractor(const vpFeatureDescriptorType &extractorType)
Definition: vpKeyPoint.h:835
void setCovarianceComputation(const bool &flag)
Definition: vpKeyPoint.h:751
RANSAC_FILTER_FLAGS
Definition: vpPose.h:103