opencv学习笔记三十五:基于透视变换的FLANN匹配对象检测

 步骤:先用SURF描述子检测关键点,再利用FLANN匹配对关键点进行筛选匹配,最后利用透视变换将匹配后的对象画出来。

#include<opencv2\opencv.hpp>
#include<opencv2\xfeatures2d.hpp>

using namespace cv;
using namespace xfeatures2d;
using namespace std;
int main(int arc, char** argv) 
{ 
	Mat src1 = imread("1.png",IMREAD_GRAYSCALE);
	Mat src2 = imread("2.png", IMREAD_GRAYSCALE);
	namedWindow("input1", CV_WINDOW_AUTOSIZE);
	imshow("input1", src1);
	imshow("input2", src2);
	//surf features extraction
	int minHessian = 400;
	Ptr<SURF>surf = SURF::create(minHessian);
	vector<KeyPoint>keypoints1, keypoints2;
	Mat descriptors1, descriptors2;
	surf->detectAndCompute(src1, Mat(), keypoints1, descriptors1);
	surf->detectAndCompute(src2, Mat(), keypoints2, descriptors2);
	//match
	FlannBasedMatcher matcher;
	vector<DMatch>matches;
	matcher.match(descriptors1, descriptors2, matches);
	//looking for some good match
	double minDist = 1000;
	double maxDist = 0;
	for (int i = 0; i < descriptors1.rows; i++) 
	{
		double dist = matches[i].distance;
		if (dist > maxDist) 
		{
			maxDist = dist;
		}
		if (dist < minDist) 
		{
			minDist = dist;
		}
	}
	printf("max distance:%lf\n", maxDist);
	printf("min distance:%lf\n", minDist);
	vector<DMatch>goodMatchers;
	for (int i = 0; i < descriptors1.rows; i++) 
	{
		double dist = matches[i].distance;
		if (dist < max(3*minDist,0.02)) 
		{
			goodMatchers.push_back(matches[i]);
		}
	}
	//draw matches_img
	Mat matches_img;
	drawMatches(src1, keypoints1, src2, keypoints2, goodMatchers, matches_img, Scalar::all(-1), Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

	vector<Point2f>srcGoodPoints;
	vector<Point2f>dstGoodPoints;
	for (int j = 0; j < goodMatchers.size(); j++)
	{
		srcGoodPoints.push_back(keypoints1[goodMatchers[j].queryIdx].pt);
		dstGoodPoints.push_back(keypoints2[goodMatchers[j].trainIdx].pt);
	}
	Mat H = findHomography(srcGoodPoints, dstGoodPoints, RANSAC);//寻找透视矩阵
	
	//detect object
	vector<Point2f>src_corners(4);
	vector<Point2f>dst_corners(4);
	src_corners[0] = Point(0, 0);
	src_corners[1] = Point(src1.cols, 0);
	src_corners[2] = Point(src1.cols, src1.rows);
	src_corners[3] = Point(0,src1.rows);

	perspectiveTransform(src_corners, dst_corners, H);//点的透视变换
	//在匹配图上画出目标,因为匹配图的画布是两幅图合在一起的,所以需要加上第一幅图的宽度
	line(matches_img, dst_corners[0] + Point2f(src1.cols,0), dst_corners[1] + Point2f(src1.cols,0),Scalar(0,0,255), 2);
	line(matches_img, dst_corners[1] + Point2f(src1.cols,0), dst_corners[2] + Point2f(src1.cols,0), Scalar(0, 0, 255), 2);
	line(matches_img, dst_corners[2] + Point2f(src1.cols,0), dst_corners[3] + Point2f(src1.cols,0), Scalar(0, 0, 255), 2);
	line(matches_img, dst_corners[3] + Point2f(src1.cols,0), dst_corners[0] + Point2f(src1.cols,0), Scalar(0, 0, 255), 2);
	imshow("output1", matches_img);
	//在原图上画出目标
	cvtColor(src2, src2, CV_GRAY2BGR);
	line(src2, dst_corners[0] , dst_corners[1], Scalar(0, 0, 255), 2);
	line(src2, dst_corners[1] , dst_corners[2], Scalar(0, 0, 255), 2);
	line(src2, dst_corners[2] , dst_corners[3], Scalar(0, 0, 255), 2);
	line(src2, dst_corners[3] , dst_corners[0], Scalar(0, 0, 255), 2);
	imshow("output2", src2);
	waitKey(0);
	return 0;
}

 

 

猜你喜欢

转载自blog.csdn.net/qq_24946843/article/details/82697719