opencv3.4.6 特征点匹配:SIFT、SURF

SIFT

Scale Invariant Feature Transform,尺度不变特征变换。SIFT特征对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征。

SIFT算法主要有以下几个步骤:

高斯差分金字塔的构建
使用组和层的结构构建了一个具有线性关系的金字塔(尺度空间),这样可以在连续的高斯核尺度上查找图像的特征点;另外,它使用一阶的高斯差分来近似高斯的拉普拉斯核,大大的减少了运算量。
尺度空间的极值检测及特征点的定位
搜索上一步建立的高斯尺度空间,通过高斯差分来识别潜在的对尺度和旋转不变的特征点。但是,在离散空间中,局部极值点可能并不是真正意义的极值点,真正的极值点有可能落在离散点的间隙中,SIFT通过尺度空间DoG函数进行曲线拟合寻找极值点。
特征方向赋值
基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性。
特征描述子的生成
通过上面的步骤已经找到的SIFT特征点的位置、方向、尺度信息,最后使用一组向量来描述特征点及其周围邻域像素的信息。
 

SURF

Speeded Up Robust Features。加速版的SIFT。SURF的流程和SIFT比较类似,这些改进体现在以下几个方面:

特征点检测是基于Hessian矩阵,依据Hessian矩阵行列式的极值来定位特征点的位置。并且将Hession特征计算与高斯平滑结合在一起,两个操作通过近似处理得到一个核模板。
在构建尺度空间时,使用box filter与源图像卷积,而不是使用DoG算子。
SURF使用一阶Haar小波在x、y两个方向的响应作为构建特征向量的分布信息。
 

头文件:

#include 

SIFT 和SURF属于xfeatures2d模块,在opencv的官网发布版中并没有,需要自编译 ,官网说明如下:

 定义:

typedef SIFT 	cv::xfeatures2d::SiftDescriptorExtractor
typedef SIFT 	cv::xfeatures2d::SiftFeatureDetector
typedef SURF 	cv::xfeatures2d::SurfDescriptorExtractor
typedef SURF 	cv::xfeatures2d::SurfFeatureDetector

由以下类的继承图可看看出:

SurfFeatureDetector类和SurfDescriptorExtractor类,其实就是SURF类,他们三者等价; 

同样地,SiftFeatureDetector类和SiftDescriptorExtractor类,其实就是SIFT类,他们三者等价; 

 opencv3.4.6 特征点匹配:SIFT、SURF_第1张图片

测试示例:

#include 
#include 
#include 

using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;

int main()
{
	Mat left_image = imread("..\\image\\left.jpg", 0);
	Mat right_image = imread("..\\image\\right.jpg", 0);

	//创建检测器
	//cv::Ptr detector = SiftFeatureDetector::create();//sift
	cv::Ptr detector = SurfFeatureDetector::create(100);//surf

	//提取特征点、计算描述子
	vector key_points_1, key_points_2;
	cv::Mat dstImage1, dstImage2;
	detector->detectAndCompute(left_image, Mat(), key_points_1, dstImage1);
	detector->detectAndCompute(right_image, Mat(), key_points_2, dstImage2);

	//绘制特征点
	Mat img_keypoints_1, img_keypoints_2;
	drawKeypoints(left_image, key_points_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
	drawKeypoints(right_image, key_points_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT);

	//匹配
	cv::Ptr matcher = cv::DescriptorMatcher::create("FlannBased");
	vector mach;
	matcher->match(dstImage1, dstImage2, mach);

	//计算匹配距离筛选阈值
	double Max_dist = 0;
	double Min_dist = 100;

	for (int i = 0; i Max_dist)Max_dist = dist;
	}
	std::cout << "最短距离" << Min_dist << std::endl;
	std::cout << "最长距离" << Max_dist << std::endl;
	
	//筛选匹配点
	vectorgoodmaches;
	for (int i = 0; i < dstImage1.rows; i++)
	{
		if (mach[i].distance < 2.0 * Min_dist)
		{
			goodmaches.push_back(mach[i]);
		}
	}
	
	// 画出匹配图
	Mat imageMatches;
	drawMatches(left_image, key_points_1, right_image, key_points_2, goodmaches,
		imageMatches, Scalar(0, 0, 255));

	return 0;
}

 

你可能感兴趣的:(图像配准)