引言:
在我写的关于 sift 算法的前倆篇文章里头,已经对 sift 算法有了初步的介绍:九、图像特征提取
与匹配之 SIFT 算法,而后在:九(续)、sift 算法的编译与实现里,我也简单记录下了如何利用 opencv,
gsl 等库编译运行 sift 程序。
但据一朋友表示,是否能用 c 语言实现 sift 算法,同时,尽量不用到 opencv,gsl 等第三方库之
类的东西。而且,Rob Hess 维护的 sift 库,也不好懂,有的人根本搞不懂是怎么一回事。
那么本文,就教你如何利用 c 语言一步一步实现 sift 算法,同时,你也就能真正明白 sift 算法到
底是怎么一回事了。
ok,先看一下,本程序最终运行的效果图,sift 算法分为五个步骤(下文详述),对应以下第二-
-第六幅图:
sift 算法的步骤
要实现一个算法,首先要完全理解这个算法的原理或思想。咱们先来简单了解下,什么叫 sift 算
法:
sift,尺度不变特征转换,是一种电脑视觉的算法用来侦测与描述影像中的局部性特征,它在空间
尺度中寻找极值点,并提取出其位置、尺度、旋转不变量,此算法由 David Lowe 在 1999 年所发表,200
4 年完善总结。
所谓,Sift 算法就是用不同尺度(标准差)的高斯函数对图像进行平滑,然后比较平滑后图像的
差别,
差别大的像素就是特征明显的点。
以下是 sift 算法的五个步骤:
一、建立图像尺度空间(或高斯金字塔),并检测极值点
首先建立尺度空间,要使得图像具有尺度空间不变形,就要建立尺度空间,sift 算法采用了高斯
函数来建立尺度空间,高斯函数公式为:
G(x,y,e) = [1/2*pi*e^2] * exp[ -(x^2 + y^2)/2e^2]
上述公式 G(x,y,e),即为尺度可变高斯函数。
而,一个图像的尺度空间 L(x,y,e) ,定义为原始图像 I(x,y)与上述的一个可变尺度的 2 维高斯函
数 G(x,y,e) 卷积运算。
即,原始影像 I(x,y)在不同的尺度 e 下,与高斯函数 G(x,y,e)进行卷积,得到 L(x,y,e),如下:
L(x,y,e) = G(x,y,e)*I(x,y)
以上的(x,y)是空间坐标, e,是尺度坐标,或尺度空间因子,e 的大小决定平滑程度,大尺度
对应图像的概貌特征,小尺度对应图像的细节特征。大的 e 值对应粗糙尺度(低分辨率),反之,对应精细
尺度(高分辨率)。
尺度,受 e 这个参数控制的表示。而不同的 L(x,y,e)就构成了尺度空间,具体计算的时候,即
使连续的高斯函数,都被离散为(一般为奇数大小)(2*k+1) *(2*k+1)矩阵,来和数字图像进行卷积运算。
随着 e 的变化,建立起不同的尺度空间,或称之为建立起图像的高斯金字塔。
但,像上述 L(x,y,e) = G(x,y,e)*I(x,y)的操作,在进行高斯卷积时,整个图像就要遍历所有的
像素进行卷积(边界点除外),于此,就造成了时间和空间上的很大浪费。
为了更有效的在尺度空间检测到稳定的关键点,也为了缩小时间和空间复杂度,对上述的操作作了
一个改建:即,提出了高斯差分尺度空间(DOG scale-space)。利用不同尺度的高斯差分与原始图像 I(x,
y)相乘 ,卷积生成。
D(x,y,e) = ((G(x,y,ke) - G(x,y,e)) * I(x,y)
DOG 算子计算简单,是尺度归一化的 LOG 算子的近似。
= L(x,y,ke) - L(x,y,e)
ok,耐心点,咱们再来总结一下上述内容:
1、高斯卷积
在组建一组尺度空间后,再组建下一组尺度空间,对上一组尺度空间的最后一幅图像进行二分之一
采样,得到下一组尺度空间的第一幅图像,然后进行像建立第一组尺度空间那样的操作,得到第二组尺度
空间,公式定义为
L(x,y,e) = G(x,y,e)*I(x,y)
图像金字塔的构建:图像金字塔共 O 组,每组有 S 层,下一组的图像由上一组图像降采样得到,效
果图,图 A 如下(左为上一组,右为下一组):
2、高斯差分
在尺度空间建立完毕后,为了能够找到稳定的关键点,采用高斯差分的方法来检测那些在局部位置
的极值点,即采用俩个相邻的尺度中的图像相减,即公式定义为:
D(x,y,e) = ((G(x,y,ke) - G(x,y,e)) * I(x,y)
= L(x,y,ke) - L(x,y,e)
效果图,图 B:
SIFT 的精妙之处在于采用图像金字塔的方法解决这一问题,我们可以把两幅图像想象成是连续的,
分别以它们作为底面作四棱锥,就像金字塔,那么每一个 截面与原图像相似,那么两个金字塔中必然会有
包含大小一致的物体的无穷个截面,但应用只能是离散的,所以我们只能构造有限层,层数越多当然越好,
但处理时 间会相应增加,层数太少不行,因为向下采样的截面中可能找不到尺寸大小一致的两个物体的图
像。
咱们再来具体阐述下构造 D(x,y,e)的详细步骤:
1、首先采用不同尺度因子的高斯核对图像进行卷积以得到图像的不同尺度空间,将这一组图像作
为金子塔图像的第一层。
2、接着对第一层图像中的 2 倍尺度图像(相对于该层第一幅图像的 2 倍尺度)以 2 倍像素距离进
行下采样来得到金子塔图像的第二层中的第一幅图像,对该图像采用不同尺度因子的高斯核进行卷积,以
获得金字塔图像中第二层的一组图像。
3、再以金字塔图像中第二层中的 2 倍尺度图像(相对于该层第一幅图像的 2 倍尺度)以 2 倍像素
距离进行下采样来得到金字塔图像的第三层中的第一幅图像,对该图像采用不同尺度因子的高斯核进行卷
积,以获得金字塔图像中第三层的一组图像。这样依次类推,从而获得了金字塔图像的每一层中的一组图
像,如下图所示:
4、对上图得到的每一层相邻的高斯图像相减,就得到了高斯差分图像,如下述第一幅图所示。下
述第二幅图中的右列显示了将每组中相邻图像相减所生成的高斯差分图像的结果,限于篇幅,图中只给出
了第一层和第二层高斯差分图像的计算(下述俩幅图统称为图 2):
5、因为高斯差分函数是归一化的高斯拉普拉斯函数的近似,所以可以从高斯差分金字塔分层结构
提取出图像中的极值点作为候选的特征点。对 DOG 尺度空间每个点与相邻尺度和相邻位置的点逐个进行比
较,得到的局部极值位置即为特征点所处的位置和对应的尺度。
二、检测关键点
为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺
度域的相邻点大或者小。如下图,图 3 所示,中间的检测点和它同尺度的 8 个相邻点和上下相邻尺度对应
的 9×2 个点共 26 个点比较,以确保在尺度空间和二维图像空间都检测到极值点。