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 * Planar surface detection tool. 33 * 34 * Authors: 35 * Romain Tallonneau 36 * 37 *****************************************************************************/ 38 39 #ifndef VPPLANAROBJECTDETECTOR_H_ 40 #define VPPLANAROBJECTDETECTOR_H_ 41 42 #include <visp3/core/vpConfig.h> 43 44 #if (VISP_HAVE_OPENCV_VERSION >= 0x020000) && \ 45 (VISP_HAVE_OPENCV_VERSION < 0x030000) // Require opencv >= 2.0.0 and < 3.0.0 46 47 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1 48 #include <opencv2/calib3d/calib3d.hpp> 49 #include <opencv2/features2d/features2d.hpp> 50 #include <opencv2/imgproc/imgproc.hpp> 51 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020000) // Require opencv >= 2.0.0 52 #include <cv.h> 53 #include <cvaux.hpp> 54 #endif 55 56 #include <visp3/core/vpCameraParameters.h> 57 #include <visp3/core/vpHomogeneousMatrix.h> 58 #include <visp3/core/vpImage.h> 59 #include <visp3/core/vpImagePoint.h> 60 #include <visp3/core/vpPoint.h> 61 #include <visp3/core/vpRect.h> 62 #include <visp3/vision/vpFernClassifier.h> 63 #include <visp3/vision/vpHomography.h> 64 65 /*! 66 \class vpPlanarObjectDetector 67 \ingroup group_vision_keypoints 68 69 \brief Class used to detect a planar surface. 70 71 \deprecated This class is deprecated with OpenCV 3.0.0 or more recent. 72 73 This class allows to learn and recognise a surface in an image based on the 74 Fern Classifier or any other point of interest matching class. 75 76 It uses the class vpFernClassifier to extract points of interest in a 77 reference image. These points are recorded and a classifier is trained to 78 recognises them. 79 80 In this class the points detected are assumed to belong to a planar surface. 81 Therefore an homography can be computed between the reference image and the 82 current image if the object is detected in the image. 83 84 A robust method (RANSAC) is used to remove outliers in the matching process. 85 86 The following example shows how to use the class. 87 88 \code 89 #include <visp3/core/vpDisplay.h> 90 #include <visp3/core/vpImage.h> 91 #include <visp3/vision/vpPlanarObjectDetector.h> 92 93 #if VISP_HAVE_OPENCV_VERSION >= 0x020000 // Surf Fern classifier only 94 available since 2.1.0 int main() 95 { 96 vpImage<unsigned char> Ireference; 97 vpImage<unsigned char> Icurrent; 98 vpPlanarObjectDetector planar; 99 100 //First grab the reference image Ireference 101 102 //Select a part of the image by clincking on two points which define a rectangle 103 vpImagePoint corners[2]; 104 for (int i=0 ; i < 2 ; i++) { 105 vpDisplay::getClick(Ireference, corners[i]); 106 } 107 108 //Build the reference points (and train the classifier). 109 int nbrRef; 110 unsigned int height, width; 111 height = (unsigned int)(corners[1].get_i() - corners[0].get_i()); 112 width = (unsigned int)(corners[1].get_j() - corners[0].get_j()); 113 nbrRef = planar.buildReference(Ireference, corners[0], height, width); 114 115 //Then grab another image which represents the current image Icurrent 116 117 //Match points between the reference points and the current points computed in the current image. 118 bool isDetected; height = (unsigned int)(corners[1].get_i() - corners[0].get_i()); 119 width = (unsigned int)(corners[1].get_j() - corners[0].get_j()); 120 isDetected = planar.matchPoint(Icurrent, corners[0], height, width); 121 122 //Display the matched points 123 if(isDetected){ 124 planar.display(Ireference, Icurrent); 125 vpHomography homography; 126 planar.getHomography(homography); 127 } 128 else{ 129 std::cerr << "planar surface not detected in the current image" << std::endl; 130 } 131 132 return(0); 133 } 134 #else 135 int main() {} 136 #endif 137 \endcode 138 139 */ 140 class VISP_EXPORT vpPlanarObjectDetector 141 { 142 protected: 143 //! Fern Classifier used to match the points between a reference image and 144 //! the current image. 145 vpFernClassifier fern; 146 147 //! Computed homography in the ViSP format. 148 vpHomography homography; 149 //! Computed homography in the OpenCV format. 150 cv::Mat H; 151 152 //! The estimated new coordinates of the corners (reprojected using the 153 //! homography). 154 std::vector<cv::Point2f> dst_corners; 155 156 //! Flag to indicate wether the last computed homography is correct or not. 157 bool isCorrect; 158 159 //! The corners in the reference image 160 std::vector<cv::Point2f> ref_corners; 161 162 //! The ROI for the reference image. 163 cv::Rect modelROI; 164 165 //! Vector of the image point in the current image that match after the 166 //! deletion of the outliers with the RANSAC. 167 std::vector<vpImagePoint> currentImagePoints; 168 //! Vector of the image point in the reference image that match after the 169 //! deletion of the outliers with the RANSAC. 170 std::vector<vpImagePoint> refImagePoints; 171 172 //! Minimal number of point to after the ransac needed to suppose that the 173 //! homography has been correctly computed. 174 unsigned int minNbMatching; 175 176 public: 177 // constructors and destructors 178 vpPlanarObjectDetector(); 179 vpPlanarObjectDetector(const std::string &dataFile, const std::string &objectName); 180 virtual ~vpPlanarObjectDetector(); 181 182 // main functions 183 // creation of reference 184 unsigned int buildReference(const vpImage<unsigned char> &I); 185 unsigned int buildReference(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height, 186 unsigned int width); 187 unsigned int buildReference(const vpImage<unsigned char> &I, const vpRect &rectangle); 188 189 // matching 190 bool matchPoint(const vpImage<unsigned char> &I); 191 bool matchPoint(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height, 192 unsigned int width); 193 bool matchPoint(const vpImage<unsigned char> &I, const vpRect &rectangle); 194 // database management 195 void recordDetector(const std::string &objectName, const std::string &dataFile); 196 void load(const std::string &dataFilename, const std::string &objName); 197 198 // display 199 void display(vpImage<unsigned char> &I, bool displayKpts = false); 200 void display(vpImage<unsigned char> &Iref, vpImage<unsigned char> &Icurrent, bool displayKpts = false); 201 202 /*! 203 Return the positions of the detected corners. 204 205 \return a vector of vpImagePoint containing the position of the corners of 206 the planar surface in the current image. 207 */ 208 std::vector<vpImagePoint> getDetectedCorners() const; 209 210 /*! 211 Return a reference to the classifier. 212 213 \return The fern classifier. 214 */ getFernClassifier()215 vpFernClassifier &getFernClassifier() { return this->fern; } 216 217 /*! 218 Return the computed homography between the reference image and the current 219 image. 220 221 \param _H : The computed homography. 222 */ getHomography(vpHomography & _H)223 inline void getHomography(vpHomography &_H) const { _H = this->homography; } 224 225 /*! 226 Return the number of reference points 227 228 \return Number of reference points. 229 */ getNbRefPoints()230 inline unsigned int getNbRefPoints() { return (unsigned int)currentImagePoints.size(); } 231 232 /*! 233 Get the i-th reference point. 234 235 \throw vpException if _i is out if bound. 236 237 \param _i : index of the point to get 238 \param _imPoint : image point returned by the 239 */ 240 void getReferencePoint(const unsigned int _i, vpImagePoint &_imPoint); 241 242 /*! 243 Get the nth couple of reference point and current point which have been 244 matched. These points are copied in the vpImagePoint instances given in 245 argument. 246 247 \param _index : The index of the desired couple of reference point and 248 current point . The index must be between 0 and the number of matched 249 points - 1. \param _referencePoint : The coordinates of the desired 250 reference point are copied here. \param _currentPoint : The coordinates of 251 the desired current point are copied here. 252 */ 253 void getMatchedPoints(const unsigned int _index, vpImagePoint &_referencePoint, vpImagePoint &_currentPoint); 254 255 /*! 256 Set the threshold for the minimal number of point to validate the 257 homography. Default value is 10. 258 259 \param _min : the new threshold. 260 */ setMinNbPointValidation(const unsigned int _min)261 void setMinNbPointValidation(const unsigned int _min) { this->minNbMatching = _min; } 262 263 /*! 264 Get the threshold for the minimal number of point to validate the 265 homography. Default value is 10. 266 267 \return : the current threshold. 268 */ getMinNbPointValidation()269 unsigned int getMinNbPointValidation() const { return this->minNbMatching; } 270 271 protected: 272 virtual void init(); 273 void computeRoi(vpImagePoint *ip, unsigned int nbpt); 274 void initialiseRefCorners(const cv::Rect &_modelROI); 275 }; 276 277 #endif 278 279 #endif /* VPPLANAROBJECTDETECTOR_H_ */ 280