Visual Servoing Platform  version 3.1.0
vpKeyPoint.h
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 defined(VISP_HAVE_OPENCV_XFEATURES2D) // OpenCV >= 3.0.0
76 #include <opencv2/xfeatures2d.hpp>
77 #elif defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION >= 0x020400) && \
78  (VISP_HAVE_OPENCV_VERSION < 0x030000)
79 #include <opencv2/nonfree/nonfree.hpp>
80 #endif
81 
82 #ifdef VISP_HAVE_XML2
83 #include <libxml/xmlwriter.h>
84 #endif
85 
223 class VISP_EXPORT vpKeyPoint : public vpBasicKeyPoint
224 {
225 
226 public:
229  constantFactorDistanceThreshold,
231  stdDistanceThreshold,
233  ratioDistanceThreshold,
236  stdAndRatioDistanceThreshold,
238  noFilterMatching
239  };
240 
243  detectionThreshold,
245  detectionScore
248  };
249 
251  typedef enum {
255  pgmImageFormat
257 
260 #if (VISP_HAVE_OPENCV_VERSION >= 0x020403)
267 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) || (defined(VISP_HAVE_OPENCV_XFEATURES2D))
269 #endif
270 #if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
273 #endif
274 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
275  DETECTOR_KAZE,
276  DETECTOR_AKAZE,
277  DETECTOR_AGAST,
278 #endif
279 #if (VISP_HAVE_OPENCV_VERSION >= 0x030100) && defined(VISP_HAVE_OPENCV_XFEATURES2D)
280  DETECTOR_MSD,
281 #endif
282 #endif
283  DETECTOR_TYPE_SIZE
284  };
285 
288 #if (VISP_HAVE_OPENCV_VERSION >= 0x020403)
291 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) || (defined(VISP_HAVE_OPENCV_XFEATURES2D))
294 #endif
295 #if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
298 #endif
299 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
300  DESCRIPTOR_KAZE,
301  DESCRIPTOR_AKAZE,
302 #if defined(VISP_HAVE_OPENCV_XFEATURES2D)
303  DESCRIPTOR_DAISY,
304  DESCRIPTOR_LATCH,
305 #endif
306 #endif
307 #if (VISP_HAVE_OPENCV_VERSION >= 0x030200) && defined(VISP_HAVE_OPENCV_XFEATURES2D)
308  DESCRIPTOR_VGG,
309  DESCRIPTOR_BoostDesc,
310 #endif
311 #endif
312  DESCRIPTOR_TYPE_SIZE
313  };
314 
315  vpKeyPoint(const vpFeatureDetectorType &detectorType, const vpFeatureDescriptorType &descriptorType,
316  const std::string &matcherName, const vpFilterMatchingType &filterType = ratioDistanceThreshold);
317  vpKeyPoint(const std::string &detectorName = "ORB", const std::string &extractorName = "ORB",
318  const std::string &matcherName = "BruteForce-Hamming",
319  const vpFilterMatchingType &filterType = ratioDistanceThreshold);
320  vpKeyPoint(const std::vector<std::string> &detectorNames, const std::vector<std::string> &extractorNames,
321  const std::string &matcherName = "BruteForce",
322  const vpFilterMatchingType &filterType = ratioDistanceThreshold);
323 
324  unsigned int buildReference(const vpImage<unsigned char> &I);
325  unsigned int buildReference(const vpImage<unsigned char> &I, const vpImagePoint &iP, const unsigned int height,
326  const unsigned int width);
327  unsigned int buildReference(const vpImage<unsigned char> &I, const vpRect &rectangle);
328 
329  void buildReference(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &trainKeyPoint,
330  std::vector<cv::Point3f> &points3f, const bool append = false, const int class_id = -1);
331  void buildReference(const vpImage<unsigned char> &I, const std::vector<cv::KeyPoint> &trainKeyPoint,
332  const cv::Mat &trainDescriptors, const std::vector<cv::Point3f> &points3f,
333  const bool append = false, const int class_id = -1);
334 
335  static void compute3D(const cv::KeyPoint &candidate, const std::vector<vpPoint> &roi, const vpCameraParameters &cam,
336  const vpHomogeneousMatrix &cMo, cv::Point3f &point);
337 
338  static void compute3D(const vpImagePoint &candidate, const std::vector<vpPoint> &roi, const vpCameraParameters &cam,
339  const vpHomogeneousMatrix &cMo, vpPoint &point);
340 
341  static void compute3DForPointsInPolygons(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
342  std::vector<cv::KeyPoint> &candidates,
343  const std::vector<vpPolygon> &polygons,
344  const std::vector<std::vector<vpPoint> > &roisPt,
345  std::vector<cv::Point3f> &points, cv::Mat *descriptors = NULL);
346 
347  static void compute3DForPointsInPolygons(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
348  std::vector<vpImagePoint> &candidates,
349  const std::vector<vpPolygon> &polygons,
350  const std::vector<std::vector<vpPoint> > &roisPt,
351  std::vector<vpPoint> &points, cv::Mat *descriptors = NULL);
352 
353  static void
354  compute3DForPointsOnCylinders(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
355  std::vector<cv::KeyPoint> &candidates, const std::vector<vpCylinder> &cylinders,
356  const std::vector<std::vector<std::vector<vpImagePoint> > > &vectorOfCylinderRois,
357  std::vector<cv::Point3f> &points, cv::Mat *descriptors = NULL);
358 
359  static void
360  compute3DForPointsOnCylinders(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam,
361  std::vector<vpImagePoint> &candidates, const std::vector<vpCylinder> &cylinders,
362  const std::vector<std::vector<std::vector<vpImagePoint> > > &vectorOfCylinderRois,
363  std::vector<vpPoint> &points, cv::Mat *descriptors = NULL);
364 
365  bool computePose(const std::vector<cv::Point2f> &imagePoints, const std::vector<cv::Point3f> &objectPoints,
366  const vpCameraParameters &cam, vpHomogeneousMatrix &cMo, std::vector<int> &inlierIndex,
367  double &elapsedTime, bool (*func)(vpHomogeneousMatrix *) = NULL);
368 
369  bool computePose(const std::vector<vpPoint> &objectVpPoints, vpHomogeneousMatrix &cMo, std::vector<vpPoint> &inliers,
370  double &elapsedTime, bool (*func)(vpHomogeneousMatrix *) = NULL);
371 
372  bool computePose(const std::vector<vpPoint> &objectVpPoints, vpHomogeneousMatrix &cMo, std::vector<vpPoint> &inliers,
373  std::vector<unsigned int> &inlierIndex, double &elapsedTime,
374  bool (*func)(vpHomogeneousMatrix *) = NULL);
375 
376  void createImageMatching(vpImage<unsigned char> &IRef, vpImage<unsigned char> &ICurrent,
377  vpImage<unsigned char> &IMatching);
378  void createImageMatching(vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching);
379 
380  void detect(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints,
381  const vpRect &rectangle = vpRect());
382  void detect(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, const cv::Mat &mask = cv::Mat());
383  void detect(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, double &elapsedTime,
384  const vpRect &rectangle = vpRect());
385  void detect(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, double &elapsedTime,
386  const cv::Mat &mask = cv::Mat());
387 
388  void detectExtractAffine(const vpImage<unsigned char> &I, std::vector<std::vector<cv::KeyPoint> > &listOfKeypoints,
389  std::vector<cv::Mat> &listOfDescriptors,
390  std::vector<vpImage<unsigned char> > *listOfAffineI = NULL);
391 
392  void display(const vpImage<unsigned char> &IRef, const vpImage<unsigned char> &ICurrent, unsigned int size = 3);
393  void display(const vpImage<unsigned char> &ICurrent, unsigned int size = 3, const vpColor &color = vpColor::green);
394 
395  void displayMatching(const vpImage<unsigned char> &IRef, vpImage<unsigned char> &IMatching, unsigned int crossSize,
396  unsigned int lineThickness = 1, const vpColor &color = vpColor::green);
397  void displayMatching(const vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching,
398  const std::vector<vpImagePoint> &ransacInliers = std::vector<vpImagePoint>(),
399  unsigned int crossSize = 3, unsigned int lineThickness = 1);
400 
401  void extract(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
402  std::vector<cv::Point3f> *trainPoints = NULL);
403  void extract(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
404  std::vector<cv::Point3f> *trainPoints = NULL);
405  void extract(const vpImage<unsigned char> &I, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors,
406  double &elapsedTime, std::vector<cv::Point3f> *trainPoints = NULL);
407  void extract(const cv::Mat &matImg, std::vector<cv::KeyPoint> &keyPoints, cv::Mat &descriptors, double &elapsedTime,
408  std::vector<cv::Point3f> *trainPoints = NULL);
409 
420  {
421  if (!m_computeCovariance) {
422  std::cout << "Warning : The covariance matrix has not been computed. "
423  "See setCovarianceComputation() to do it."
424  << std::endl;
425  return vpMatrix();
426  }
427 
428  if (m_computeCovariance && !m_useRansacVVS) {
429  std::cout << "Warning : The covariance matrix can only be computed "
430  "with a Virtual Visual Servoing approach."
431  << std::endl
432  << "Use setUseRansacVVS(true) to choose to use a pose "
433  "estimation method based on a Virtual Visual Servoing "
434  "approach."
435  << std::endl;
436  return vpMatrix();
437  }
438 
439  return m_covarianceMatrix;
440  }
441 
447  inline double getDetectionTime() const { return m_detectionTime; }
448 
456  inline cv::Ptr<cv::FeatureDetector> getDetector(const vpFeatureDetectorType &type) const
457  {
458  std::map<vpFeatureDetectorType, std::string>::const_iterator it_name = m_mapOfDetectorNames.find(type);
459  if (it_name == m_mapOfDetectorNames.end()) {
460  std::cerr << "Internal problem with the feature type and the "
461  "corresponding name!"
462  << std::endl;
463  }
464 
465  std::map<std::string, cv::Ptr<cv::FeatureDetector> >::const_iterator findDetector =
466  m_detectors.find(it_name->second);
467  if (findDetector != m_detectors.end()) {
468  return findDetector->second;
469  }
470 
471  std::cerr << "Cannot find: " << it_name->second << std::endl;
472  return cv::Ptr<cv::FeatureDetector>();
473  }
474 
482  inline cv::Ptr<cv::FeatureDetector> getDetector(const std::string &name) const
483  {
484  std::map<std::string, cv::Ptr<cv::FeatureDetector> >::const_iterator findDetector = m_detectors.find(name);
485  if (findDetector != m_detectors.end()) {
486  return findDetector->second;
487  }
488 
489  std::cerr << "Cannot find: " << name << std::endl;
490  return cv::Ptr<cv::FeatureDetector>();
491  }
492 
496  inline std::map<vpFeatureDetectorType, std::string> getDetectorNames() const { return m_mapOfDetectorNames; }
497 
503  inline double getExtractionTime() const { return m_extractionTime; }
504 
512  inline cv::Ptr<cv::DescriptorExtractor> getExtractor(const vpFeatureDescriptorType &type) const
513  {
514  std::map<vpFeatureDescriptorType, std::string>::const_iterator it_name = m_mapOfDescriptorNames.find(type);
515  if (it_name == m_mapOfDescriptorNames.end()) {
516  std::cerr << "Internal problem with the feature type and the "
517  "corresponding name!"
518  << std::endl;
519  }
520 
521  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> >::const_iterator findExtractor =
522  m_extractors.find(it_name->second);
523  if (findExtractor != m_extractors.end()) {
524  return findExtractor->second;
525  }
526 
527  std::cerr << "Cannot find: " << it_name->second << std::endl;
528  return cv::Ptr<cv::DescriptorExtractor>();
529  }
530 
538  inline cv::Ptr<cv::DescriptorExtractor> getExtractor(const std::string &name) const
539  {
540  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> >::const_iterator findExtractor = m_extractors.find(name);
541  if (findExtractor != m_extractors.end()) {
542  return findExtractor->second;
543  }
544 
545  std::cerr << "Cannot find: " << name << std::endl;
546  return cv::Ptr<cv::DescriptorExtractor>();
547  }
548 
552  inline std::map<vpFeatureDescriptorType, std::string> getExtractorNames() const { return m_mapOfDescriptorNames; }
553 
559  inline vpImageFormatType getImageFormat() const { return m_imageFormat; }
560 
566  inline double getMatchingTime() const { return m_matchingTime; }
567 
573  inline cv::Ptr<cv::DescriptorMatcher> getMatcher() const { return m_matcher; }
574 
581  inline std::vector<cv::DMatch> getMatches() const { return m_filteredMatches; }
582 
590  inline std::vector<std::pair<cv::KeyPoint, cv::KeyPoint> > getMatchQueryToTrainKeyPoints() const
591  {
592  std::vector<std::pair<cv::KeyPoint, cv::KeyPoint> > matchQueryToTrainKeyPoints(m_filteredMatches.size());
593  for (size_t i = 0; i < m_filteredMatches.size(); i++) {
594  matchQueryToTrainKeyPoints.push_back(
595  std::pair<cv::KeyPoint, cv::KeyPoint>(m_queryFilteredKeyPoints[(size_t)m_filteredMatches[i].queryIdx],
596  m_trainKeyPoints[(size_t)m_filteredMatches[i].trainIdx]));
597  }
598  return matchQueryToTrainKeyPoints;
599  }
600 
606  inline unsigned int getNbImages() const { return static_cast<unsigned int>(m_mapOfImages.size()); }
607 
608  void getObjectPoints(std::vector<cv::Point3f> &objectPoints) const;
609  void getObjectPoints(std::vector<vpPoint> &objectPoints) const;
610 
616  inline double getPoseTime() const { return m_poseTime; }
617 
624  inline cv::Mat getQueryDescriptors() const { return m_queryDescriptors; }
625 
626  void getQueryKeyPoints(std::vector<cv::KeyPoint> &keyPoints) const;
627  void getQueryKeyPoints(std::vector<vpImagePoint> &keyPoints) const;
628 
634  inline std::vector<vpImagePoint> getRansacInliers() const { return m_ransacInliers; }
635 
641  inline std::vector<vpImagePoint> getRansacOutliers() const { return m_ransacOutliers; }
642 
649  inline cv::Mat getTrainDescriptors() const { return m_trainDescriptors; }
650 
651  void getTrainKeyPoints(std::vector<cv::KeyPoint> &keyPoints) const;
652  void getTrainKeyPoints(std::vector<vpImagePoint> &keyPoints) const;
653 
654  void getTrainPoints(std::vector<cv::Point3f> &points) const;
655  void getTrainPoints(std::vector<vpPoint> &points) const;
656 
657  void initMatcher(const std::string &matcherName);
658 
659  void insertImageMatching(const vpImage<unsigned char> &IRef, const vpImage<unsigned char> &ICurrent,
660  vpImage<unsigned char> &IMatching);
661  void insertImageMatching(const vpImage<unsigned char> &ICurrent, vpImage<unsigned char> &IMatching);
662 
663 #ifdef VISP_HAVE_XML2
664  void loadConfigFile(const std::string &configFile);
665 #endif
666 
667  void loadLearningData(const std::string &filename, const bool binaryMode = false, const bool append = false);
668 
669  void match(const cv::Mat &trainDescriptors, const cv::Mat &queryDescriptors, std::vector<cv::DMatch> &matches,
670  double &elapsedTime);
671 
672  unsigned int matchPoint(const vpImage<unsigned char> &I);
673  unsigned int matchPoint(const vpImage<unsigned char> &I, const vpImagePoint &iP, const unsigned int height,
674  const unsigned int width);
675  unsigned int matchPoint(const vpImage<unsigned char> &I, const vpRect &rectangle);
676 
678  bool (*func)(vpHomogeneousMatrix *) = NULL, const vpRect &rectangle = vpRect());
680  double &error, double &elapsedTime, bool (*func)(vpHomogeneousMatrix *) = NULL,
681  const vpRect &rectangle = vpRect());
682 
683  bool matchPointAndDetect(const vpImage<unsigned char> &I, vpRect &boundingBox, vpImagePoint &centerOfGravity,
684  const bool isPlanarObject = true, std::vector<vpImagePoint> *imPts1 = NULL,
685  std::vector<vpImagePoint> *imPts2 = NULL, double *meanDescriptorDistance = NULL,
686  double *detectionScore = NULL, const vpRect &rectangle = vpRect());
687 
688  bool matchPointAndDetect(const vpImage<unsigned char> &I, const vpCameraParameters &cam, vpHomogeneousMatrix &cMo,
689  double &error, double &elapsedTime, vpRect &boundingBox, vpImagePoint &centerOfGravity,
690  bool (*func)(vpHomogeneousMatrix *) = NULL, const vpRect &rectangle = vpRect());
691 
692  void reset();
693 
694  void saveLearningData(const std::string &filename, const bool binaryMode = false,
695  const bool saveTrainingImages = true);
696 
703  inline void setCovarianceComputation(const bool &flag)
704  {
705  m_computeCovariance = flag;
706  if (!m_useRansacVVS) {
707  std::cout << "Warning : The covariance matrix can only be computed "
708  "with a Virtual Visual Servoing approach."
709  << std::endl
710  << "Use setUseRansacVVS(true) to choose to use a pose "
711  "estimation method based on a Virtual "
712  "Visual Servoing approach."
713  << std::endl;
714  }
715  }
716 
722  inline void setDetectionMethod(const vpDetectionMethodType &method) { m_detectionMethod = method; }
723 
729  inline void setDetector(const vpFeatureDetectorType &detectorType)
730  {
731  m_detectorNames.clear();
732  m_detectorNames.push_back(m_mapOfDetectorNames[detectorType]);
733  m_detectors.clear();
734  initDetector(m_mapOfDetectorNames[detectorType]);
735  }
736 
742  inline void setDetector(const std::string &detectorName)
743  {
744  m_detectorNames.clear();
745  m_detectorNames.push_back(detectorName);
746  m_detectors.clear();
747  initDetector(detectorName);
748  }
749 
750 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
751 
759  template <typename T1, typename T2, typename T3>
760  inline void setDetectorParameter(const T1 detectorName, const T2 parameterName, const T3 value)
761  {
762  if (m_detectors.find(detectorName) != m_detectors.end()) {
763  m_detectors[detectorName]->set(parameterName, value);
764  }
765  }
766 #endif
767 
774  inline void setDetectors(const std::vector<std::string> &detectorNames)
775  {
776  m_detectorNames.clear();
777  m_detectors.clear();
778  m_detectorNames = detectorNames;
779  initDetectors(m_detectorNames);
780  }
781 
787  inline void setExtractor(const vpFeatureDescriptorType &extractorType)
788  {
789  m_extractorNames.clear();
790  m_extractorNames.push_back(m_mapOfDescriptorNames[extractorType]);
791  m_extractors.clear();
792  initExtractor(m_mapOfDescriptorNames[extractorType]);
793  }
794 
801  inline void setExtractor(const std::string &extractorName)
802  {
803  m_extractorNames.clear();
804  m_extractorNames.push_back(extractorName);
805  m_extractors.clear();
806  initExtractor(extractorName);
807  }
808 
809 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
810 
818  template <typename T1, typename T2, typename T3>
819  inline void setExtractorParameter(const T1 extractorName, const T2 parameterName, const T3 value)
820  {
821  if (m_extractors.find(extractorName) != m_extractors.end()) {
822  m_extractors[extractorName]->set(parameterName, value);
823  }
824  }
825 #endif
826 
833  inline void setExtractors(const std::vector<std::string> &extractorNames)
834  {
835  m_extractorNames.clear();
836  m_extractorNames = extractorNames;
837  m_extractors.clear();
838  initExtractors(m_extractorNames);
839  }
840 
846  inline void setImageFormat(const vpImageFormatType &imageFormat) { m_imageFormat = imageFormat; }
847 
863  inline void setMatcher(const std::string &matcherName)
864  {
865  m_matcherName = matcherName;
866  initMatcher(m_matcherName);
867  }
868 
884  inline void setFilterMatchingType(const vpFilterMatchingType &filterType)
885  {
886  m_filterType = filterType;
887 
888  // Use k-nearest neighbors (knn) to retrieve the two best matches for a
889  // keypoint So this is useful only for ratioDistanceThreshold method
890  if (filterType == ratioDistanceThreshold || filterType == stdAndRatioDistanceThreshold) {
891  m_useKnn = true;
892 
893 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
894  if (m_matcher != NULL && m_matcherName == "BruteForce") {
895  // if a matcher is already initialized, disable the crossCheck
896  // because it will not work with knnMatch
897  m_matcher->set("crossCheck", false);
898  }
899 #endif
900  } else {
901  m_useKnn = false;
902 
903 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
904  if (m_matcher != NULL && m_matcherName == "BruteForce") {
905  // if a matcher is already initialized, set the crossCheck mode if
906  // necessary
907  m_matcher->set("crossCheck", m_useBruteForceCrossCheck);
908  }
909 #endif
910  }
911  }
912 
919  inline void setMatchingFactorThreshold(const double factor)
920  {
921  if (factor > 0.0) {
922  m_matchingFactorThreshold = factor;
923  } else {
924  throw vpException(vpException::badValue, "The factor must be positive.");
925  }
926  }
927 
933  inline void setMatchingRatioThreshold(const double ratio)
934  {
935  if (ratio > 0.0 && (ratio < 1.0 || std::fabs(ratio - 1.0) < std::numeric_limits<double>::epsilon())) {
936  m_matchingRatioThreshold = ratio;
937  } else {
938  throw vpException(vpException::badValue, "The ratio must be in the interval ]0 ; 1].");
939  }
940  }
941 
948  inline void setRansacConsensusPercentage(const double percentage)
949  {
950  if (percentage > 0.0 &&
951  (percentage < 100.0 || std::fabs(percentage - 100.0) < std::numeric_limits<double>::epsilon())) {
952  m_ransacConsensusPercentage = percentage;
953  } else {
954  throw vpException(vpException::badValue, "The percentage must be in the interval ]0 ; 100].");
955  }
956  }
957 
964  inline void setRansacIteration(const int nbIter)
965  {
966  if (nbIter > 0) {
967  m_nbRansacIterations = nbIter;
968  } else {
969  throw vpException(vpException::badValue, "The number of iterations must be greater than zero.");
970  }
971  }
972 
980  inline void setRansacReprojectionError(const double reprojectionError)
981  {
982  if (reprojectionError > 0.0) {
983  m_ransacReprojectionError = reprojectionError;
984  } else {
985  throw vpException(vpException::badValue, "The Ransac reprojection "
986  "threshold must be positive "
987  "as we deal with distance.");
988  }
989  }
990 
996  inline void setRansacMinInlierCount(const int minCount)
997  {
998  if (minCount > 0) {
999  m_nbRansacMinInlierCount = minCount;
1000  } else {
1001  throw vpException(vpException::badValue, "The minimum number of inliers must be greater than zero.");
1002  }
1003  }
1004 
1011  inline void setRansacThreshold(const double threshold)
1012  {
1013  if (threshold > 0.0) {
1014  m_ransacThreshold = threshold;
1015  } else {
1016  throw vpException(vpException::badValue, "The Ransac threshold must be positive as we deal with distance.");
1017  }
1018  }
1019 
1027  inline void setUseAffineDetection(const bool useAffine) { m_useAffineDetection = useAffine; }
1028 
1029 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
1030 
1036  inline void setUseBruteForceCrossCheck(const bool useCrossCheck)
1037  {
1038  // Only available with BruteForce and with k=1 (i.e not used with a
1039  // ratioDistanceThreshold method)
1040  if (m_matcher != NULL && !m_useKnn && m_matcherName == "BruteForce") {
1041  m_matcher->set("crossCheck", useCrossCheck);
1042  } else if (m_matcher != NULL && m_useKnn && m_matcherName == "BruteForce") {
1043  std::cout << "Warning, you try to set the crossCheck parameter with a "
1044  "BruteForce matcher but knn is enabled";
1045  std::cout << " (the filtering method uses a ratio constraint)" << std::endl;
1046  }
1047  }
1048 #endif
1049 
1056  inline void setUseMatchTrainToQuery(const bool useMatchTrainToQuery)
1057  {
1058  m_useMatchTrainToQuery = useMatchTrainToQuery;
1059  }
1060 
1068  inline void setUseRansacConsensusPercentage(const bool usePercentage) { m_useConsensusPercentage = usePercentage; }
1069 
1077  inline void setUseRansacVVS(const bool ransacVVS) { m_useRansacVVS = ransacVVS; }
1078 
1085  inline void setUseSingleMatchFilter(const bool singleMatchFilter) { m_useSingleMatchFilter = singleMatchFilter; }
1086 
1087 private:
1090  bool m_computeCovariance;
1092  vpMatrix m_covarianceMatrix;
1094  int m_currentImageId;
1097  vpDetectionMethodType m_detectionMethod;
1099  double m_detectionScore;
1102  double m_detectionThreshold;
1104  double m_detectionTime;
1106  std::vector<std::string> m_detectorNames;
1109  // with a key based upon the detector name.
1110  std::map<std::string, cv::Ptr<cv::FeatureDetector> > m_detectors;
1112  double m_extractionTime;
1114  std::vector<std::string> m_extractorNames;
1117  // with a key based upon the extractor name.
1118  std::map<std::string, cv::Ptr<cv::DescriptorExtractor> > m_extractors;
1120  std::vector<cv::DMatch> m_filteredMatches;
1122  vpFilterMatchingType m_filterType;
1124  vpImageFormatType m_imageFormat;
1127  std::vector<std::vector<cv::DMatch> > m_knnMatches;
1129  std::map<vpFeatureDescriptorType, std::string> m_mapOfDescriptorNames;
1131  std::map<vpFeatureDetectorType, std::string> m_mapOfDetectorNames;
1134  std::map<int, int> m_mapOfImageId;
1137  std::map<int, vpImage<unsigned char> > m_mapOfImages;
1140  cv::Ptr<cv::DescriptorMatcher> m_matcher;
1142  std::string m_matcherName;
1144  std::vector<cv::DMatch> m_matches;
1146  double m_matchingFactorThreshold;
1148  double m_matchingRatioThreshold;
1150  double m_matchingTime;
1152  std::vector<std::pair<cv::KeyPoint, cv::Point3f> > m_matchRansacKeyPointsToPoints;
1154  int m_nbRansacIterations;
1156  int m_nbRansacMinInlierCount;
1159  std::vector<cv::Point3f> m_objectFilteredPoints;
1161  double m_poseTime;
1164  cv::Mat m_queryDescriptors;
1166  std::vector<cv::KeyPoint> m_queryFilteredKeyPoints;
1168  std::vector<cv::KeyPoint> m_queryKeyPoints;
1171  double m_ransacConsensusPercentage;
1173  std::vector<vpImagePoint> m_ransacInliers;
1175  std::vector<vpImagePoint> m_ransacOutliers;
1178  double m_ransacReprojectionError;
1181  double m_ransacThreshold;
1184  // detected in the train images).
1185  cv::Mat m_trainDescriptors;
1187  std::vector<cv::KeyPoint> m_trainKeyPoints;
1190  std::vector<cv::Point3f> m_trainPoints;
1193  std::vector<vpPoint> m_trainVpPoints;
1196  bool m_useAffineDetection;
1197 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400 && VISP_HAVE_OPENCV_VERSION < 0x030000)
1198  bool m_useBruteForceCrossCheck;
1202 #endif
1203  bool m_useConsensusPercentage;
1207  bool m_useKnn;
1212  bool m_useMatchTrainToQuery;
1214  bool m_useRansacVVS;
1217  bool m_useSingleMatchFilter;
1218 
1219  void affineSkew(double tilt, double phi, cv::Mat &img, cv::Mat &mask, cv::Mat &Ai);
1220 
1221  double computePoseEstimationError(const std::vector<std::pair<cv::KeyPoint, cv::Point3f> > &matchKeyPoints,
1222  const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo_est);
1223 
1224  void filterMatches();
1225 
1226  void init();
1227  void initDetector(const std::string &detectorNames);
1228  void initDetectors(const std::vector<std::string> &detectorNames);
1229 
1230  void initExtractor(const std::string &extractorName);
1231  void initExtractors(const std::vector<std::string> &extractorNames);
1232 
1233  void initFeatureNames();
1234 
1235  inline size_t myKeypointHash(const cv::KeyPoint &kp)
1236  {
1237  size_t _Val = 2166136261U, scale = 16777619U;
1238  Cv32suf u;
1239  u.f = kp.pt.x;
1240  _Val = (scale * _Val) ^ u.u;
1241  u.f = kp.pt.y;
1242  _Val = (scale * _Val) ^ u.u;
1243  u.f = kp.size;
1244  _Val = (scale * _Val) ^ u.u;
1245  // As the keypoint angle can be computed for certain type of keypoint only
1246  // when extracting the corresponding descriptor, the angle field is not
1247  // taking into account for the hash
1248  // u.f = kp.angle; _Val = (scale * _Val) ^ u.u;
1249  u.f = kp.response;
1250  _Val = (scale * _Val) ^ u.u;
1251  _Val = (scale * _Val) ^ ((size_t)kp.octave);
1252  _Val = (scale * _Val) ^ ((size_t)kp.class_id);
1253  return _Val;
1254  }
1255 
1256 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
1257  /*
1258  * Adapts a detector to detect points over multiple levels of a Gaussian
1259  * pyramid. Useful for detectors that are not inherently scaled.
1260  * From OpenCV 2.4.11 source code.
1261  */
1262  class PyramidAdaptedFeatureDetector : public cv::FeatureDetector
1263  {
1264  public:
1265  // maxLevel - The 0-based index of the last pyramid layer
1266  PyramidAdaptedFeatureDetector(const cv::Ptr<cv::FeatureDetector> &detector, int maxLevel = 2);
1267 
1268  // TODO implement read/write
1269  virtual bool empty() const;
1270 
1271  protected:
1272  virtual void detect(cv::InputArray image, CV_OUT std::vector<cv::KeyPoint> &keypoints,
1273  cv::InputArray mask = cv::noArray());
1274  virtual void detectImpl(const cv::Mat &image, std::vector<cv::KeyPoint> &keypoints,
1275  const cv::Mat &mask = cv::Mat()) const;
1276 
1277  cv::Ptr<cv::FeatureDetector> detector;
1278  int maxLevel;
1279  };
1280 
1281  /*
1282  * A class filters a vector of keypoints.
1283  * Because now it is difficult to provide a convenient interface for all
1284  * usage scenarios of the keypoints filter class, it has only several needed
1285  * by now static methods.
1286  */
1287  class KeyPointsFilter
1288  {
1289  public:
1290  KeyPointsFilter() {}
1291 
1292  /*
1293  * Remove keypoints within borderPixels of an image edge.
1294  */
1295  static void runByImageBorder(std::vector<cv::KeyPoint> &keypoints, cv::Size imageSize, int borderSize);
1296  /*
1297  * Remove keypoints of sizes out of range.
1298  */
1299  static void runByKeypointSize(std::vector<cv::KeyPoint> &keypoints, float minSize, float maxSize = FLT_MAX);
1300  /*
1301  * Remove keypoints from some image by mask for pixels of this image.
1302  */
1303  static void runByPixelsMask(std::vector<cv::KeyPoint> &keypoints, const cv::Mat &mask);
1304  /*
1305  * Remove duplicated keypoints.
1306  */
1307  static void removeDuplicated(std::vector<cv::KeyPoint> &keypoints);
1308 
1309  /*
1310  * Retain the specified number of the best keypoints (according to the
1311  * response)
1312  */
1313  static void retainBest(std::vector<cv::KeyPoint> &keypoints, int npoints);
1314  };
1315 
1316 #endif
1317 };
1318 
1319 #endif
1320 #endif
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
void setRansacIteration(const int nbIter)
Definition: vpKeyPoint.h:964
cv::Ptr< cv::FeatureDetector > getDetector(const vpFeatureDetectorType &type) const
Definition: vpKeyPoint.h:456
class that defines what is a Keypoint. This class provides all the basic elements to implement classe...
void setUseRansacVVS(const bool ransacVVS)
Definition: vpKeyPoint.h:1077
std::vector< std::pair< cv::KeyPoint, cv::KeyPoint > > getMatchQueryToTrainKeyPoints() const
Definition: vpKeyPoint.h:590
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setRansacThreshold(const double threshold)
Definition: vpKeyPoint.h:1011
cv::Ptr< cv::DescriptorMatcher > getMatcher() const
Definition: vpKeyPoint.h:573
void setExtractor(const std::string &extractorName)
Definition: vpKeyPoint.h:801
void setUseSingleMatchFilter(const bool singleMatchFilter)
Definition: vpKeyPoint.h:1085
Class to define colors available for display functionnalities.
Definition: vpColor.h:120
std::map< vpFeatureDetectorType, std::string > getDetectorNames() const
Definition: vpKeyPoint.h:496
double getDetectionTime() const
Definition: vpKeyPoint.h:447
error that can be emited by ViSP classes.
Definition: vpException.h:71
void setDetectors(const std::vector< std::string > &detectorNames)
Definition: vpKeyPoint.h:774
cv::Mat getTrainDescriptors() const
Definition: vpKeyPoint.h:649
vpMatrix getCovarianceMatrix() const
Definition: vpKeyPoint.h:419
static const vpColor green
Definition: vpColor.h:183
Class that defines what is a point.
Definition: vpPoint.h:58
std::vector< vpImagePoint > getRansacOutliers() const
Definition: vpKeyPoint.h:641
void setExtractors(const std::vector< std::string > &extractorNames)
Definition: vpKeyPoint.h:833
void setMatcher(const std::string &matcherName)
Definition: vpKeyPoint.h:863
void setUseMatchTrainToQuery(const bool useMatchTrainToQuery)
Definition: vpKeyPoint.h:1056
cv::Mat getQueryDescriptors() const
Definition: vpKeyPoint.h:624
std::map< vpFeatureDescriptorType, std::string > getExtractorNames() const
Definition: vpKeyPoint.h:552
std::vector< vpImagePoint > getRansacInliers() const
Definition: vpKeyPoint.h:634
vpFeatureDetectorType
Definition: vpKeyPoint.h:259
virtual unsigned int buildReference(const vpImage< unsigned char > &I)=0
Generic class defining intrinsic camera parameters.
vpFeatureDescriptorType
Definition: vpKeyPoint.h:287
void setDetector(const vpFeatureDetectorType &detectorType)
Definition: vpKeyPoint.h:729
double getPoseTime() const
Definition: vpKeyPoint.h:616
unsigned int getNbImages() const
Definition: vpKeyPoint.h:606
void setDetectionMethod(const vpDetectionMethodType &method)
Definition: vpKeyPoint.h:722
void setUseBruteForceCrossCheck(const bool useCrossCheck)
Definition: vpKeyPoint.h:1036
void setRansacMinInlierCount(const int minCount)
Definition: vpKeyPoint.h:996
void setImageFormat(const vpImageFormatType &imageFormat)
Definition: vpKeyPoint.h:846
virtual void display(const vpImage< unsigned char > &Iref, const vpImage< unsigned char > &Icurrent, unsigned int size=3)=0
void setRansacConsensusPercentage(const double percentage)
Definition: vpKeyPoint.h:948
virtual unsigned int matchPoint(const vpImage< unsigned char > &I)=0
cv::Ptr< cv::DescriptorExtractor > getExtractor(const std::string &name) const
Definition: vpKeyPoint.h:538
void setUseAffineDetection(const bool useAffine)
Definition: vpKeyPoint.h:1027
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
Definition: vpKeyPoint.h:223
cv::Ptr< cv::FeatureDetector > getDetector(const std::string &name) const
Definition: vpKeyPoint.h:482
vpDetectionMethodType
Definition: vpKeyPoint.h:242
double getExtractionTime() const
Definition: vpKeyPoint.h:503
void setDetectorParameter(const T1 detectorName, const T2 parameterName, const T3 value)
Definition: vpKeyPoint.h:760
vpFilterMatchingType
Definition: vpKeyPoint.h:228
std::vector< cv::DMatch > getMatches() const
Definition: vpKeyPoint.h:581
double getMatchingTime() const
Definition: vpKeyPoint.h:566
cv::Ptr< cv::DescriptorExtractor > getExtractor(const vpFeatureDescriptorType &type) const
Definition: vpKeyPoint.h:512
void setDetector(const std::string &detectorName)
Definition: vpKeyPoint.h:742
Defines a rectangle in the plane.
Definition: vpRect.h:78
vpImageFormatType getImageFormat() const
Definition: vpKeyPoint.h:559
void setExtractorParameter(const T1 extractorName, const T2 parameterName, const T3 value)
Definition: vpKeyPoint.h:819
void setUseRansacConsensusPercentage(const bool usePercentage)
Definition: vpKeyPoint.h:1068
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:884
void setMatchingFactorThreshold(const double factor)
Definition: vpKeyPoint.h:919
void setExtractor(const vpFeatureDescriptorType &extractorType)
Definition: vpKeyPoint.h:787
void setRansacReprojectionError(const double reprojectionError)
Definition: vpKeyPoint.h:980
void setMatchingRatioThreshold(const double ratio)
Definition: vpKeyPoint.h:933
void setCovarianceComputation(const bool &flag)
Definition: vpKeyPoint.h:703