Programming Computer Vision with Python (学习笔记十一)

尺度不变特征变换(Scale-invariant feature transform, 简称SIFT)是图像局部特征提取的现代方法——基于区域/图像块的分析。在上篇笔记里我们使用的图像之间对应点的匹配方法,不适用于不同尺度的图像。有许多应用场景需要对不同尺度(即分辨率、缩放、旋转角度、亮度等都可能存在不同)的图像进行特征识别和匹配,这就需要一种特征提取方法,通过这种方法提取出来的特征描述,可以不受尺度的影响,SIFT算法就是这种方法的实现。SHIT算法有如下的特点:

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

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

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

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

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

SIFT算法的应用非常广泛,包括物体识别、机器人地图感知与导航、全景拼接、3D建模、手势识别、影像追踪和动作比对等,原书后面章节的算法也会多次用到它。SIFT算法的过程较复杂,本文只是粗略介绍其关键步骤,以便引出SURF——基于SIFT的改进算法。

SIFT的算法还是比较复杂的,但也让人大开眼界,权威的和详细的介绍应该直接看英文论文,我的笔记记录的也只是其算法的要点,目的是为了理解算法的思想,为了对涉及到的数学有一个大概的了解。

SIFT算法要点

降采样

降采样或隔点采样,将一幅图像降为一半大小的图像,连续使用几次降采样,每次得到的图像大小都降为前一张大小的一半,最后得到一组降采样的图像。降采样的目的是为了综合所有不同清晰度的图像进行关键点提取,这种关键点携带了不同清晰度的信息,对缩放具有不变性。

高斯差分算子(Difference of Gaussians,简称DOG)

在之前的笔记介绍过,原图像与高斯核(2维高斯算子)作卷积(高斯滤波)的结果即为模糊图像,实为平滑效果,高斯滤波属于低通滤波,它可以过滤掉一定的噪声。如果把两张使用不同sigma的模糊图像记为Bσ和Bkσ, DOG操作即为两张模糊图像之差,记:

Gσ = Bkσ - Bσ

Gσ为DOG图像,它包含的特征是目标的轮廓。

SIFT先对降采样后的每张图像使用不同的sigma进行高斯模糊,结果是每个降采样图像对应一组模糊图像:

《Programming Computer Vision with Python (学习笔记十一)》

然后对每组模糊图像的相邻图像作DOG,结果是每个降采样图像对应一组DOG图像,如图:

《Programming Computer Vision with Python (学习笔记十一)》

把每一组图像堆叠起来,位于塔底的是第一组(first octave),往上是第二组,第三组…每一组的图像大小为前一组的一半,看起来像金字塔:

《Programming Computer Vision with Python (学习笔记十一)》
如图Gaussian列(左边)称为高斯金字塔,DOG列(右边)称为DOG金字塔

关键点检测

SIFT分别对每组DOG图像提取关键点,以第一组为例,将第一组DOG图像上下对齐叠加在一起,形成DOG空间,DOG空间有两个域:图像域和尺度域。图像域指图像本身的二维平面像素,尺度域指垂直于图像域的第三维度构成的像素。SIFT使用局部极值检测来定位找到关键点,如下图所示:

《Programming Computer Vision with Python (学习笔记十一)》
X位置所在像素即为当前要检测的点,以X为中心的周围像素(包括图像域和尺度域)形成了一个局部空间(像3X3魔方),如果X为此局部空间的极值(最大值或最小值),那么X即为关键点之一。

关键点描述

