1Features2D + Homography to find a known object {#tutorial_feature_homography} 2============================================== 3 4Goal 5---- 6 7In this tutorial you will learn how to: 8 9- Use the function @ref cv::findHomography to find the transform between matched keypoints. 10- Use the function @ref cv::perspectiveTransform to map the points. 11 12Theory 13------ 14 15Code 16---- 17 18This tutorial code's is shown lines below. 19@code{.cpp} 20#include <stdio.h> 21#include <iostream> 22#include "opencv2/core.hpp" 23#include "opencv2/imgproc.hpp" 24#include "opencv2/features2d.hpp" 25#include "opencv2/highgui.hpp" 26#include "opencv2/calib3d.hpp" 27#include "opencv2/xfeatures2d.hpp" 28 29using namespace cv; 30using namespace cv::xfeatures2d; 31 32void readme(); 33 34/* @function main */ 35int main( int argc, char** argv ) 36{ 37 if( argc != 3 ) 38 { readme(); return -1; } 39 40 Mat img_object = imread( argv[1], IMREAD_GRAYSCALE ); 41 Mat img_scene = imread( argv[2], IMREAD_GRAYSCALE ); 42 43 if( !img_object.data || !img_scene.data ) 44 { std::cout<< " --(!) Error reading images " << std::endl; return -1; } 45 46 //-- Step 1: Detect the keypoints and extract descriptors using SURF 47 int minHessian = 400; 48 49 Ptr<SURF> detector = SURF::create( minHessian ); 50 51 std::vector<KeyPoint> keypoints_object, keypoints_scene; 52 Mat descriptors_object, descriptors_scene; 53 54 detector->detectAndCompute( img_object, Mat(), keypoints_object, descriptors_object ); 55 detector->detectAndCompute( img_scene, Mat(), keypoints_scene, descriptors_scene ); 56 57 //-- Step 2: Matching descriptor vectors using FLANN matcher 58 FlannBasedMatcher matcher; 59 std::vector< DMatch > matches; 60 matcher.match( descriptors_object, descriptors_scene, matches ); 61 62 double max_dist = 0; double min_dist = 100; 63 64 //-- Quick calculation of max and min distances between keypoints 65 for( int i = 0; i < descriptors_object.rows; i++ ) 66 { double dist = matches[i].distance; 67 if( dist < min_dist ) min_dist = dist; 68 if( dist > max_dist ) max_dist = dist; 69 } 70 71 printf("-- Max dist : %f \n", max_dist ); 72 printf("-- Min dist : %f \n", min_dist ); 73 74 //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist ) 75 std::vector< DMatch > good_matches; 76 77 for( int i = 0; i < descriptors_object.rows; i++ ) 78 { if( matches[i].distance < 3*min_dist ) 79 { good_matches.push_back( matches[i]); } 80 } 81 82 Mat img_matches; 83 drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, 84 good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), 85 std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 86 87 //-- Localize the object 88 std::vector<Point2f> obj; 89 std::vector<Point2f> scene; 90 91 for( size_t i = 0; i < good_matches.size(); i++ ) 92 { 93 //-- Get the keypoints from the good matches 94 obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt ); 95 scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt ); 96 } 97 98 Mat H = findHomography( obj, scene, RANSAC ); 99 100 //-- Get the corners from the image_1 ( the object to be "detected" ) 101 std::vector<Point2f> obj_corners(4); 102 obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 ); 103 obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows ); 104 std::vector<Point2f> scene_corners(4); 105 106 perspectiveTransform( obj_corners, scene_corners, H); 107 108 //-- Draw lines between the corners (the mapped object in the scene - image_2 ) 109 line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 ); 110 line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 ); 111 line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 ); 112 line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 ); 113 114 //-- Show detected matches 115 imshow( "Good Matches & Object detection", img_matches ); 116 117 waitKey(0); 118 return 0; 119 } 120 121 /* @function readme */ 122 void readme() 123 { std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; } 124@endcode 125Explanation 126----------- 127 128Result 129------ 130 131-# And here is the result for the detected object (highlighted in green) 132 133 ![](images/Feature_Homography_Result.jpg) 134