opencv笔记(11):SIFT特征

特征提取之SIFT特征

尺度不变特征变换(Scale-invariant feature transform,SIFT)是一种检测局部特征的算法,通过求一幅图中的特征点及其有关的scale和orientation的描述子得到特征并进行图像特征点匹配。

1.SIFT算法过程

(1)构建尺度空间
尺度空间理论目的是模拟图像数据的多尺度特征,为初始化操作。
可以通过构建图像金字塔来实现图像的多尺度表达,其中主要用高斯金字塔。为了有效的在尺度空间检测到稳定的关键点,提出了高斯差分尺度空间,利用不同尺度的高斯差分核与图像卷积生成。
其中,(x,y)是空间坐标,σ大小决定图像的平滑程度,大尺度对应图像的概貌特征(低分辨率),小尺度对应图像的细节特征(高分辨率)。如下图为高斯差分金字塔的形成,通过高斯金字塔每组中相邻上下两层图像相减得到。

(2)空间极值点检测
关键点是由DOG(高斯差分)空间的局部极值点组成的,为了找到尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看是否比其他的图像域和尺度域大或者小。如图,中间的检测点要与它同尺度的8个相邻点和上下相邻尺度对应的9*2=18个点相比较,共8+18=26个点。若该点是最大或者最小的点时,则为图像在该尺度下的一个特征点。
在极值的比较过程中,每组图像的首末两层是无法进行极值比较的,需要在每组图像的顶层继续用高斯模糊生成三幅图像图像,因为DOG金字塔需要S+2层图像,而DOG是通过高斯金字塔相邻两层相减得到的,所以需要S+3层图像。

(3)关键点定位
通过拟合三维二次函数来确定关键点的位置和尺度,同时去除低对比度的关键点和不稳定的边缘响应点。
利用DOG函数在尺度空间的泰勒展开式为:
,其中
求导让方程为0,可以得到极值点的偏移量为:
将极值点代入方程:
,其中 代表相对插值中心的的偏移量。若 ,则保存,否则丢弃。
去除不稳定的边缘响应点:一个定义不好的高斯差分算子的极值在横跨边缘的地方有较大的主曲率,而在垂直边缘的方向有较小的主曲率。获取特征点处的Hessian矩阵,主曲率通过一个2*2的Hessian矩阵H求出:
D的主曲率和H的特征值成正比,令α为较大特征值,β为较小的特征值
令α=γβ,则
(r + 1)^2/r的值在两个特征值相等的时候最小,随着r的增大而增大,因此,为了检测主曲率是否在某域值r下,只需检测
满足保留,否则丢弃,Lowe的文章中,r取10。

(4)关键点方向匹配
利用关键点领域像素的梯度方向分布特性为每一个关键点指定方向参数,这样使得算子具有旋转不变性。对于检测出来的关键点:
其中,m(x,y)和θ(x,y)为(x,y)处梯度的模值和方向公式,L为关键点所在的尺度空间值。
使用梯度直方图统计领域内像素的梯度和方向。梯度直方图的范围是0~360度,其中每10度为一个柱,共有36个柱(bins)。如下图直方图的峰值方向代表了关键点的方向。其中主方向代表了该特征点处领域梯度的方向,以直方图中最大值作为该关键点的主方向,而其他大于主方向80%的峰值方向作为辅助方向。
到此为止,检测出来含有位置、尺度和方向的关键点即为该图像是SIFT特征点。

(5)关键点特征描述
SIFT描述子是关键点领域高斯图像梯度统计结果的一种表示,通过对关键点周围区域分块,计算块内梯度直方图,生成具有独特性的向量。使用关键点尺度空间内4*4的窗口中计算的8个方向的梯度信息,共4*4*8=128维向量特征。
  • 将坐标轴旋转为关键点方向,确保旋转不变性。
  • 在高斯图像上以关键点为中心取8*8的窗口,求得窗口内所有像素的梯度和方向。
  • 用高斯窗口对其进行加权运算,图中蓝色圈代表了高斯加权的范围。
  • 在每4*4的小块上计算8个方向的梯度方向直方图,绘制每个梯度方向的累加值,得到4个种子点。

  • 计算4个种子点周围16*16窗口中的每一个像素的梯度,使用高斯下降函数降低远离中心的权重。
  • 在每个4*4的1/16象限中,通过加权梯度值加到直方图8个方向区间中的一个,计算出一个梯度方向直方图。
  • 通过设置门限值(一般取0.2)截断较大的梯度值,进行归一化处理,去除了光照等的影响。
  • 按特征点的尺度对特征描述向量进行排序

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

using namespace std;
using namespace cv;

int main(){
	Mat dst;
	Mat image = imread("D:/img/1.jpg");	//输入图像
	namedWindow("src");
	imshow("src", image);

	vector<KeyPoint>Keypoints;		//特征点向量
	//构造SIFT检测器(0.03为特征的阈值,用于去除低对比度的关键点;10用于降低直线敏感度,去除不稳定点的边缘响应点)
	SiftFeatureDetector sift(0.03, 10);
	sift.detect(image, Keypoints);	//检测SIFT特征值

	//画出特征点的大小和方向
	drawKeypoints(image, Keypoints, dst, Scalar(255, 255, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	namedWindow("dst");
	imshow("dst", dst);

	waitKey(0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值