SIFT算法学习

(本文的部分内容摘自一些网友的博客)  

Sift是David Lowe于1999年提出的局部特征描述子,并于2004年进行了更深入的发展和完善。Sift特征匹配算法可以处理两幅图像之间发生平移、旋转、仿射变换情况下的匹配问题,具有很强的匹配能力。在Mikolajczyk对包括Sift算子在内的十种局部描述子所做的不变性对比实验中,Sift及其扩展算法已被证实在同类描述子中具有最强的健壮性。

   

 总体来说,Sift算子具有以下特性:

   (1)Sift特征是图像的局部特征,对平移、旋转、尺度缩放、亮度变化、遮挡和噪声等具有良好的不变性,对视觉变化、仿射变换也保持一定程度的稳定性。

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

   (3)多量性,即使少数的几个物体也可以产生大量Sift特征向量。

   (4)速度相对较快,经优化的Sift匹配算法甚至可以达到实时的要求。

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

 -----------------------------------------------------------------------------------------------------------------------------------------------------------

Sift特征匹配算法主要包括两个阶段:第一个阶段是Sift特征的生成;第二阶段是Sift特征向量的匹配。

     Sift特征的生成一般包括以下几个步骤:

 

Scale space extrema detection

 

图像尺度空间的概念:

The scale space of an image is defined as a function,L(x,y,σ), that is produced from the convolution of a variable-scale Gaussian G(x,y,σ) with the input image I(x,y)

          L(x,y,σ) = G(x,y,σ)×I(x,y)   

尺度空间可以理解为图像高斯金字塔

高斯金字塔的构造是这样的,每组里有若干层!第一组的第一层为原图像,然后将图像做一次高斯平滑(高斯卷积、高斯模糊)高斯平滑里有一个参数σ,在SIFT里作者取1.6,然后将σ乘一个比例系数k作为新的平滑因子来平滑第一组第二层得到第三层。重复若干次,得到L层他们分别对应的平滑参数为:0,σ,kσ,k2σ....。然后将最后一幅图像做比例因子为2的降采样得到第二组的第一层然后对第二组的第一层做参数是σ的高斯平滑,对第二层做kσ的平滑得到第三层.....这里一定注意:每组对应的平滑因子是一样的!这样反复形成了O组L层。一般模糊的高斯模板长宽都约为6σ(这里σ为当次的平滑因子,就是可能是kσ,k2σ..)。

DoG(Difference of Gaussian)金字塔

由高斯金字塔构造出来,他的第一组第一层是由高斯金字塔的第一组第二层减第一组第一层,他的第一组第二层是由高斯金字塔的第一组第三层减第一组第二层得到,(说的这么繁琐是为了大家能理解的直观点)。每组都这样就生成了DoG金字塔。顺便说一下,DoG金字塔每组图像几乎都是一片黑,但仔细看你能看出轮廓的。

(两个金字塔在SIFT算法里的特殊说明:

  1、在SIFT里高斯金字塔的第一组第一层通常是由一个原图像长宽扩大一倍开始的,这样做是为了可以得到更多的特征点
  2、大家可以发现如果用每组5层的高斯金字塔构造一个DoG金字塔的的话,DoG的每组的层数是4。
  3、对于DoG金字塔,特征点的搜索从每组的二层到倒数第二层的(后面说明为什么),所以如果实际用n层那么DoG金字塔应该有n+2层,那么对应的高斯金字塔  应该有n+3层。
  4、由于这样所以高斯金字塔从第二组开始的每组第一层是由上一组的倒数第二层降采样得到的。
1
2
 
DoG的局部极值点:

关键点是由DOG空间的局部极值点组成的。为了寻找DoG函数的极值点,每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。中间的检测点和它同尺度的 8 个相邻点和上下相邻尺度对应的 9×2 个点共 8+18=26 个点比较,以确保在尺度空间和二维图像空间都检测到极值点。

在极值比较的过程中,每一组图像的首末两层是无法进行极值比较的,为了满足尺度变化的连续性,我们在每一组图像的顶层继续用高斯模糊生成了3幅图像,高斯金字塔有每组S+3层图像。DOG金字塔每组有S+2层图像。

 

Keypoint location

 

关键点精确定位:由于DoG值对噪声和边缘较敏感,因此,在上面DoG尺度空间中检测到局部极值点还要经过进一步的检验才能精确定位为特征点。为了提高关键点的稳定性,需要对尺度空间DoG函数进行曲线拟合,利用DoG函数在尺度空间的Taylor展开式获取极值点的偏移量:

假设极值点的坐标为X=(x,y,l),此时这三个方向上的坐标都为整数。根据泰勒公式可以计算出以极值点为原点相对于极值点在行、列以及层数上的偏移量

X_P=(x_p,y_p,intvl_p)。

定位准则:

1)如果三个方向上的偏移量都小于0.5,则认为该点就是极值点。此时可以结束对这个极值点的分析,保存该点的偏移信息,然后分析该极值点的像素值是否满足要求。

