{"id":9216,"date":"2016-12-02T07:49:30","date_gmt":"2016-12-02T12:49:30","guid":{"rendered":"httpss:\/\/www.powenko.com\/wordpress\/?p=9216"},"modified":"2016-12-02T07:49:30","modified_gmt":"2016-12-02T12:49:30","slug":"05-homography","status":"publish","type":"post","link":"https:\/\/www.powenko.com\/wordpress\/?p=9216","title":{"rendered":"05 Homography"},"content":{"rendered":"<p>\u5728FLANN\u7279\u5fb5\u4e0a\uff0c\u9084\u53ef\u4ee5\u9032\u4e00\u6b65\u5229\u7528Homography\u6620\u5c04\u627e\u51fa\u5df2\u77e5\u7269\u9ad4\u3002<br \/>\n\u5c31\u662f\u5229\u7528findHomography\u51fd\u6578\uff0c\u5229\u7528\u5339\u914d\u7684\u95dc\u9375\u9ede\u627e\u51fa\u76f8\u61c9\u7684\u8b8a\u63db\uff0c\u518d\u5229\u7528perspectiveTransform\u51fd\u6578\u6620\u5c04\u9ede\u7fa4\u3002<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;opencv2\/core\/core.hpp&gt;\r\n#include &lt;opencv2\/features2d\/features2d.hpp&gt;\r\n#include &lt;opencv2\/nonfree\/features2d.hpp&gt;\r\n#include &lt;opencv2\/highgui\/highgui.hpp&gt;\r\n#include &lt;opencv2\/calib3d\/calib3d.hpp&gt;\r\n#include &lt;opencv2\/nonfree\/nonfree.hpp&gt;\r\n\r\n\r\nusing namespace cv;\r\n\r\nvoid readme();\r\n\r\n\/** @function main *\/\r\nint main( int argc, char** argv )\r\n{\r\n   \r\n    \r\n    Mat img_1 = imread( &quot;\/Users\/powenko\/Desktop\/doughnut.png&quot;, CV_LOAD_IMAGE_GRAYSCALE );\r\n    Mat img_2 = imread( &quot;\/Users\/powenko\/Desktop\/doughnuts.png&quot;, CV_LOAD_IMAGE_GRAYSCALE );\r\n    \r\n    \r\n    Mat img_object =img_1; \/\/ imread( argv&#x5B;1], CV_LOAD_IMAGE_GRAYSCALE );\r\n    Mat img_scene = img_2; \/\/imread( argv&#x5B;2], CV_LOAD_IMAGE_GRAYSCALE );\r\n    \r\n    if( !img_object.data || !img_scene.data )\r\n    { std::cout&lt;&lt; &quot; --(!) Error reading images &quot; &lt;&lt; std::endl; return -1; }\r\n    \r\n    \/\/-- Step 1: Detect the keypoints using SURF Detector\r\n    int minHessian = 400;\r\n    \r\n    SurfFeatureDetector detector( minHessian );\r\n    \r\n    std::vector&lt;KeyPoint&gt; keypoints_object, keypoints_scene;\r\n    \r\n    detector.detect( img_object, keypoints_object );\r\n    detector.detect( img_scene, keypoints_scene );\r\n    \r\n    \/\/-- Step 2: Calculate descriptors (feature vectors)\r\n    SurfDescriptorExtractor extractor;\r\n    \r\n    Mat descriptors_object, descriptors_scene;\r\n    \r\n    extractor.compute( img_object, keypoints_object, descriptors_object );\r\n    extractor.compute( img_scene, keypoints_scene, descriptors_scene );\r\n    \r\n    \/\/-- Step 3: Matching descriptor vectors using FLANN matcher\r\n    FlannBasedMatcher matcher;\r\n    std::vector&lt; DMatch &gt; matches;\r\n    matcher.match( descriptors_object, descriptors_scene, matches );\r\n    \r\n    double max_dist = 0; double min_dist = 100;\r\n    \r\n    \/\/-- Quick calculation of max and min distances between keypoints\r\n    for( int i = 0; i &lt; descriptors_object.rows; i++ )\r\n    { double dist = matches&#x5B;i].distance;\r\n        if( dist &lt; min_dist ) min_dist = dist;\r\n        if( dist &gt; max_dist ) max_dist = dist;\r\n    }\r\n    \r\n    printf(&quot;-- Max dist : %f \\n&quot;, max_dist );\r\n    printf(&quot;-- Min dist : %f \\n&quot;, min_dist );\r\n    \r\n    \/\/-- Draw only &quot;good&quot; matches (i.e. whose distance is less than 3*min_dist )\r\n    std::vector&lt; DMatch &gt; good_matches;\r\n    \r\n    for( int i = 0; i &lt; descriptors_object.rows; i++ )\r\n    { if( matches&#x5B;i].distance &lt; 3*min_dist )\r\n    { good_matches.push_back( matches&#x5B;i]); }\r\n    }\r\n    \r\n    Mat img_matches;\r\n    drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,\r\n                good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),\r\n                vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );\r\n    \r\n    \/\/-- Localize the object\r\n    std::vector&lt;Point2f&gt; obj;\r\n    std::vector&lt;Point2f&gt; scene;\r\n    \r\n    for( int i = 0; i &lt; good_matches.size(); i++ )\r\n    {\r\n        \/\/-- Get the keypoints from the good matches\r\n        obj.push_back( keypoints_object&#x5B; good_matches&#x5B;i].queryIdx ].pt );\r\n        scene.push_back( keypoints_scene&#x5B; good_matches&#x5B;i].trainIdx ].pt );\r\n    }\r\n    \r\n    Mat H = findHomography( obj, scene, CV_RANSAC );\r\n    \r\n    \/\/-- Get the corners from the image_1 ( the object to be &quot;detected&quot; )\r\n    std::vector&lt;Point2f&gt; obj_corners(4);\r\n    obj_corners&#x5B;0] = cvPoint(0,0); obj_corners&#x5B;1] = cvPoint( img_object.cols, 0 );\r\n    obj_corners&#x5B;2] = cvPoint( img_object.cols, img_object.rows ); obj_corners&#x5B;3] = cvPoint( 0, img_object.rows );\r\n    std::vector&lt;Point2f&gt; scene_corners(4);\r\n    \r\n    perspectiveTransform( obj_corners, scene_corners, H);\r\n    \r\n    \/\/-- Draw lines between the corners (the mapped object in the scene - image_2 )\r\n    line( img_matches, scene_corners&#x5B;0] + Point2f( img_object.cols, 0), scene_corners&#x5B;1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );\r\n    line( img_matches, scene_corners&#x5B;1] + Point2f( img_object.cols, 0), scene_corners&#x5B;2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );\r\n    line( img_matches, scene_corners&#x5B;2] + Point2f( img_object.cols, 0), scene_corners&#x5B;3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );\r\n    line( img_matches, scene_corners&#x5B;3] + Point2f( img_object.cols, 0), scene_corners&#x5B;0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );\r\n    \r\n    \/\/-- Show detected matches\r\n    imshow( &quot;Good Matches &amp; Object detection&quot;, img_matches );\r\n    \r\n    waitKey(0);\r\n    return 0;\r\n}\r\n\r\n\/** @function readme *\/\r\nvoid readme()\r\n{ std::cout &lt;&lt; &quot; Usage: .\/SURF_descriptor &lt;img1&gt; &lt;img2&gt;&quot; &lt;&lt; std::endl; }\r\n<\/pre>\n<p><a href=\"httpss:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM.png\"><img loading=\"lazy\" decoding=\"async\" src=\"httpss:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-570x352.png\" alt=\"screen-shot-2016-12-02-at-8-45-54-pm\" width=\"570\" height=\"352\" class=\"alignnone size-medium wp-image-9217\" srcset=\"https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-570x352.png 570w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-300x185.png 300w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-316x195.png 316w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-120x74.png 120w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-210x130.png 210w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-496x307.png 496w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM-140x87.png 140w, https:\/\/www.powenko.com\/wordpress\/wp-content\/uploads\/2016\/12\/Screen-Shot-2016-12-02-at-8.45.54-PM.png 1301w\" sizes=\"(max-width: 570px) 100vw, 570px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728FLANN\u7279\u5fb5\u4e0a\uff0c\u9084\u53ef\u4ee5\u9032\u4e00\u6b65\u5229\u7528Homography\u6620\u5c04\u627e\u51fa\u5df2\u77e5\u7269\u9ad4\u3002 \u5c31\u662f\u5229\u7528findHomograph [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9217,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[338],"tags":[],"class_list":["post-9216","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ch06-surfsift"],"_links":{"self":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9216"}],"collection":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9216"}],"version-history":[{"count":1,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9216\/revisions"}],"predecessor-version":[{"id":9220,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9216\/revisions\/9220"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/9217"}],"wp:attachment":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}