Episode Four:SIFT算法应用1

SIFT(Scale-Invariant Feature Transform):尺度不变特征变换算法,作者David Lowe。

用于图像处理领域的一种描述,描述具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子。SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。且对于光线、噪声和微视角的改变的容忍度也相当高。基于这些特性,他们是高度显著而且相对容易撷取,且在数目庞大的特征数据库中,很容易辨识物体且很少有误认。

SIFT算法有一些特点:

1. SIFT特征是图像的局部特征,其对旋转、尺度缩放、高亮变化保持不变性,对视角变化,放射变化,噪声也保持一定程度的稳定性。

2. 独特性好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配。

3. 多量性,即使少数的几个物体也可以产生大量的SIFT特征向量。

4. 高速性,经优化的SIFT匹配算法甚至可以达到实时的要求。

5. 可扩展性,可以很方便的与其他形式的特征向量进行联合。


算法一、SIFT特征检测:

step1:尺度空间极值检测;搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。

step2:关键点定位;在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据它们的稳定程度。

step3:方向确定;基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。

step4:关键点描述;在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。


算法二、SIFT特征匹配:

阶段一:SIFT特征的生成,即从多幅图像中提取对尺度缩放、旋转、亮度变化无关的特征向量。

阶段二:SIFT特征向量的匹配。

step1:构建尺度空间,检测极值点,获得尺度不变性;

step2:特征点过滤并进行精确定位;

step3:为特征点分配方向值;

step4:生成特征描述子。(4*4*8的128维特征描述子)



code:

///SIFT特征点匹配
#include "opencv2/opencv.hpp"
#include "opencv2/nonfree/nonfree.hpp"//SIFT相关
#include "opencv2/legacy/legacy.hpp"//匹配器相关
#include 
#include 

using namespace std;
using namespace cv;

int main()
{
	//1.SIFT特征点提取——detect()方法  
	Mat srcImg1 = imread("a.jpg", CV_LOAD_IMAGE_COLOR);
	Mat srcImg2 = imread("b.jpg", CV_LOAD_IMAGE_COLOR);
	Mat dstImg1, dstImg2;
	SiftFeatureDetector siftDetector;//SiftFeatureDetector是SIFT类的别名    
	vector keyPoints1;
	vector keyPoints2;
	siftDetector.detect(srcImg1, keyPoints1);
	siftDetector.detect(srcImg2, keyPoints2);
	drawKeypoints(srcImg1, keyPoints1, dstImg1);
	drawKeypoints(srcImg2, keyPoints2, dstImg2);
	imshow("dstImg1", dstImg1);
	imshow("dstImg2", dstImg2);
	//2.特征点描述符(特征向量)提取——compute()方法  
	SiftDescriptorExtractor descriptor;//SiftDescriptorExtractor是SIFT类的别名    
	Mat description1;
	Mat description2;
	descriptor.compute(srcImg1, keyPoints1, description1);//注意原图和特征点要对应,不要写错  
	descriptor.compute(srcImg2, keyPoints2, description2);
	imshow("description1", description1);
	imshow("description2", description2);
	//3.使用暴力匹配器进行暴力匹配——BruteForceMatcher类的match()方法  
	BruteForceMatcher> matcher;//实例化暴力匹配器  
	vector matches; //定义匹配结果变量  
	matcher.match(description1, description2, matches);//实现描述符之间的匹配  
	//4.对匹配结果进行筛选(依据DMatch结构体中的float类型变量distance进行筛选)  
	float minDistance = 100;
	float maxDistance = 0;
	for (int i = 0; i < matches.size(); i++)
	{
		if (matches[i].distance < minDistance)
			minDistance = matches[i].distance;
		if (matches[i].distance > maxDistance)
			maxDistance = matches[i].distance;
	}
	cout << "minDistance: " << minDistance << endl;
	cout << "maxDistance: " << maxDistance << endl;
	
	vector goodMatches;
	for (int i = 0; i < matches.size(); i++)
	{
		if (matches[i].distance < 2 * minDistance)
		{
			goodMatches.push_back(matches[i]);
		}
	}
	//5.绘制匹配结果——drawMatches()  
	Mat dstImg3;
	drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, goodMatches, dstImg3);
	namedWindow("dstImg3", WINDOW_NORMAL);//为防止图像太大,屏幕显示不下,采用可以手动拉伸的方法;或者可以采用提前把图片缩小的方法
	imshow("dstImg3", dstImg3);
	waitKey(0);
	return 0;
}

Smart is the new sexy!

你可能感兴趣的:(opencv)