1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
14 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
18 // Peng Xiao, pengxiao@multicorewareinc.com
20 // Redistribution and use in source and binary forms, with or without modification,
21 // are permitted provided that the following conditions are met:
23 // * Redistribution's of source code must retain the above copyright notice,
24 // this list of conditions and the following disclaimer.
26 // * Redistribution's in binary form must reproduce the above copyright notice,
27 // this list of conditions and the following disclaimer in the documentation
28 // and/or other oclMaterials provided with the distribution.
30 // * The name of the copyright holders may not be used to endorse or promote products
31 // derived from this software without specific prior written permission.
33 // This software is provided by the copyright holders and contributors as is and
34 // any express or implied warranties, including, but not limited to, the implied
35 // warranties of merchantability and fitness for a particular purpose are disclaimed.
36 // In no event shall the Intel Corporation or contributors be liable for any direct,
37 // indirect, incidental, special, exemplary, or consequential damages
38 // (including, but not limited to, procurement of substitute goods or services;
39 // loss of use, data, or profits; or business interruption) however caused
40 // and on any theory of liability, whether in contract, strict liability,
41 // or tort (including negligence or otherwise) arising in any way out of
42 // the use of this software, even if advised of the possibility of such damage.
48 #include "opencv2/core/core.hpp"
49 #include "opencv2/highgui/highgui.hpp"
50 #include "opencv2/ocl/ocl.hpp"
51 #include "opencv2/nonfree/ocl.hpp"
52 #include "opencv2/calib3d/calib3d.hpp"
53 #include "opencv2/nonfree/nonfree.hpp"
56 using namespace cv::ocl;
58 const int LOOP_NUM = 10;
59 const int GOOD_PTS_MAX = 50;
60 const float GOOD_PORTION = 0.15f;
68 std::cout << "\nThis program demonstrates using SURF_OCL features detector and descriptor extractor" << std::endl;
69 std::cout << "\nUsage:\n\tsurf_matcher --left <image1> --right <image2> [-c]" << std::endl;
70 std::cout << "\nExample:\n\tsurf_matcher --left box.png --right box_in_scene.png" << std::endl;
78 work_begin = getTickCount();
82 work_end = getTickCount() - work_begin;
85 return work_end /((double)cvGetTickFrequency() * 1000.);
88 template<class KPDetector>
92 SURFDetector(double hessian = 800.0)
97 void operator()(const T& in, const T& mask, vector<cv::KeyPoint>& pts, T& descriptors, bool useProvided = false)
99 surf(in, mask, pts, descriptors, useProvided);
103 template<class KPMatcher>
108 void match(const T& in1, const T& in2, vector<cv::DMatch>& matches)
110 matcher.match(in1, in2, matches);
117 const vector<KeyPoint>& keypoints1,
118 const vector<KeyPoint>& keypoints2,
119 vector<DMatch>& matches,
120 vector<Point2f>& scene_corners_
123 //-- Sort matches and preserve top 10% matches
124 std::sort(matches.begin(), matches.end());
125 std::vector< DMatch > good_matches;
126 double minDist = matches.front().distance,
127 maxDist = matches.back().distance;
129 const int ptsPairs = std::min(GOOD_PTS_MAX, (int)(matches.size() * GOOD_PORTION));
130 for( int i = 0; i < ptsPairs; i++ )
132 good_matches.push_back( matches[i] );
134 std::cout << "\nMax distance: " << maxDist << std::endl;
135 std::cout << "Min distance: " << minDist << std::endl;
137 std::cout << "Calculating homography using " << ptsPairs << " point pairs." << std::endl;
139 // drawing the results
141 drawMatches( cpu_img1, keypoints1, cpu_img2, keypoints2,
142 good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
143 vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
145 //-- Localize the object
146 std::vector<Point2f> obj;
147 std::vector<Point2f> scene;
149 for( size_t i = 0; i < good_matches.size(); i++ )
151 //-- Get the keypoints from the good matches
152 obj.push_back( keypoints1[ good_matches[i].queryIdx ].pt );
153 scene.push_back( keypoints2[ good_matches[i].trainIdx ].pt );
155 //-- Get the corners from the image_1 ( the object to be "detected" )
156 std::vector<Point2f> obj_corners(4);
157 obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( cpu_img1.cols, 0 );
158 obj_corners[2] = cvPoint( cpu_img1.cols, cpu_img1.rows ); obj_corners[3] = cvPoint( 0, cpu_img1.rows );
159 std::vector<Point2f> scene_corners(4);
161 Mat H = findHomography( obj, scene, CV_RANSAC );
162 perspectiveTransform( obj_corners, scene_corners, H);
164 scene_corners_ = scene_corners;
166 //-- Draw lines between the corners (the mapped object in the scene - image_2 )
168 scene_corners[0] + Point2f( (float)cpu_img1.cols, 0), scene_corners[1] + Point2f( (float)cpu_img1.cols, 0),
169 Scalar( 0, 255, 0), 2, CV_AA );
171 scene_corners[1] + Point2f( (float)cpu_img1.cols, 0), scene_corners[2] + Point2f( (float)cpu_img1.cols, 0),
172 Scalar( 0, 255, 0), 2, CV_AA );
174 scene_corners[2] + Point2f( (float)cpu_img1.cols, 0), scene_corners[3] + Point2f( (float)cpu_img1.cols, 0),
175 Scalar( 0, 255, 0), 2, CV_AA );
177 scene_corners[3] + Point2f( (float)cpu_img1.cols, 0), scene_corners[0] + Point2f( (float)cpu_img1.cols, 0),
178 Scalar( 0, 255, 0), 2, CV_AA );
183 ////////////////////////////////////////////////////
184 // This program demonstrates the usage of SURF_OCL.
185 // use cpu findHomography interface to calculate the transformation matrix
186 int main(int argc, char* argv[])
188 vector<cv::ocl::Info> info;
189 if(cv::ocl::getDevice(info) == 0)
191 std::cout << "Error: Did not find a valid OpenCL device!" << std::endl;
194 ocl::setDevice(info[0]);
196 Mat cpu_img1, cpu_img2, cpu_img1_grey, cpu_img2_grey;
202 for (int i = 1; i < argc; ++i)
204 if (string(argv[i]) == "--left")
206 cpu_img1 = imread(argv[++i]);
207 CV_Assert(!cpu_img1.empty());
208 cvtColor(cpu_img1, cpu_img1_grey, CV_BGR2GRAY);
209 img1 = cpu_img1_grey;
211 else if (string(argv[i]) == "--right")
213 cpu_img2 = imread(argv[++i]);
214 CV_Assert(!cpu_img2.empty());
215 cvtColor(cpu_img2, cpu_img2_grey, CV_BGR2GRAY);
216 img2 = cpu_img2_grey;
218 else if (string(argv[i]) == "-c")
223 }else if(string(argv[i]) == "-g")
228 }else if(string(argv[i]) == "-a")
234 else if (string(argv[i]) == "--help")
244 << info[0].DeviceName[0]
247 double surf_time = 0.;
249 //declare input/output
250 vector<KeyPoint> keypoints1, keypoints2;
251 vector<DMatch> matches;
253 vector<KeyPoint> gpu_keypoints1;
254 vector<KeyPoint> gpu_keypoints2;
255 vector<DMatch> gpu_matches;
257 Mat descriptors1CPU, descriptors2CPU;
259 oclMat keypoints1GPU, keypoints2GPU;
260 oclMat descriptors1GPU, descriptors2GPU;
262 //instantiate detectors/matchers
263 SURFDetector<SURF> cpp_surf;
264 SURFDetector<SURF_OCL> ocl_surf;
266 SURFMatcher<BFMatcher> cpp_matcher;
267 SURFMatcher<BFMatcher_OCL> ocl_matcher;
269 //-- start of timing section
272 for (int i = 0; i <= LOOP_NUM; i++)
274 if(i == 1) workBegin();
275 cpp_surf(cpu_img1_grey, Mat(), keypoints1, descriptors1CPU);
276 cpp_surf(cpu_img2_grey, Mat(), keypoints2, descriptors2CPU);
277 cpp_matcher.match(descriptors1CPU, descriptors2CPU, matches);
280 std::cout << "CPP: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl;
281 std::cout << "CPP: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl;
283 surf_time = getTime();
284 std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n";
288 for (int i = 0; i <= LOOP_NUM; i++)
290 if(i == 1) workBegin();
291 ocl_surf(img1, oclMat(), keypoints1, descriptors1GPU);
292 ocl_surf(img2, oclMat(), keypoints2, descriptors2GPU);
293 ocl_matcher.match(descriptors1GPU, descriptors2GPU, matches);
296 std::cout << "OCL: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl;
297 std::cout << "OCL: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl;
299 surf_time = getTime();
300 std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n";
304 for (int i = 0; i <= LOOP_NUM; i++)
306 if(i == 1) workBegin();
307 cpp_surf(cpu_img1_grey, Mat(), keypoints1, descriptors1CPU);
308 cpp_surf(cpu_img2_grey, Mat(), keypoints2, descriptors2CPU);
309 cpp_matcher.match(descriptors1CPU, descriptors2CPU, matches);
312 std::cout << "\nCPP: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl;
313 std::cout << "CPP: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl;
315 surf_time = getTime();
316 std::cout << "(CPP)SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl;
319 for (int i = 0; i <= LOOP_NUM; i++)
321 if(i == 1) workBegin();
322 ocl_surf(img1, oclMat(), gpu_keypoints1, descriptors1GPU);
323 ocl_surf(img2, oclMat(), gpu_keypoints2, descriptors2GPU);
324 ocl_matcher.match(descriptors1GPU, descriptors2GPU, gpu_matches);
327 std::cout << "\nOCL: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl;
328 std::cout << "OCL: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl;
330 surf_time = getTime();
331 std::cout << "(OCL)SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n";
335 //--------------------------------------------------------------------------
336 std::vector<Point2f> cpu_corner;
337 Mat img_matches = drawGoodMatches(cpu_img1, cpu_img2, keypoints1, keypoints2, matches, cpu_corner);
339 std::vector<Point2f> gpu_corner;
341 if(useALL || (!useCPU&&!useGPU))
343 ocl_img_matches = drawGoodMatches(cpu_img1, cpu_img2, gpu_keypoints1, gpu_keypoints2, gpu_matches, gpu_corner);
346 std::cout<<"\nCheck accuracy:\n";
348 if(cpu_corner.size()!=gpu_corner.size())
349 std::cout<<"Failed\n";
353 for(size_t i = 0; i < cpu_corner.size(); i++)
355 if((std::abs(cpu_corner[i].x - gpu_corner[i].x) > 10)
356 ||(std::abs(cpu_corner[i].y - gpu_corner[i].y) > 10))
358 std::cout<<"Failed\n";
365 std::cout<<"Passed\n";
369 //-- Show detected matches
372 namedWindow("cpu surf matches", 0);
373 imshow("cpu surf matches", img_matches);
377 namedWindow("ocl surf matches", 0);
378 imshow("ocl surf matches", img_matches);
381 namedWindow("cpu surf matches", 0);
382 imshow("cpu surf matches", img_matches);
384 namedWindow("ocl surf matches", 0);
385 imshow("ocl surf matches", ocl_img_matches);