Advertisement
Guest User

asdf

a guest
Aug 16th, 2017
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.10 KB | None | 0 0
  1. /*------------------------------------------------------------------------------------------*\
  2. This file contains material supporting chapter 10 of the book:
  3. OpenCV3 Computer Vision Application Programming Cookbook
  4. Third Edition
  5. by Robert Laganiere, Packt Publishing, 2016.
  6.  
  7. This program is free software; permission is hereby granted to use, copy, modify,
  8. and distribute this source code, or portions thereof, for any purpose, without fee,
  9. subject to the restriction that the copyright notice may not be removed
  10. or altered from any source or altered source distribution.
  11. The software is released on an as-is basis and without any warranties of any kind.
  12. In particular, the software is not guaranteed to be fault-tolerant or free from failure.
  13. The author disclaims all warranties with regard to this software, any use,
  14. and any consequent failure, is purely the responsibility of the user.
  15.  
  16. Copyright (C) 2016 Robert Laganiere, www.laganiere.name
  17. \*------------------------------------------------------------------------------------------*/
  18.  
  19. #if !defined TMATCHER
  20. #define TMATCHER
  21.  
  22. // set to 1 to view match results, 0 otherwise
  23. #define VERBOSE 1
  24.  
  25. #include <iostream>
  26. #include <vector>
  27. #include <opencv2/core.hpp>
  28. #include <opencv2/imgproc.hpp>
  29. #include <opencv2/highgui.hpp>
  30. #include <opencv2/features2d.hpp>
  31. #include <opencv2/calib3d.hpp>
  32. #include <opencv2/features2d.hpp>
  33.  
  34. class TargetMatcher {
  35.  
  36. private:
  37.  
  38. // pointer to the feature point detector object
  39. cv::Ptr<cv::FeatureDetector> detector;
  40. // pointer to the feature descriptor extractor object
  41. cv::Ptr<cv::DescriptorExtractor> descriptor;
  42. cv::Mat target; // target image
  43. int normType; // to compare descriptor vectors
  44. double distance; // min reprojection error
  45. int numberOfLevels; // pyramid size
  46. double scaleFactor; // scale between levels
  47. // the pyramid of target images and its keypoints
  48. std::vector<cv::Mat> pyramid;
  49. std::vector<std::vector<cv::KeyPoint>> pyrKeypoints;
  50. std::vector<cv::Mat> pyrDescriptors;
  51.  
  52. // create a pyramid of target images
  53. void createPyramid() {
  54.  
  55. // create the pyramid of target images
  56. pyramid.clear();
  57. cv::Mat layer(target);
  58. for (int i = 0; i < numberOfLevels; i++) { // reduce size at each layer
  59. pyramid.push_back(target.clone());
  60. resize(target, target, cv::Size(), scaleFactor, scaleFactor);
  61. }
  62.  
  63. pyrKeypoints.clear();
  64. pyrDescriptors.clear();
  65. // keypoint detection and description in pyramid
  66. for (int i = 0; i < numberOfLevels; i++) {
  67. // detect target keypoints at level i
  68. pyrKeypoints.push_back(std::vector<cv::KeyPoint>());
  69. detector->detect(pyramid[i], pyrKeypoints[i]);
  70. if (VERBOSE)
  71. std::cout << "Interest points: target=" << pyrKeypoints[i].size() << std::endl;
  72. // compute descriptor at level i
  73. pyrDescriptors.push_back(cv::Mat());
  74. descriptor->compute(pyramid[i], pyrKeypoints[i], pyrDescriptors[i]);
  75. }
  76. }
  77.  
  78. public:
  79.  
  80. TargetMatcher(const cv::Ptr<cv::FeatureDetector> &detector,
  81. const cv::Ptr<cv::DescriptorExtractor> &descriptor = cv::Ptr<cv::DescriptorExtractor>(),
  82. int numberOfLevels=8, double scaleFactor=0.9)
  83. : detector(detector), descriptor(descriptor), normType(cv::NORM_L2), distance(1.0),
  84. numberOfLevels(numberOfLevels), scaleFactor(scaleFactor) {
  85.  
  86. // in this case use the associated descriptor
  87. if (!this->descriptor) {
  88. this->descriptor = this->detector;
  89. }
  90. }
  91.  
  92. // Set the norm to be used for matching
  93. void setNormType(int norm) {
  94.  
  95. normType= norm;
  96. }
  97.  
  98. // Set the minimum reprojection distance
  99. void setReprojectionDistance(double d) {
  100.  
  101. distance= d;
  102. }
  103.  
  104. // Set the target image
  105. void setTarget(const cv::Mat t) {
  106.  
  107. if (VERBOSE)
  108. cv::imshow("Target", t);
  109. target= t;
  110. createPyramid();
  111. }
  112.  
  113. // Identify good matches using RANSAC
  114. // Return homography matrix and output matches
  115. cv::Mat ransacTest(const std::vector<cv::DMatch>& matches,
  116. std::vector<cv::KeyPoint>& keypoints1,
  117. std::vector<cv::KeyPoint>& keypoints2,
  118. std::vector<cv::DMatch>& outMatches) {
  119.  
  120. // Convert keypoints into Point2f
  121. std::vector<cv::Point2f> points1, points2;
  122. outMatches.clear();
  123. for (std::vector<cv::DMatch>::const_iterator it= matches.begin();
  124. it!= matches.end(); ++it) {
  125.  
  126. // Get the position of left keypoints
  127. points1.push_back(keypoints1[it->queryIdx].pt);
  128. // Get the position of right keypoints
  129. points2.push_back(keypoints2[it->trainIdx].pt);
  130. }
  131.  
  132. // Find the homography between image 1 and image 2
  133. std::vector<uchar> inliers(points1.size(),0);
  134. cv::Mat homography= cv::findHomography(
  135. points1,points2, // corresponding points
  136. inliers, // match status (inlier or outlier)
  137. cv::RHO, // RHO method
  138. distance); // max distance to reprojection point
  139.  
  140. // extract the surviving (inliers) matches
  141. std::vector<uchar>::const_iterator itIn= inliers.begin();
  142. std::vector<cv::DMatch>::const_iterator itM= matches.begin();
  143. // for all matches
  144. for ( ;itIn!= inliers.end(); ++itIn, ++itM) {
  145.  
  146. if (*itIn) { // it is a valid match
  147.  
  148. outMatches.push_back(*itM);
  149. }
  150. }
  151.  
  152. return homography;
  153. }
  154.  
  155. // detect the defined planar target in an image
  156. // returns the homography and
  157. // the 4 corners of the detected target
  158. cv::Mat detectTarget(const cv::Mat& image,
  159. // position of the target corners (clock-wise)
  160. std::vector<cv::Point2f>& detectedCorners) {
  161.  
  162. // 1. detect image keypoints
  163. std::vector<cv::KeyPoint> keypoints;
  164. detector->detect(image, keypoints);
  165. if (VERBOSE)
  166. std::cout << "Interest points: image=" << keypoints.size() << std::endl;
  167. // compute descriptors
  168. cv::Mat descriptors;
  169. descriptor->compute(image, keypoints, descriptors);
  170. std::vector<cv::DMatch> matches;
  171.  
  172. cv::Mat bestHomography;
  173. cv::Size bestSize;
  174. int maxInliers = 0;
  175. cv::Mat homography;
  176.  
  177. // Construction of the matcher
  178. cv::BFMatcher matcher(normType);
  179.  
  180. // 2. robustly find homography for each pyramid level
  181. for (int i = 0; i < numberOfLevels; i++) {
  182. // find a RANSAC homography between target and image
  183. matches.clear();
  184.  
  185. // match descriptors
  186. matcher.match(pyrDescriptors[i], descriptors, matches);
  187. if (VERBOSE)
  188. std::cout << "Number of matches (level " << i << ")=" << matches.size() << std::endl;
  189. // validate matches using RANSAC
  190. std::vector<cv::DMatch> inliers;
  191. homography = ransacTest(matches, pyrKeypoints[i], keypoints, inliers);
  192. if (VERBOSE)
  193. std::cout << "Number of inliers=" << inliers.size() << std::endl;
  194.  
  195. if (inliers.size() > maxInliers) { // we have a better H
  196. maxInliers = inliers.size();
  197. bestHomography = homography;
  198. bestSize = pyramid[i].size();
  199. }
  200.  
  201. if (VERBOSE) {
  202. cv::Mat imageMatches;
  203. cv::drawMatches(target, pyrKeypoints[i], // 1st image and its keypoints
  204. image, keypoints, // 2nd image and its keypoints
  205. inliers, // the matches
  206. imageMatches, // the image produced
  207. cv::Scalar(255, 255, 255), // color of the lines
  208. cv::Scalar(255, 255, 255), // color of the keypoints
  209. std::vector<char>(),
  210. 2);
  211. cv::imshow("Target matches", imageMatches);
  212. cv::waitKey();
  213. }
  214. }
  215.  
  216. // 3. find the corner position on the image using best homography
  217. if (maxInliers > 8) { // the estimate is valid
  218.  
  219. // target corners at best size
  220. std::vector<cv::Point2f> corners;
  221. corners.push_back(cv::Point2f(0, 0));
  222. corners.push_back(cv::Point2f(bestSize.width - 1, 0));
  223. corners.push_back(cv::Point2f(bestSize.width - 1, bestSize.height - 1));
  224. corners.push_back(cv::Point2f(0, bestSize.height - 1));
  225.  
  226. // reproject the target corners
  227. cv::perspectiveTransform(corners, detectedCorners, bestHomography);
  228. }
  229.  
  230. if (VERBOSE)
  231. std::cout << "Best number of inliers=" << maxInliers << std::endl;
  232. return bestHomography;
  233. }
  234. };
  235.  
  236. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement