opencv图像处理学习(四十六)——sift特征

计算机视觉理论中的特征描述是常见的目标分析技术之一,关键点检测与关键点提取是目标特征分析的重要步骤。局部图像特征描述的核心基础问题是不变性和可分性分析,不变性是基于特征描述对视角变化的不变性、尺度变化的不变性及旋转变化的不变性等,可分性是基于局部图像内容的可区分性。在实际应用场景中,不变性与可分性是相互依存且矛盾的。Opnecv中常见的特征描述子有多种,如SIFT、SURF及ORB特征描述子。

1.SIFT特征步骤

SIFT都目前应用最广泛的关键点检测和描述算法,SIFT特征提取充分利用了图像局部信息,SIFT特征包含以下优点:(1)SIFT特征具有旋转、尺度、平移、视角及亮度不变性,有利于对目标特征信息进行有效表达。(2)SIFT特征对参数调整鲁棒性好,在进行特征描述时,根据场景需要可调整适宜调整特征点数量,以便进行特征分析。

SIFT特征算法对图像局部特征点的提取主要包括4个步骤:疑似关键点检测、去除伪关键点、关键点梯度与方向匹配及特征向量生成。

步骤1——疑似关键点检测

关键点在某些情况下是图像中的角点,然而由于SIFT特征需要关键点包含尺度及方向,因此需要建立相应的图像尺度空间,高斯函数是唯一可以产生尺度空间的核因子。对于图像f(x,y),利用其与高斯函数卷积可实现多尺度操作,尺度空间中下采样2次对于方差增加4倍,图像的尺度空间D(x,y,\sigma)满足下式子:

其中参数\simga为方差因子,这里也称尺度因子,其大小决定图像曲线平滑变化情况,较大值对应于图像的外轮廓特征,较小值对应于图像的细节特征。在计算图像特征中的关键点时,对于连续图像通常是利用高斯差分(DoG)算子进行计算,根据不同尺度下高斯差分核来进行关键点检测:D(x,y,k,\sigma)=L(x,y,k\sigma)-L(x,y,\sigma)。对图像应用拉普拉斯下的高斯差分进行操作,整个过程产生的最大和最小输出响应比传统对图像进行梯度检测更加稳定。

步骤2——去除伪关键点

上一步骤得到的疑似关键点在大部分场景中并不能直接进行特征描述,高斯差分算子对边缘及噪声相对敏感,会产生伪边缘信息和伪极值响应信息。为了去除上述原因造成的伪关键点,需要分析高斯差分算子的特性。该算子函数最主要的特性是水平边缘方向存在较大主曲率,而相对侧方向和垂直方向确存在较小曲率,利用该特性来计算特征点曲率。主曲率计算可以利用2维Hessian矩阵得到:

其中水平和垂直方向的倒数可以由相邻采样点的差分得到,特征点高斯差分算子函数的主曲率于H矩阵特征值成正比,我们并不需要计算H矩阵中每个特征值的大小,而是通过数学运算找到其比例关系。

在此考虑H矩阵的trace与det的比,则可以得到下式:

当检测到主曲率对应的M满足阈值T时,即M满足条件表达式M<(T+1)^2/T时,对应特征点判定为边缘点。

步骤3——关键点梯度及方向分配

通过步骤2实现图像尺度不变特征提取,要实现特征选择不变性,我们需要对特征点方向进行重分配。图像中的特征点梯度和方向计算如下式所示:

步骤4——特征向量生成

特征描述通常是把图像中所描述的关键点性质特征生成向量的过程,在特征描述过程中为了消除非线性光照或环境的影响,特征向量需要进行归一化操作。非线性光照对梯度的幅度值影响较大,对梯度方向的影响较小,因此需要先对梯度幅值阈值化操作,然后再进行特征向量归一化操作,经过归一化操作后得到的特征向量可直接用于特征分析、匹配及训练等。

检测思路是将源图像与待匹配图像转换为灰度图像并归一化处理:接着定义SIFT描述子,分别计算两幅图像的特征点向量;然后利用BruteForceMatcher进行两幅图像的关键点匹配,对匹配结果的向量进行二分排序,根据排序结果筛选特征向量,最后去除特征点不匹配情况,输出最终特征点检测及匹配情况。

2.相关函数

(1)DescriptExtractor类成员函数:

void compute(const Mat &image,vector<KetPoint> &keypointm,Mat &descriptors) const;//计算单个图像的关键点描述子

void compute(const vector<Mat> &image,vector<KetPoint> &keypointm,Mat &descriptors) const;//计算单个图像的关键点描述子

virtual void read(const FileNode &);//读取文件中特征描述的子对象

virtual void write(const FileStorage &);//写文件中特征描述的子对象

virtual int descriptorSize() const = 0;//获取描述子尺寸

virtual int descriptoType() const = 0;//获取描述子类型

static Ptr<DescrptorExtracot> creat(const string &descriptorExtracotType);//创建特征描述子对象

而SiftDescriptExtractor类是从DescriptExtractor类公有继承过来的。

3.Demo

首先明确一点,opencv2与opencv3中,SIFT的使用方法有所不同,前者会创建实例化对象,而后者则是使用opencv智能指针:cv::Ptr,创建指针类型变量。

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\xfeatures2d\nonfree.hpp>
#include <opencv2\imgproc\imgproc.hpp>


cv::Mat SIFTFeatureAndCompare(cv::Mat InputImage1, cv::Mat InputImage2)
{
	cv::Mat grayMat1, grayMat2;
	cv::cvtColor(InputImage1, grayMat1, CV_BGR2GRAY);
	cv::normalize(grayMat1, grayMat1, 0, 255,cv::NORM_MINMAX);
	cv::cvtColor(InputImage2, grayMat2, CV_BGR2GRAY);
	cv::normalize(grayMat2, grayMat2, 0, 255, cv::NORM_MINMAX);

	cv::Ptr<cv::Feature2D> f2d = cv::xfeatures2d::SIFT::create();

	std::vector<cv::KeyPoint> keypoint1, keypoint2;
	f2d->detect(grayMat1, keypoint1);
	f2d->detect(grayMat2, keypoint2);

	cv::Mat descriptors1, descriptors2;
	f2d->compute(InputImage1, keypoint1, descriptors1);
	f2d->compute(InputImage2, keypoint2, descriptors2);

	cv::BFMatcher matcher;
	std::vector<cv::DMatch> matches;
	matcher.match(descriptors1, descriptors2, matches);

	cv::Mat Match;
	cv::drawMatches(InputImage1,keypoint1,InputImage2,keypoint2,matches, Match);
	return Match;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值