1. 程式人生 > >Surf特徵點檢測與匹配

Surf特徵點檢測與匹配

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\nonfree\features2d.hpp>
#include <opencv2\nonfree\nonfree.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <iostream>

using namespace std;
using namespace cv;

vector<DMatch> ransac(vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint,vector<DMatch> matches);


int main(int argc,char* argv[])
{
	//定義影象
	Mat queryImage,trainImage;
	
	//讀取影象
	queryImage = imread("3.jpg",IMREAD_COLOR);
	trainImage = imread("4.jpg",IMREAD_COLOR);
	//判斷是否讀取影象
	if(queryImage.empty() || trainImage.empty())
	{
		cerr<<"Failure in loading image"<<endl;
		return -1;
	}

	//定義Surf特徵檢測器
	SurfFeatureDetector surfDetector;

	//定義特徵點
	vector<KeyPoint> queryKeyPoint,trainKeyPoint;

	//檢測surf特徵
	surfDetector.detect(queryImage,queryKeyPoint);
	surfDetector.detect(trainImage,trainKeyPoint);

	//檢視檢測到的特徵點的數目
	cout<<"Number of queryKeyPoint:"<<queryKeyPoint.size()<<endl;
	cout<<"Number of trainKeyPoint:"<<trainKeyPoint.size()<<endl;

	//定義繪製surf特徵點的影象
	Mat queryImageKeyPoint,trainImageKeyPoint;

	//繪製surf特徵點
	drawKeypoints(queryImage,queryKeyPoint,queryImageKeyPoint,Scalar(0,0,255),
		/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT);
	drawKeypoints(trainImage,trainKeyPoint,trainImageKeyPoint,Scalar(0,0,255),
		/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT);

	//定義顯示視窗,可不要
	namedWindow("queryImageKeyPoint",CV_WINDOW_AUTOSIZE);
	namedWindow("trainImageKeyPoint",CV_WINDOW_AUTOSIZE);

	//顯示surf特徵點
	imshow("queryImageKeyPoint",queryImageKeyPoint);
	imshow("trainImageKeyPoint",trainImageKeyPoint);

	//定義surf特徵描述子
	Mat queryDescriptor,trainDescriptor;

	//定義Surf特徵描述子提取器
	SurfDescriptorExtractor surfExtractor;

	//提取特徵描述子
	surfExtractor.compute(queryImage,queryKeyPoint,queryDescriptor);
	surfExtractor.compute(trainImage,trainKeyPoint,trainDescriptor);
	
	//定義描述子匹配對
	vector<DMatch> bfMatches;
	vector<DMatch> flannMatches;

	//Brute Match,窮舉法求最近鄰
	BFMatcher bfMatcher;
	bfMatcher.match(queryDescriptor,trainDescriptor,bfMatches);

	//FlannBasedMatcher,最近鄰近似匹配
	FlannBasedMatcher flannMatcher;
	flannMatcher.match(queryDescriptor,trainDescriptor,flannMatches);


	//對匹配點進行RANSAC過濾
	vector<DMatch> ransac_BFMatches,ransac_FlannMatches;

	ransac_BFMatches=ransac(queryKeyPoint,trainKeyPoint,bfMatches);
	ransac_FlannMatches=ransac(queryKeyPoint,trainKeyPoint,flannMatches);

	//定義匹配影象
	Mat bfMatchImage,flannMatchImage;

	//繪製匹配影象
	//drawMatches(queryImage,queryKeyPoint,trainImage,trainKeyPoint,bfMatches,bfMatchImage);
	//drawMatches(queryImage,queryKeyPoint,trainImage,trainKeyPoint,flannMatches,flannMatchImage);
	drawMatches(queryImage,queryKeyPoint,trainImage,trainKeyPoint,ransac_BFMatches,bfMatchImage);
	drawMatches(queryImage,queryKeyPoint,trainImage,trainKeyPoint,ransac_FlannMatches,flannMatchImage);
	
	//顯示匹配結果
	imshow("BFMatch",bfMatchImage);
	imshow("FlannMatch",flannMatchImage);


	waitKey(0);
	return 0;
}

vector<DMatch> ransac(vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint,vector<DMatch> matches)
{
	cout<<"ransac前:"<<matches.size()<<endl;
	vector<Point2f> queryPoints(matches.size()),trainPoints(matches.size());
	for(int i=0;i<matches.size();i++)
	{
		queryPoints[i] = queryKeyPoint[matches[i].queryIdx].pt; 
		trainPoints[i] = trainKeyPoint[matches[i].trainIdx].pt; 
	}

	Mat H;
	vector<unsigned char> inlierMask(matches.size());
	vector<DMatch> ransac_matches;
	H = findHomography(queryPoints,trainPoints,CV_RANSAC,3,inlierMask);

	for(int i=0;i<inlierMask.size();i++)
	{
		if(inlierMask[i])
		{
			ransac_matches.push_back(matches[i]);
		}
	}
	cout<<"ransac後:"<<ransac_matches.size()<<endl;
	return ransac_matches;
}

匹配結果: