SIFT特征检测与RANSAC过滤

本文介绍了一种使用SIFT特征检测与匹配的方法,并通过RANSAC算法过滤错误匹配点,提高匹配精度。文章详细展示了SIFT特征提取、描述子计算及匹配过程,并实现了RANSAC算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/*
 *@function SiftDetect.cpp
 *@brief 对sift特征检测和匹配进行测试,并实现RANSAC算法进行过滤错配点
 *@author ltc
 *@date 11:20 Saturday,28 November,2015
 */
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\nonfree\nonfree.hpp>
using namespace std;
using namespace cv;


//RANSAC算法
vector<DMatch> ransac(vector<DMatch> matches,vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint);

int main(int argc,char* argv[])
{
	//图像读取
	Mat img1,img2;
	img1=imread("1 (2).jpg",CV_WINDOW_AUTOSIZE);
	img2=imread("2 (2).jpg",CV_WINDOW_AUTOSIZE);

	if(img1.empty()||img2.empty())
	{
		return -1;
	}

	//sift特征提取
	SiftFeatureDetector detector;	
	vector<KeyPoint> keyPoint1,keyPoint2;
	detector.detect(img1,keyPoint1);
	detector.detect(img2,keyPoint2);
	//cout<<"Number of KeyPoint1:"<<keyPoint1.size()<<endl;
	//cout<<"Number of KeyPoint2:"<<keyPoint2.size()<<endl;

	//sift特征描述子计算
	SiftDescriptorExtractor desExtractor;
	Mat des1,des2;
	desExtractor.compute(img1,keyPoint1,des1);
	desExtractor.compute(img2,keyPoint2,des2);

	//sift特征点(描述子)匹配
	Mat res1,res2;
//	drawKeypoints(img1,keyPoint1,res1,Scalar::all(-1),/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT);
//	drawKeypoints(img2,keyPoint2,res2,Scalar::all(-1),/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT);
	BFMatcher matcher(NORM_L2);
	FlannBasedMatcher matcher_flann;
	vector<DMatch> matches;

	vector<vector<DMatch>> matches_knn;
	matcher.match(des1,des2,matches);
	matcher.knnMatch(des1,des2,matches_knn,2);

//	cout<<"matches_knn.size:"<<matches_knn.size()<<endl;

	//sift特征最近距离与次近距离之比小于0.6视为正确匹配
	vector<DMatch> match_knn;
	for(int i=0;i<matches_knn.size();i++)
	{
		float ratio=matches_knn[i][0].distance/matches_knn[i][1].distance;
		if(ratio<0.6)
		{
			match_knn.push_back(matches_knn[i][0]);
		}
	}

//	matcher_flann.match(des1,des2,matches_flann);

	//for(int i=0;i<matches.size();i++)
	//{
	//	cout<<"第"<<i<<"对匹配:"<<endl;
	//	cout<<"queryIdx:"<<matches[i].queryIdx<<"\ttrainIdx:"<<matches[i].trainIdx<<endl;
	//	cout<<"imgIdx:"<<matches[i].imgIdx<<"\tdistance:"<<matches[i].distance<<endl;
	//}

	//cout<<"Number of matches:"<<matches.size()<<endl;
	//cout<<"Number of matches_flann:"<<matches_flann.size()<<endl;
	
	vector<DMatch> matches_ransac=ransac(matches,keyPoint1,keyPoint2);
	Mat img_match,img_match_flann;
	
	drawMatches(img1,keyPoint1,img2,keyPoint2,matches_ransac,img_match);
	drawMatches(img1,keyPoint1,img2,keyPoint2,match_knn,img_match_flann);

	imshow("img_match",img_match);
	imshow("img_match_flann",img_match_flann);
	
	//for(size_t i=0;i<keyPoint1.size();i++)
	//{
	//	//cout<<"x:"<<kp1.at(i).pt.x<<endl;
	//	circle(img1,Point((int)(keyPoint1.at(i).pt.x),(int)(keyPoint1.at(i).pt.y)),3,Scalar(255,0,0),2,8,0);
	//}

	//imshow("img1",img1);
	//imshow("img1_",res1);
//	imshow("img2",res2);
	ransac(matches,keyPoint1,keyPoint2);
	waitKey(0);

	return 0;
}
//RANSAC算法实现
vector<DMatch> ransac(vector<DMatch> matches,vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint)
{
	//定义保存匹配点对坐标
	vector<Point2f> srcPoints(matches.size()),dstPoints(matches.size());
	//保存从关键点中提取到的匹配点对的坐标
	for(int i=0;i<matches.size();i++)
	{
		srcPoints[i]=queryKeyPoint[matches[i].queryIdx].pt;
		dstPoints[i]=trainKeyPoint[matches[i].trainIdx].pt;
	}
	//保存计算的单应性矩阵
	Mat homography;
	//保存点对是否保留的标志
	vector<unsigned char> inliersMask(srcPoints.size()); 
	//匹配点对进行RANSAC过滤
	homography = findHomography(srcPoints,dstPoints,CV_RANSAC,5,inliersMask);
	//RANSAC过滤后的点对匹配信息
	vector<DMatch> matches_ransac;
	//手动的保留RANSAC过滤后的匹配点对
	for(int i=0;i<inliersMask.size();i++)
	{
		//cout<<inliersMask[i]<<endl;
		cout<<(int)(inliersMask[i])<<endl;
		if(inliersMask[i])
		{
			matches_ransac.push_back(matches[i]);
			//cout<<"第"<<i<<"对匹配:"<<endl;
			//cout<<"queryIdx:"<<matches[i].queryIdx<<"\ttrainIdx:"<<matches[i].trainIdx<<endl;
			//cout<<"imgIdx:"<<matches[i].imgIdx<<"\tdistance:"<<matches[i].distance<<endl;
		}
	}
	//返回RANSAC过滤后的点对匹配信息
	return matches_ransac;
}


SIFT原理:http://blog.youkuaiyun.com/quincuntial/article/details/50460975


匹配结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值