opencv3.1.0 特征点检测与图像匹配(features2d、xfeatures2d)

特征检测与匹配,在物体检测,视觉跟踪,三维重建等领域都有广泛的应用。所以学习features2d、xfeatures2d中函数的使用,很有必要。

1、得到特征点与特征点描述(SIFT SURF ORB  AKAZE)

(1)SIFT

#include 
vector key_points;
Mat descriptor;
Ptr sift = xfeatures2d::SIFT::create(0, 3, 0.04, 10);
sift->detectAndCompute(image, noArray(), key_points, descriptor);

(2)SURF(可以认为是尺度不变特征变换sift的加速版)

#include 
Ptr surf = xfeatures2d::SURF::create();
surf->detectAndCompute(image, noArray(), key_points, descriptor);

(3)ORB(实际来看,速度很快,但效果并不一定好)

#include 
Ptr orb = ORB::create(5000);
orb->detectAndCompute(image, noArray(), key_points, descriptor);


(4)AKAZE(与ORB在同一个hpp中)

#include 
Ptr akaze = AKAZE::create();
akaze->detectAndCompute(image, noArray(), key_points, descriptor);

2、特征点匹配的几种方法

(1)与ORB结合使用,效果较好

void match_features_knn(Mat& query, Mat& train, vector& matches)
{
	flann::Index flannIndex(query,flann::LshIndexParams(12,20,2),cvflann::FLANN_DIST_HAMMING);
	Mat matchindex(train.rows,2,CV_32SC1);
	Mat matchdistance(train.rows, 2, CV_32FC1);
	flannIndex.knnSearch(train, matchindex, matchdistance,2,flann::SearchParams());
	//根据劳氏算法
	for (int i = 0; i < matchdistance.rows; i++)
	{
		if (matchdistance.at(i, 0) < 0.6*matchdistance.at(i, 1))
		{
			DMatch dmatches(matchindex.at(i, 0),i, matchdistance.at(i, 0));
			matches.push_back(dmatches);
		}
	}
}

(2)个人感觉这种方法,效果与暴力匹配法没啥区别,但是被注释掉的方法,效果不好

void match_features_FLANN(Mat& query, Mat& train, vector& matches)
{
	FlannBasedMatcher matcher;
	
	/*vector match;
	matcher.match(query, train, match);
	double max_dist = 0;
	double min_dist = 100;
	for (int i = 0; i < match.size(); i++)
	{
		double dist = match[i].distance;
		if (dist < min_dist) min_dist = dist;
		if (dist > max_dist) max_dist = dist;
	}
	for (int i = 0; i < match.size(); i++)
	{
		if (match[i].distance < 2 * min_dist) matches.push_back(match[i]);
	}*/

	vector> knn_matches;
	matcher.knnMatch(query, train, knn_matches, 2);

	//获取满足Ratio Test的最小匹配的距离
	float min_dist = FLT_MAX;
	for (int r = 0; r < knn_matches.size(); ++r)
	{
		//Ratio Test
		if (knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance)
			continue;

		float dist = knn_matches[r][0].distance;
		if (dist < min_dist) min_dist = dist;
	}

	matches.clear();
	for (size_t r = 0; r < knn_matches.size(); ++r)
	{
		//排除不满足Ratio Test的点和匹配距离过大的点
		if (
			knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance ||
			knn_matches[r][0].distance > 5 * max(min_dist, 10.0f)
			)
			continue;

		//保存匹配点
		matches.push_back(knn_matches[r][0]);
	}

}

(3)也叫暴力匹配法,此种方法结合sift、surf用的比较多

void match_features(Mat& query, Mat& train, vector& matches)
{
	vector> knn_matches;
	BFMatcher matcher(NORM_L2);

	matcher.knnMatch(query, train, knn_matches, 2);

	//获取满足Ratio Test的最小匹配的距离
	float min_dist = FLT_MAX;
	for (int r = 0; r < knn_matches.size(); ++r)
	{
		//Ratio Test
		if (knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance)
			continue;

		float dist = knn_matches[r][0].distance;
		if (dist < min_dist) min_dist = dist;
	}

	matches.clear();
	for (size_t r = 0; r < knn_matches.size(); ++r)
	{
		//排除不满足Ratio Test的点和匹配距离过大的点
		if (
			knn_matches[r][0].distance > 0.6*knn_matches[r][1].distance ||
			knn_matches[r][0].distance > 5 * max(min_dist, 10.0f)
			)
			continue;

		//保存匹配点
		matches.push_back(knn_matches[r][0]);
	}
}
看下面的效果图,会发现大部分点都是匹配正确的。但是,依然有少部分点匹配的明显不正确。

opencv3.1.0 特征点检测与图像匹配(features2d、xfeatures2d)_第1张图片

3、进一步匹配(寻找源图与目标图像之间的透视变换)

bool refineMatchesWithHomography(const std::vector& queryKeypoints,const std::vector& trainKeypoints,
float reprojectionThreshold,std::vector& matches,cv::Mat& homography)
{
	const int minNumberMatchesAllowed = 8;
	if (matches.size() < minNumberMatchesAllowed)
		return false;
	// Prepare data for cv::findHomography  
	std::vector srcPoints(matches.size());
	std::vector dstPoints(matches.size());
	for (size_t i = 0; i < matches.size(); i++)
	{
		srcPoints[i] = trainKeypoints[matches[i].trainIdx].pt;
		dstPoints[i] = queryKeypoints[matches[i].queryIdx].pt;
		//srcPoints[i] = trainKeypoints[i].pt;
		//dstPoints[i] = queryKeypoints[i].pt;
	}
	// Find homography matrix and get inliers mask  
	std::vector inliersMask(srcPoints.size());
	homography = cv::findHomography(srcPoints,dstPoints,CV_FM_RANSAC,reprojectionThreshold,inliersMask);
	std::vector inliers;
	for (size_t i = 0; i minNumberMatchesAllowed;
}

效果如下所示(没有发现匹配不对的点)

opencv3.1.0 特征点检测与图像匹配(features2d、xfeatures2d)_第2张图片







你可能感兴趣的:(opencv)