2)如果某一方向上的偏移量大于等于0.5,如假设x_p>=0.5,则采取下述方式进行处理:先将x_p四舍五入得到一个整数intx,然后将intx与x相加得到一个新的极值点 X_N=(x+intx,y,l), 如果点X_N没有进入预先排除的区域则对这个点进行泰勒展开(否则该点被放弃,然后分析下一个极值点),直到找到一个点的偏移满足在三个方向上都小于0.5为止,然后记下点X_N及其偏移值,此时极值点为X_N。但是这个重新确定极值点并重新定位的操作只能循环5次。若超过5次仍无法满足1)的要求,这该极值点被放弃,然后分析下一个点。

 确定精确定位后的极值点的像素值,进行对比度的检测。若像素值满足大于contr_thr / intvls(程序中为0.04/3),则该点才能最终确定为极值点。

消除边界响应:

要想移除边界特征,我们要计算特征点附近高斯模糊图像的梯度。基于特征点附近的图像,有三种可能的特征:

1. 平坦特征:该特征在两个方向的梯度值都很小。

2. 边界特征:该特征一个方向的梯度值很大(垂直于边界的方向),另一个方向的梯度值很小(沿着边界的方向)。

3. 直角特征:该特征两个方向的梯度值都很大。

直角特征是很好的特征点,我们想得到直角特征,如果特征点的两个方向的梯度值都很大,那么就让它通过,否则就拒绝它。这可以通过Hessian矩阵实现,使用这个矩阵我们可以很容易地检测它是不是直角特征。在SIFT算法中,不需要像Harris corner检测直接计算Hessian矩阵的两个特征值,而只需要计算两个特征值的积与和的比率。

 

关键点的尺度

 2i-1(σ,kσ,k2σ,...,kS-1σ)

k=21/S  S是每组的层数

i  金字塔组数

n  每一组的层数

 

Orientation Assignment

 

分配特征点的方

在上个步骤,我们得到了合理的特征点,并且这些特征点被测试是在位置上稳定的,容易识别匹配的。由于我们已经知道特征点是在哪个尺度被检测到的,所以这些特征点也是尺度不变的。接下来要对每个特征点赋一个方向,以使这些特征点具有旋转不变性。特征点所拥有的不变性越多越好。

在特征点附近,我们创建一个方向收集区域来控制该特征点影响的范围,方向收集区域的大小依赖于它所在图像的尺度,尺度越大,收集的区域越大。在方向收集区域中每个像素点的梯度大小和方向用下面的公式计算,从而得到另外两幅图,分别是梯度的大小图和方向图。

我们用一个直方图来统计方向收集区域中像素的平均方向,在该直方图中,将360度的方向分成36个bins,每个bin包含10度。假设方向收集区域中某个像素点的梯度方向是18.75度,把它放入10-19度的bin中,并且加入到bin中的量与该像素点的梯度大小成正比。

一旦对方向收集区域中的每个像素点都执行了这个操作后,直方图在某个bin上出现最高峰值。并且所有大于最高峰80%的峰值也被转化为一个新的特征点,这个新的特征点和原来的特征点一样拥有相同的位置和尺度,但是新特征点的方向是另一个峰值。因此方向将一个特征点分为多个特征点。

 

方向收集区域的窗口大小等于1.5倍图像尺度量的高斯窗口的大小。

 

Keypoint descriptor

 

现在我们已经得到了拥有尺度不变性和旋转不变性的特征点,接下来要为每个特征点创建一个唯一标识它的“指纹”,SIFT算法作者将它称为SIFT描述子(descriptor)。所生成的SIFT描述子既要能让相同场景中图像的特征点能够正确匹配,而且还要让不同场景中图像的特征点能够正确区分。

为了得到这样的SIFT描述子,我们将特征点周围16*16的窗口分解为16个4*4的子窗口,下图显示了分解的过程。在每个4*4的子窗口中,计算出梯度的大小和方向,并用一个8个bin的直方图来统计子窗口的平均方向,如图2.13所示。

下图将特征点周围16*16的窗口分解为16个4*4的子窗口

梯度方向在0-44度范围的像素点被放到第一个bin中,45-89度范围的像素点被放到下一个bin中,依此类推。同样加入到bin中的量依赖于该像素点梯度的大小。与之前不同的是,加入的量不仅与像素点的梯度大小相关,而且还依赖离特征点的距离,这样远离特征点的像素点会加入较少的量到直方图中。这通过一个高斯加权函数来实现,这个函数生成一个加权值(像一个二维的钟形曲线),用它乘以16*16的窗口中每个像素点的梯度大小,得到加权后的梯度大小,距离特征点越远,要加入直方图的像素点的梯度大小越小。

这样每个4*4的子窗口都对应一个8bin的直方图,且直方图中加入的值是像素的用高斯加权后的梯度大小,而特征点周围16*16的窗口中包含16个4*4的子窗口,共有16*8=128个数,然后将这128个数组成的向量进行单位化,单位化后的128维向量就是SIFT的描述子。

 

 

————————————————————————————————————————————————————————————

 关于SIFT匹配,后面两篇文章讲K-D tree的,讲的不错,可以过去看看。

http://underthehood.blog.51cto.com/2531780/687160

http://grunt1223.iteye.com/blog/921371

 

 

posted on 2011-12-29 17:35  刘晓辉  阅读(13783)  评论(1编辑  收藏  举报

导航