SIFT的提取的特征(关键点)需要对尺度保持不变性,所以这里讲的关键点,比之前笔记介绍的角点和兴趣点稍为复杂些,SIFT关键点需要携带尺度信息,包括缩放、方向等信息,主要由它周围的像素来贡献。如果用一个向量来存储这些信息,此向量称为关键点描述(key point descriptor,简称KPD),KPD生成步骤:

  1. 在关键点所在图像上,划出以关键点为中心的16×16的矩形图像:
    《Programming Computer Vision with Python (学习笔记十一)》

  2. 将16×16矩形图像划分为16小格,每小格为4×4,并计算每个像素的梯度和幅度(即像素值变化的方向及大小):
    《Programming Computer Vision with Python (学习笔记十一)》

  3. 对每个小格进行统计,统计8个方向的幅度,形成幅度直方图:
    《Programming Computer Vision with Python (学习笔记十一)》

  4. 将16小格的幅度直方图连接起来,用向量表示,即为KPD,共有128(8×16)维:
    《Programming Computer Vision with Python (学习笔记十一)》
    使用向量表示为: R = (r1, r2, …, r128)

为了让关键点对方向具有不变性,在选取16×16矩形区域的时候,将矩形的方向旋转到与关键点主方向一致。SIFT定义关键点主方向为:以关键点为中心的周围像素所贡献的主方向。

可采用梯度直方图统计法,统计以关键点为原点,一定区域内的图像像素点对关键点方向生成所作的贡献,贡献最大的那个方向即为关键点主方向。

关键点匹配

关键点的匹配问题,已经转为KPD的匹配问题,两KPD的相似程度,使用欧式距离进行计算。设有两个KPD分别为R = (r1, r2, …, r128)和S = (s1, s2, …, s128),R与S的欧式距离计算公式为:

d = sqrt((r1 - s1)^2 + (r2 - s2)^2 + ... + (r128 - s128)^2)

所以,要找出两张不同尺度图像间的对应点(具有对应关系的关键点),分下面几步:

  1. 分别检测两张图像的关键点,并计算出每个关键点的KPD,分别得到两个KPD集合SET1和SET2

  2. 为SET1中每个KPD,从SET2找最佳匹配(即欧式距离最小的为最佳匹配),然后反过来,为SET2每个KPD,从SET1中找最佳匹配,只有彼此认为是最佳匹配的那些KPD对才是对应点

为提高匹配准确率,可以设定一个阈值,欧式距离大于此阈值的那些匹配对,将不考虑。
为提高算法效率,可以使用kd树和RANSAC( Random Sample Consensus, 随机抽样一致)方法。

SURF

SURF(Speeded Up Robust Features)是对SIFT的一种改进,主要特点是快速。SURF与SIFT主要有以下几点不同处理:

  1. SIFT在构造DOG金字塔以及求DOG局部空间极值比较耗时,SURF的改进是使用Hessian矩阵变换图像,极值的检测只需计算Hessian矩阵行列式,作为进一步优化,使用一个简单的方程可以求出Hessian行列式近似值,使用盒状模糊滤波(box blur)求高斯模糊近似值。

  2. SURF不使用降采样,通过保持图像大小不变,但改变盒状滤波器的大小来构建尺度金字塔。

  3. 在计算关键点主方向以及关键点周边像素方向的方法上,SURF不使用直方图统计,而是使用哈尔(haar)小波转换。

  4. SIFT的KPD达到128维,导致KPD的比较耗时,SURF使用哈尔(haar)小波转换得到的方向,让SURF的KPD降到64维,减少了一半,提高了匹配速度。

小结

SIFT算法是有专利的,正规使用是要交专利费的,所以有人提出了一种可作为SIFT替代的算法——ORB,ORB没有专利问题,考虑到本文篇幅过长,图片过多,此算法的介绍和示例将在下一笔记介绍。

可能也是因为专利问题,skimage库有ORB算法,但没有SIFT和SURF。虽然OpenCV都包含了上述算法,但OpenCV目前不在我的学习计划中。

原书示例使用了一个第三方实现的SIFT算法库,我认为在实际使用可能价值不高,另外,书上也没有介绍ORB(也许是因为在写此书时,ORB还没有出来),但我认为ORB更有研究的必要,因为无专利问题,它将会是一个被广泛使用的算法,所以本文没有给出SIFT代码示例,但计划在下篇笔记介绍ORB和给出示例。

你还可以看我其它的笔记

参考资料

    原文作者:jk_v1
    原文地址: https://segmentfault.com/a/1190000004149225
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