SIFT(Scale-Invariant Feature Transform)是什么?

先下结论:SIFT是图像特征一种。可以用来代表该图像,和别的图像进行对比或别的操作。

图像特征具体该怎么理解呢?除了SIFT还有什么别的图像特征,它们之间有什么关联吗?

1.OpenCV-Python Tutorial中对图像特征的解释

       我相信你们大多数人都玩过拼图游戏吧。首先你们拿到一张图片的一堆碎片,要做的就是把这些碎片以正确的方式排列起来从而重建这幅图像。我们想让计算机也学会玩拼图,那首先考虑一下我们是如何把一堆碎片拼在一起的?答案就是:我们要寻找一些唯一的特征,这些特征要适于被跟踪,容易被比较。如果我们深入的观察一些图像并搜索不同的pattern,我们会发现一些有趣的事。以下图为例:


在图像的上方给出了六个小图。你要做的就是找到这些小图在原始图像中的位置。你能找到多少正确结果呢?
A 和B 是平面,而且它们的图像中很多地方都存在。很难找到这些小图的准确位置。C 和D 更简单。它们是建筑的边缘。你可以找到它们的近似位置,但是准确位置还是很难找到。这是因为:沿着边缘,所有的地方都一样。所以边缘是比平面更好的特征,但是还不够好(在拼图游戏中要找连续的边缘)。最后E 和F 是建筑的一些角点。它们能很容易的被找到。因为在角点的地
方,无论你向哪个方向移动小图,结果都会有很大的不同。所以可以把它们当成一个好的特征。为了更好的理解这个概念我们举个更简单的例子。

如上图所示,蓝色框中的区域是一个平面很难被找到和跟踪。无论你向那个方向移动蓝色框,长的都一样。对于黑色框中的区域,它是一个边缘。如果你沿垂直方向移动,它会改变。但是如果沿水平方向移动就不会改变。而红色框中的角点无论你向哪个方向移动,得到的结果都不同,这说明它是唯一的。所以,基本上来说角点是一个好的图像特征。如果我们找到了图像特征(假设你已经搞定)。在找到这些之后,你应该在其他图像中也找到同样的特征。我们应该怎么做呢?我们选择特征周围的一个区域,然后用我们自己的语言来描述它,比如“上边是蓝天,下边是建筑,在建筑上有很多玻璃等”,你就可以在其他图片中搜索相同的区域了。基本上看来,你是在描述特征。同样,计算机也要对特征周围的区域进行描述,这样它才能在其他图像中找到相同的特征。我们把这种描述称为特征描述。当你有了特征很它们的描述后,你就可以在所有的图像中找这个相同的特征了,找到之后你就可以做任何你想做的了。

2.只有角点是不够的,所以有了SIFT

       角点具有旋转不变特性,即使图片发生了旋转,我们也能找到同样的角点。很明显即使图像发生旋转之后角点还是角点。那如果我们对图像进行缩放呢?角点可能就不再是角点了。以下图为例,在一副小图中使用一个小的窗口可以检测到一个角点,但是如果图像被放大,再使用同样的窗口就检测不到角点了。

所以在2004 年,D.Lowe 提出了一个新的算法:尺度不变特征变换(SIFT),这个算法可以帮助我们提取图像中的关键点并计算它们的描述符。这里的关键点可以简单理解为“角点plus”,是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。SIFT算法包括4个步骤:(1)尺度空间极值检测(2)关键点(极值点)定位(3)为关键点(极值点)指定方向参数(4)关键点描述符。之后我们就可以进行关键点匹配。

3.SIFT算法步骤(参考B站视频

3.1 尺度空间极值检测

(1)获取图片高斯金字塔

高斯金字塔是图片在不同尺寸下经过高斯模糊后得到的一组图片。如图所示,左边的黄格子图片,就是原图的二阶高斯金字塔,每一阶有5张图片,这5张图片是应用了不同大小的高斯核进行模糊得到的。

(2)求高斯金字塔的图片差分(差分就是求梯度),以求得极值。

关于这个极大值我们回忆一下,角点是怎么检测出来的。因为角点的特性就是在任意方向移动梯度变化就很大。所以我们就把某点向其他方向移动后梯度的变化记录下来,梯度变化的总和的极大值如果是比较大的话,我们就可以认为它是角点。

对于关键点也是一样。如图中所示,在一个octave中,每两张图片做差分,得到的新的图片就是梯度变化值。

 如上图是3张差分图片,假设X就是我们要找的潜在关键点,那么它的差分值应该是上下相邻26个像素中的极大值或者极小值。

举个例子:

input image经过4个不同的高斯函数模糊后得到4张图,再进行两两差分,得到一些边界信息和极值点信息。对这些点进行一个比较,找出keypoint。 

3.2 关键点定位

由于图像坐标是离散的,为了得到精确坐标,使用了一种曲面拟合的方法。利用插值,找到极值点真正的位置。

3.3  为关键点(极值点)指定方向参数

要找到极值点的主方向。计算关键点附近各个像素之间的梯度方向和梯度幅值,如上图中的绿色方格中的各个箭头。箭头方向就是梯度方向,箭头长度就是梯度幅值。然后再用一个圆圈窗口来统计窗口内各个方向的累计值,累计值最高的方向就可以作为该特征点的主方向。

3.4 关键点描述

如图所示,是两种不同的描述器。左图,把原来8*8的区域再划分成4个小区域,统计每个小区域内8个方向上的梯度大小。 最后构造出一个32维的描述器。右图则是128维的描述器。

 

 4.SIFT特征点展示:MATLAB示例

如图,图片中的keypoint标出了位置,圆圈比较大的话就代表是在尺度比较大的高斯金字塔图片上找到的该keypoint。

  上图中,圆圈内部黄色直线的方向就是该特征点的主方向。

上图是keypoint 描述器的信息,一共有128个特征。

5. Python中的SIFT特征提取

import cv2
import numpy as np
img = cv2.imread('home.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#【1】实例化sift对象
sift = cv2.SIFT()
#或者 
sift = cv2.xfeatures2d.SIFT_create() 

#【2】找出图像中的关键点
kp = sift.detect(gray,None)
#参数说明: kp表示生成的关键点,gray表示输入的灰度图

#【可视化】绘制代表关键点大小的圆圈甚至可以绘制除关键点的方向
img=cv2.drawKeypoints(gray,kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

#【3】计算关键点对应的sift特征向量/描述器
kp, dst = sift.compute(kp)
#参数说明:kp表示输入的关键点,dst表示输出的sift特征向量,通常是128维的

#【2/3】一步到位直接找到关键点并计算出其描述符
kp,dst = sift.detectAndCompute(gray)


cv2.imwrite('sift_keypoints.jpg',img)

参考

1.OpenCV-Python-Tutorial中文教程

2.机器学习进阶-图像特征sift-SIFT特征点

3.【算法漫谈】SIFT 尺度不变特征变换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值