计算机视觉-sift(1)原理

1999年由David Lowe首先发表于计算机视觉国际会议(International Conference on Computer Vision,ICCV),2004年再次经David Lowe整理完善后发表于International journal of computer vision(IJCV。截止2014年8月,该论文单篇被引次数达25000余次。---来自百科

本打算对04年的论文进行翻译,结果。居然搜到完整翻译版,虽然翻译的不太好,不过有聊胜于无。本文的讲解大部分主要还是借鉴了最下面参考文献【8】的资料,先谢过作者,该作者对opencv的好多源码进行了分析,很强啊。

先说sift中一步一步的的动机(motivation):对于普通的图像匹配来说(都是平面物体:比如放在这个桌子上的书,然后这本书放在另一个地方,而非人脸在不断的旋转,一下只能看到侧脸,一下看到前脸。即sift的优点之处,旋转,缩放,尺度不变的特性,而这里都指的是平面内,而不是平面外的旋转)【此观点如果有误还望告知】,sift的先驱们发现,对于平面物体来说只要对两幅图像找到超过3对物体间的匹配点,就能使用射影几何进行对应。而对于旋转的,缩放的图像,如何建立稳定的关键点,就是关键了,当然必须考虑到光照变化,所以相对来说,比如角点、边缘、亮区域中的暗点,暗区域中的亮点等等。--这就是关键点检测。ps:sift是建立在灰度图上的。

当然找关键点的方法就是求取空间的极值,可是对于只有离散值的图像来说,如何能够模拟连续值形式的函数来找到最小值,这是问题的关键。而且通常来说,要求图像的最值,需要求导什么的,而这都是使用滤波器的方法来实现的。可是对于不同尺度的图像或者其中的物体来说,同一个尺寸的滤波器滤波之后得到的极值有可能差别较大,所以就出现了金字塔形状。【此观点如果有误,还望告知】假设图像是深层的,那么不断的不同大小的尺度的图中是会有相同信息的,所以这可以看成是插值形式,即当前图像与图像浓缩成一个点之间无限的插值而成的不同尺度却内容相同的图像序列。可想而知这时候关键点是有了,可是杂质太多,所以需要提纯,所以在极值之后得到关键点,接着就需要基于关键点进行筛选,得到更稳定的关键点。---这就是关键点定位。ps:解决了缩放、尺度的特性问题。

然后为了使得关键点更加稳固,如果加上关键点周边的信息,一起作为其特征,那么就能更好的建立特征空间。这时候可以引入方向信息,即求其梯度,这样只要将不同图片的这一步的方向都旋转到同一个方向,那么就能够更好的匹配配了,这样就解决了旋转的问题。---这就是方向确定。ps:这样尺度、方向,位置信息就都有了。

接下来就是将上面的这些信息都进行统一的描述,从而建立最后的sift特征。---这就是建立描述符。

一、原理分析

1、尺度空间极值点检测

     尺度空间:高大上的词,具体可参考[6,7]。其实就是对应着平时拍照时候,摄像头的聚焦过程产生的清晰还是模糊的意思。为了更直观,先从维基上找到的资料来解释下什么是尺度空间,当然这里指的是计算机视觉中的尺度空间。对于一幅给定的图像 f(x, y), 它的线性(高斯)尺度空间就是由该图像与一个2维高斯核卷积得到的 L(x, y; t) .其中卷积核如下:

g(x, y; t) = \frac {1}{2 \pi t}e^{-(x^2+y^2)/2t}\,                                    (公式1)

 

其中为模糊半径的平方。得到的尺度空间为:

L(\cdot, \cdot ; t)\ = g(\cdot, \cdot ; t) * f(\cdot, \cdot) ,                                    (公式2)

  L  中的点表示只在变量 x, y,上执行卷积操作, t 就是尺度参数了,是用来表示当前在哪个尺度级别上进行卷积。这个定义  L  中限制了 t  \geq 0,不过可以看得出来,计算机视觉中得到的都是离散的,间断的图像序列,而没法得到连续的图像。当然尺度参数即为高斯过滤器的方差 t = \sigma^2 ,如果说 t = 0  那么过滤器  g  就变成一个脉冲函数,导致的结果就是 L(x, y; 0) = f(x, y),  也就是在 t = 0 这个级别的尺度空间,其实就是图像  f  自己。随着 t  的变大, L  就是针对图像上使用越来越大的平滑过滤器,因而会移除越来越多图像内容的细节。因为过滤器的标准差是 \sigma = \sqrt{t} ,所以很大程度上明显小于该值的一些细节就会被忽略掉:

 

说完了尺度空间,现在接着说sift的第一步,极值点检测。ps:尺度是自然存在的,不是人为创造的,高斯卷积只是表现尺度的一种形式。

 

     高斯卷积(也叫做高斯平滑,高斯模糊):通常可以用来减少图像噪声以及降低细节层次。因为在实际应用中,在计算高斯函数的离散近似时,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。通常,图像处理程序只需要计算的矩阵就可以保证相关像素影响。所以我们先计算σ的值,然后通过该值计算出所需要的模板的大小,然后对模板进行归一化,接着用其对图像进行高斯过滤。比如当方差为0.6时得到的就是5×5的高斯模板,可以通过matlab代码生成:

 

a=fspecial('gaussian',5,0.6)

 

    

 

       ps:高斯模糊具有园对称性;而且是线性可分的,所以可以在二维的图像上对每一维单独进行一维高斯模糊来减少计算量,这可以参考【4】中的2.3分离高斯模糊部分;而且对于一幅图像进行多次连续高斯模糊的效果与一次更大的高斯模糊可以产生同样的效果,大的高斯模糊的半径是所用多个高斯模糊半径平方和的平方根,比如,使用半径分别为6 和8的两次高斯模糊变换得到的效果等于一次半径为10的高斯模糊效果,因为6^2+8^2=10^2。所以使用多个连续较小的高斯模糊处理不会比单个高斯较大处理时间少。

上面介绍了尺度空间和高斯模糊,接下来就是介绍高斯金字塔了,通过构建多层的高斯金字塔来计算后续的图片中的极值。

 高斯金字塔


图1,高斯金字塔

高斯金字塔共分O 组(Octave),每组又分S 层(Layer)。组内各层图像的分辨率是相同的,即长和宽相同,但尺度逐渐增加,即越往塔顶图像越模糊。而下一组的图像是由上一组图像(上一组倒数第3张,即上图中的2组的第0层是第一组的上往下数第3张采样得到的)按照隔点降采样得到的,即图像的长和宽分别减半。高斯金字塔的组数O 是由输入图像的分辨率得到的,因为要进行隔点降采样,所以在执行降采样生成高斯金字塔时,一直到4*4大小(因为太小的图片也没什么意义了)。其中组数公式为:

                                                                                                (公式3)

其中,X 和Y 分别为输入图像的长和宽,⌊ ⌋表示向下取整。并且每组的金字塔的层数S 为:S = s + 2+1 。这里Lowe 建议s 为3 。(s为建议的,2是为了不同组之间能够平滑过渡而在顶部加上的2层,1为最底的原始层)【8】假设当前图像大小为512*512,则如下操作:


上面公式中减2 是因为假设当前图像即为输入图像,而有的资料减3 是因为,他们把自然界作为第0组,而经过相机拍摄就成了第1组,所以是多减一次(当然了,到底减多少,任君喜欢,这不是重点)。这时候就需要依据当前图像建立自然场景的第 0 组图像了,即用当前图像进行插值得到例如上面那样的1024*1024的一张图片。

          得到了组数之后,就是计算组内尺度和组间尺度了。记得这里是假设当前得到的图片的尺度为0.5的,即第1组的第0层(自然界为第0组),即拍照拍到之后拿到的那张图片。我们可以很自然的知道,这是有组内尺度和组间尺度的。对于组内相邻的两幅图片来说:

                                                                                                 (公式4)

假设,这里的s为小写的,不是表示层数的那个大S。(为什么使用1/2,这个可以看lowe的论文【1】)所以,对于某一组来说,当s =3时,有S=s+2+1 =6幅图片,即[0,1,2,3,4,5):


而对于组间相邻的尺度来说,因为后一组是通过前一组的倒数第3幅图进行降采样得到的,即前一组的第s幅。为,将带入得其为,即后一组的第0幅图为前一组第0幅图的2倍尺度。同时推出相邻两组同一层的图像都是2倍尺度关系的。则,总的尺度坐标为:

                                               (公式5)

其中,o 表示第几组,r表示组内第几层。

        在lowe的论文中,他将第0层,也就是自然界层的初始尺度定义为1.6,而我们获取的图片初始尺度为0.5,则图像金字塔第0层的实际尺度为sqrt(1.6*1.6-0.5*0.5)=1.52(之所以可以这么计算就是因为上面高斯金字塔之上的ps部分所述)。当然这是为了避免检测极值点之前就对原始图像的高斯平滑以致于图像丢失高频信息,所以才建议在建立尺度空间前首先对原始图像的长宽扩展一倍,以保留原始图像的信息,也就是我们之前说的那个假设你获得了图像是512*512的,那么就弄一个1024*1024的作为最底层图 ,这时候因为图像扩展造成的尺度计算为(即通过计算机得到的真实尺度),当然这一组在很多资料中也叫做第 -1 组:

                                                                                      (公式6)

      本来对于关键点的检测,可以 利用LoG(高斯拉普拉斯方法,Laplacian of Gaussian),即图像的二阶导数,能够在不同的尺度下检测到图像的斑点特征,从而可以确定图像的特征点。lindeberg在文献《scale space theory:a basic tool for analysising structures at different scales》中指出尺度规范化的log算子具有真正的尺度不变性。但LoG 的效率不高。所以sift不这么做,作者对两个相邻高斯尺度空间的图像相减,得到一个DoG(高斯差分,Difference of Gaussians)的响应值图像D(x, y, σ)来近似LoG :

                              (公式7)

两者为什么能够等效,仔细的推导可以看这里的3.4 高斯差分金字塔部分。用DoG 代替LoG 并不影响对图像斑点位置的检测。而且用DoG 近似LoG 可以实现下列好处:第一是LoG 需要使用两个方向的高斯二阶微分卷积核,而DoG 直接使用高斯卷积核,省去了卷积核生成的运算量;第二是DoG 保留了个高斯尺度空间的图像,因此在生成某一空间尺度的特征时,可以直接使用公式2产生的尺度空间图像,而无需重新再次生成该尺度的图像;第三是DoG 具有与LoG 相同的性质,即稳定性好、抗干扰能力强。为了在连续的尺度下检测图像的特征点,需要建立DoG 金字塔,而DoG 金字塔的建立又离不开高斯金字塔的建立,如下图所示,左侧为高斯金字塔,右侧为DoG 金字塔【8】: 


图2 高斯金字塔的部分图,及差分金字塔

高斯金字塔的组内相邻两层相减,而两组间的各层是不能相减的。因此高斯金字塔每组有s+3 层图像,而DoG 金字塔每组则有s+2 层图像 。我们可以发现未被利用到的高斯金字塔的第0组的第0层和最上面一组的最上面一层;而dog金字塔的每组的第0层和顶层未被用到(原因如下)。

        极值点的搜索是在DoG 金字塔内进行的,这些极值点就是候选的特征点。在搜索之前,我们需要在DoG 金字塔内剔除那些像素值过小的点,因为这些像素具有较低的对比度,它们肯定不是稳定的特征点。极值点的搜索不仅需要在它所在尺度空间图像的邻域内进行,还需要在它的相邻尺度空间图像内进行,如图2 所示。每个像素在它的尺度图像中一共有8 个相邻点,而在它的下一个相邻尺度图像和上一个相邻尺度图像还各有9 个相邻点(图2 中绿色标注的像素),也就是说,该点是在3×3×3的立方体内被包围着,因此该点在DoG 金字塔内一共有26 个相邻点需要比较,来判断其是否为极大值或极小值。这里所说的相邻尺度图像指的是在同一个组内,因此在DoG 金字塔内,每一个组的第0 层和最后一层各只有一个相邻尺度图像,所以在搜索极值点时无需在这两层尺度图像内进行,从而使极值点的搜索就只在每组的中间s 层尺度图像内进行 【8】。搜索的过程是这样的:从每组的第1 层开始,以第1 层为当前层,对第1 层的DoG 图像中的每个点取一个3×3×3 的立方体,立方体上下层分别为第0 层和第2 层。这样,搜索得到的极值点既有位置坐标(该点所在图像的空间坐标),又有尺度空间坐标(该点所在层的尺度)。当第1 层搜索完成后,再以第2 层为当前层,其过程与第1 层的搜索类似,以此类推。:


2、关键点的定位

       从上面的搜索中就能够得到许多的极值点了,之所谓极值点,就是都是一群待选的点,不是直接就可以用的关键点。因为它们还存在一些不确定的因素,首先是极值点的搜索是在离散空间内进行的,并且这些离散空间还是经过不断的降采样得到的。如果把采样点拟合成曲面后我们会发现,原先的极值点并不是真正的极值点,也就是离散空间的极值点并不是连续空间的极值点,如下图【4】:


图3

(接下来这一大段都是来自参考文献【8】,因为觉得该作者讲的详细,所以直接复制过来这部分了)为了提高关键点的稳定性,需要对尺度空间DoG函数进行曲线拟合。因为,极值点是一个三维矢量,即它包括极值点所在的图像坐标,及尺度坐标:。利用DoG函数在尺度空间的Taylor展开式(拟合函数),假设我们在点处展开,展开2阶即可 

                         (公式8)

对应的矩阵形式为:

       

                               (公式9)

在这里 表示离散空间下的插值中心(在离散空间内也就是采样点)坐标, 表示拟合后连续空间下的插值点坐标,设,则表示相对于插值中心,插值后的偏移量。因此上述公式可写成:

                                                                                  (公式10)

 求导得:

                                                                (公式11)

将其置为0,得到结果为:

                                                                                                    (公式12)

将上面的极值点带入求导前的原公式(10)得:

                                    (公式13)

对于公式12 所求得的偏移量如果大于0.5(只要x、y 和σ 任意一个量大于0.5),则表明插值点已偏移到了它的临近的插值中心,所以必须改变当前的位置,使其为它所偏移到的 插值中心处,然后在新的位置上重新进行泰勒级数插值拟合,直到偏移量小于0.5 为止(x、y 和σ 都小于0.5),这是一个迭代的工程。当然,为了避免无限次的迭代,我们还需要设置一个最大迭代次数,在达到了迭代次数但仍然没有满足偏移量小于0.5 的情况下,该极值点就要被剔除掉。另外,如果由公式13 所得到的极值过小,即时(假设图像的灰度值在0~1.0 之间),则这样的点易受到噪声的干扰而变得不稳定,所以这些点也应该剔除。而在opencv 中,使用的是下列公式来判断其是否为不稳定的极值 :

                                                                                                                (公式14)

其中T 为经验阈值,系统默认初始化为0.04。

        仅仅去除低对比度的极值点对于特征的稳定性还是远远不够的。DoG函数在图像边缘也有着较强的边缘响应,因此我们还需要排除边缘响应。一旦特征点落在图像的边缘上,这些点就是不稳定的点。这是因为一方面图像边缘上的点是很难定位的,具有定位的歧义性;另一方面这样的点很容易受到噪声的干扰而变得不稳定。因此我们一定要把这些点找到并剔除掉。它的方法与Harris 角点检测算法相似,即一个平坦的DoG 响应峰值往往在横跨边缘的地方有较大的主曲率,而在垂直边缘的方向上有较小的主曲率,主曲率可以通过2×2 的Hessian 矩阵H 求出 :

                                                                                 (公式15)

其中分别表示对DoG 图像中的像素在x 轴方向和y 轴方向上求二阶偏导和二阶混合偏导。(而这4个值,可以用有限差分求导来近似得到)在这里,我们不需要求具体的矩阵H 的两个特征值α 和β,而只要知道两个特征值的比例就可以知道该像素点的主曲率 。矩阵H 的直迹和行列式分别为:

                                                                                           (公式16)

                                                                                     (公式17)

我们首先剔除掉那些行列式为负数的点,即Det(H) < 0,因为如果像素的曲率有不同的符号,则该点肯定不是特征点。设α > β,并且α = γ β,其中γ > 1,则 :

                                                             (公式18)

上式的结果只与两个特征值的比例有关,而与具体的特征值无关。我们知道,当某个像素的H 矩阵的两个特征值相差越大,即γ 很大,则该像素越有可能是边缘。对于上面那个公式来说,当两个特征值相等时,等式的值最小,随着γ 的增加,等式的值也增加。所以,要想检查主曲率的比值是否小于某一阈值γ,只要检查下式是否成立即可 :

                                                                                             (公式19)

对于不满足上式的极值点就不是特征点,因此应该把它们剔除掉。Lowe 给出γ 为10。在上面的运算中,需要用到有限差分法求偏导 。这部分可以看看这里的4.3有限差分求导

3、方向角度的确定

        上面这样就算是从DoG图中找到极值点,然后筛选下留下的就是关键点了。这时候为了解决旋转不变性,并且使得关键点更加的鲁棒,就对其周围进行深挖,将周边的信息赋予到这个关键点上。就是需要根据检测到的特征点所在的高斯尺度图像的局部结构求得一个方向基准。该高斯尺度图像的尺度σ 是已知的,并且该尺度是相对于高斯金字塔所在组的基准层的尺度,即

               (公式20,该式子的r 表示的是第几层,而下面的r 表示的是半径)

而所谓局部结构指的是在高斯尺度图像中以特征点为中心,以r 为半径的区域内计算所有像素梯度的幅角和幅值,半径r 为: 

                                                                                                                                 (公式21)

其中σ 就是上面提到的相对于所在组的基准层的高斯尺度图像的尺度。当然了像素梯度的幅值和幅角的计算公式计算公式为:

                                     (公式22)

                                                                 (公式23)

因为在以r 为半径的区域内的像素梯度幅值对圆心处的特征点的贡献是不同的,因此还需要对幅值进行加权处理,这里采用的是高斯加权,该高斯函数的方差 为:

                                                                                                                    (公式24)

 在完成特征点邻域范围内的梯度计算后,还要应用梯度方向直方图来统计邻域内像素的梯度方向所对应的幅值大小。具体的做法是,把360度分为36 个柱,则每10度为一个柱,其中0-9为第1 柱,10-19为第2 柱,以此类推。在以r 为半径的区域内,把那些梯度方向在0-9范围内的像素找出来,把它们的加权后的梯度幅值相加在一起,作为第1 柱的柱高;求第2 柱以及其他柱的高度的方法相同。为了防止某个梯度方向角度因受到噪声的干扰而突变,我们还需要对梯度方向直方图进行平滑处理 。Opencv中直方图以周围360度为范围,每10度为一个柱,一共36个柱,柱所代表的方向为像素点梯度方向,柱的长短代表了梯度幅值。根据Lowe的建议,模板采用[0.25,0.5,0.25],并连续加权两次: 

                (公式25)

(这里要注意下,不同版本的opencv中实现的方法不一样)

其中h 和H 分别表示平滑前和平滑后的直方图。由于角度是循环的,即0度=360度,如果出现h(j),j 超出了(0,…,15)的范围,那么可以通过圆周循环的方法找到它所对应的、在0-360度之间的值,如h(-1) = h(35) 。

 


图4

上图只画了8个柱。该图来自这里。方向直方图的峰值则代表了该特征点处邻域梯度的方向,以直方图中最大值作为该关键点的主方向。为了增强匹配的鲁棒性,只保留峰值大于主方向峰值80%的方向作为该关键点的辅方向。因此,对于同一梯度值的多个峰值的关键点位置,在相同位置和尺度将会有多个关键点被创建但方向不同。仅有15%的关键点被赋予多个方向,但可以明显的提高关键点匹配的稳定性。实际编程实现中,就是把该关键点复制成多份关键点,并将方向值分别赋给这些复制后的关键点,并且,离散的梯度方向直方图要进行插值拟合处理,来求得更精确的方向角度值。

        这样,直方图的主峰值,即最高的那个柱体所代表的方向就是该特征点处邻域范围内图像梯度的主方向,也就是该特征点的主方向。由于柱体所代表的角度只是一个范围,如第1柱的角度为0-9度,因此还需要对离散的梯度方向直方图进行插值拟合处理,以得到更精确的方向角度值。例如我们已经得到了第i 柱所代表的方向为特征点的主方向,则拟合公式为 :

                                               (公式26)

                                                                                          (公式27)

其中,H 为由公式34 得到的直方图,角度θ 的单位是度。同样的,上面两个公式也存在着之前那个直方图平滑所遇到的角度问题,处理的方法同样还是利用角度的圆周循环。 

    每个特征点除了必须分配一个主方向外,还可能有一个或更多个辅方向,增加辅方向的目的是为了增强图像匹配的鲁棒性。辅方向的定义是,当存在另一个柱体高度大于主方向柱 体高度的80%时,则该柱体所代表的方向角度就是该特征点的辅方向。在第2 步中,我们实现了用两个信息量来表示一个特征点,即位置和尺度。那么经过上面的计算,我们对特征点的表示形式又增加了一个信息量:方向, 即。如果某个特征点还有一个辅方向,则这个特征点就要用两个值来表示:,其中表示主方向,表示辅助方向。而其他的变量:x, y, σ 不变。 

4、描述符的建立

        描述的目的在于之前的那些零碎的关键点的计算之后,如何用一组向量来将这个关键点描述出来,这个描述子不但包含关键点,也包含了周边贡献的像素点的信息。因为已经有了尺度,位置和方向等信息,所以能够有较好的适应性。思路就是对关键点周围图像区域分块,计算块内梯度直方图生成具有独特性的向量,该向量就是该区域图像信息的一种抽象,具有唯一性。

        在图像局部区域内,这些参数可以重复的用来描述局部二维坐标系统,因为这些参数具有不变性。下面就来计算局部图像区域的描述符,描述符既具有可区分性,又具有对某些变量的不变性,如光亮或三维视角。描述符是与关键点所在的尺度有关的,所以描述关键点是需要在该关键点所在的高斯尺度图像上进行的。在高斯尺度图像上,以关键点为中心,将其附近邻域划分为d×d 个子区域(Lowe 取d = 4)。每个子区域都是一个正方形,正方形的边长为3σ,也就是说正方形的边长有3σ 个像素点(这里当然要对3σ 取整)。σ 为相对于关键点所在的高斯金字塔的组的基准层图像的尺度,即公式20 所表示的尺度。考虑到实际编程的需要,关键点邻域范围的边长应为3σ(d+1),因此关键点邻域区域一共应有3σ(d+1)×3σ(d+1)个像素点。为了保证关键点具有旋转不变性,还需要以关键点为中心,将上面确定下来的关键点邻域区域旋转θ(θ 就是该关键点的方向)。由于是对正方形进行旋转,为了使旋转后的区域包括整个正方形,应该以从正方形的中心到它的边的最长距离为半径,也就是正方形对角线长度的一半,即: 

                                                                                                             (公式28)

        所以上述的关键点邻域区域实际应该有(2r+1)×(2r+1)个像素点。由于进行了旋转,则这些采样点的新坐标为: 

                                                              (公式29)

其中是旋转后的像素的新坐标,是旋转前的坐标。

ps:从《matrix computations.4th》中可以看到:

即上面关键点的旋转是逆时针旋转θ度:


图5.上图中上左一到上右一是坐标系顺时针的旋转了,其实也就等同于该坐标逆时针的旋转了。

        这时,我们需要计算旋转以后关键点邻域范围内像素的梯度幅值和梯度幅角。这里的梯度幅值还需要根据其对中心特征点贡献的大小进行加权处理,加权函数仍然采用高斯函数,它的方差的平方为。在实际应用中,我们是先以关键点为圆心,以公式28 中的r 为半径,计算该圆内所有像素的梯度幅角和高斯加权后的梯度幅值,然后再根据公式29 得到这些幅值和幅角所对应的像素在旋转以后新的坐标位置。 

       在计算关键点描述符的时候,我们不需要精确知道邻域内所有像素的梯度幅值和幅角,我们只需要根据直方图知道其统计值即可。这里的直方图是三维直方图 。如下图 所示:


图6

       上图 中的三维直方图为一个立方体,立方体的底就是关键点邻域区域。如前面所述,该区域被分为4×4 个子区域,即16 个子区域,邻域内的像素根据其坐标位置,把它们归属于这16 个子区域中的一个。立方体的三维直方图的高为邻域像素幅角的大小。我们把360 度的幅角范围进行8 等分,每一个等份为45 度。则再根据邻域像素梯度幅角的大小,把它们归属于这8 等份中的一份。这样三维直方图就建立了起来,即以关键点为中心的邻域像素根据其坐标位置,以及它的幅角的大小被划归为某个小正方体(如图4 中的C 点,在这里,可以通过归一化处理,得到边长都为单位长度的正方体的)内,该直方图一共有4×4×8=128个这样的正方体。而这个三维直方图的值则是正方体内所有邻域像素的高斯加权后的梯度幅值之和,所以一共有128 个值。我们把这128 个数写成一个128 维的矢量,该矢量就是该特征点的特征矢量,所有特征点的矢量构成了最终的输入图像的SIFT 描述符。

       显然,正方体的中心应该代表着该正方体。但落入正方体内的邻域像素不可能都在中心,因此我们应该对上面提到的梯度幅值做进一步处理,根据它对中心点位置的贡献大小进行加权处理,即在正方体内,根据像素点相对于正方体中心的距离,对梯度幅值做加权处理。所以三维直方图的值,即正方体的值共需要下面4 个步骤完成:1、计算落入该正方体内的邻域像素的梯度幅值A;2、根据该像素相对于关键点的距离,对A 进行高斯加权处理,得到B;3、根据该像素相对于它所在的正方体的中心的贡献大小,再对B 进行加权处理,得到C;4、对所有落入该正方体内的像素做上述处理,再进行求和运算ΣC,得到D。


图7

        由于计算相对于正方体中心点的贡献大小略显繁琐,因此在实际应用中,我们需要经过坐标平移,把中心点平移到正方体的顶点上,这样只要计算正方体内的点对正方体的8 个顶点的贡献大小即可。根据三线性插值法,对某个顶点的贡献值是以该顶点和正方体内的点为对角线的两个顶点,所构成的立方体的体积。如图4 中,C000 的坐标为(0, 0, 0),C100 的坐标为(1, 0, 0),以此类推,C 的坐标为(r, c, θ),(这里的r, c, θ 值的大小肯定是在0 和1 之间),则C 点与8 个顶点所构成的立方体的体积,也就是对8 个顶点的贡献分别为:

                                                                                                (公式30)

经过上面的三维直方图的计算,最终我们得到了该特征点的特征矢量。为了去除光照变化的影响,需要对特征矢量进行归一化处理,即:

                                                                          (公式31)

为归一化后的特征矢量。尽管通过归一化处理可以消除对光照变化的影响,但由于照相机饱和以及三维物体表面的不同数量不同角度的光照变化所引起的非线性光照变化仍然存在,它能够影响到一些梯度的相对幅值,但不太会影响梯度幅角。为了消除这部分的影响,我们还需要设一个t = 0.2 的阈值,保留Q 中小于0.2 的元素,而把Q 中大于0.2 的元素用0.2 替代。最后再对Q 进行一次归一化处理,以提高关键点的可区分性。


备注:上面的4 描述符的建立 还未完全的理解透,所以是完整的照抄的,接下来将会分析opencv中的sift代码,加深理解,然后回来修改。

2015年09月25日,第0次修改!


参考资料:

[1]  Lowe SIFT 原文:http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf
[2]  SIFT特征提取分析 http://blog.csdn.net/abcjennifer/article/details/7639681
[3]  王永明,王贵锦. 图像局部不变性特征与描述. [M] 国防工业出版社 
[4]  SIFT算法详解 http://blog.csdn.net/zddblog/article/details/7521424
[5] sift论文翻译 http://www.cnblogs.com/cuteshongshong/archive/2012/05/25/2506374.html
[6] 《Scale-space theory in computer vision  》
[7] 尺度空间:维基 https://en.wikipedia.org/wiki/Scale_space 
[8]  赵春江, opencv2.4.9 源码分析,SIFT http://blog.csdn.net/zhaocj



 

posted @ 2015-09-25 17:40  仙守  阅读(874)  评论(0编辑  收藏  举报