机器视觉基础系列三——特征点检测算法
学习一些有关点检测和点匹配的需要,补充一些机器视觉以及cv领域常用的特征点检测的算法
机器视觉中特征检测的概念
对于一张输入的图片来说我们在给出一个特征区域(或者说是特征点时)
- 平坦部分很难找到它在原图中的位置。
- 边缘相比平坦要好找一些,但也不能一下确定。
- 角点可以一下就能找到其在原图的位置。
这三种情况也对于了三种情况的点:
- homogeneous平滑的点周围像素基本没有发生变换的点。
- edge边缘点:之前opencv学习的很多算子用来提取边缘的信息。
- corner角点:也就是我们需要的特征点信息。
那么角点相对来说要包含深度特征呢?
- 在特征中最重要的是角点(角点检测)
- 灰度梯度的最大值对应的像素(转为灰色图像后)
- 两条线的交点
- 极值点(一阶导数最大值,但二阶导数为0)
我们的点提取任务通常包括了两种一种时匹配任务,一种时追踪任务
-
匹配指的是:在两张图片上分别进行角点的检测(特征点的检测)通过算法匹配两张图片上的特征点
-
跟踪tracking是指:在之前的一张图片上检测出许多的特征点,我们在下一张图片上跟踪上这些特征点的信息。(跟踪点)
最后也就引出了我们要学习的主题:一些常用的特征点提取算法(Harris、SIFT、SURF、ORB等算法)
Harris角点检测
Harris角点是由Harris和Stephens在1998年提出的
这一张图形象的给出了在进行角点检测时候选取特征点的情况。 灰色的部分我们代表的是一张灰色图像,通过绿色部分的一个滑动窗口进行计算。
-
第一:我们的窗口向任何方向移动其像素值都不会发生太大的变化。对应的也就是平滑的点。
-
第二:我们的窗口沿着上下方向移动时中心点区域及其周围不会发生太大的变化,而左右移动时会发生显著的变化,对应的就是我们的边缘区域
-
第三:不管我们的窗口向任何方向移动都会发生显著的变化对应的就是我们的角点。
这也就是这个角点检测算法的核心思想。 (计算我们窗口中的平均灰度值判断其是否会发生显著的变换
)
Harris算法的提出,实际上是对之前一个算法的改进:我们检测该像素点是否是角点。
这里我们朝着各个方向进行移动 存在的理论上的问题是:只能沿着直线的方向来进行移动
计算如图所示的窗口的平均值,取最小值来和我们的最小阈值进行比较从而判断是否为角点。
它没有考虑到向各个方向进行移动。
Harris算法的关键点检测原理
我们考虑检测一下这一个黄色的点是否是角点呢?
首先我们沿着u v向量的方向进行移动,用下面的数学公式来描述这一个过程信息。
E ( u , v ) = ∑ x , y w ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E(u, v)=\sum_{x, y} w(x, y)[I(x+u, y+v)-I(x, y)]^{2} E(u,v)=x,y∑w(x,y)[I(x+u,y+v)−I(x,y)]2
在图中就是箭头处的两个点在移动之后的差异,我们的九个格子都做一次,进行加权的求和
-
假设E(u,v)代表了在以某一点(x,y)为中心的窗口像素向x方向移动u分量,向y方向移动v分量后的亮度值变化量的累加值。
-
所以E(u,v)是一种平方差异和(sum squared differences,SSD)
-
w 可以看作是每个xy像素点的像素值也可以看作是权重信息。(例如中心点比较重要设置的权重值会比较大。)
-
这里的w(x,y)是一个窗口权函数,最简单直接令w(x,y)=1。但为了更精确,w(x,y)可以设置为二维高斯权函数
-
如果角点中心位于窗口中心,E(u,v)会明显比偏离角点中心的窗口的变化值大。可以以此来确定角点的像素级位置。
我们应用下面的泰勒展开公式进行泰勒展开的操作。
f ( x + u , y + v ) = f ( x , y ) + u f x ( x , y ) + v f y ( x , y ) f(x+u, y+v)=f(x, y)+u f_{x}(x, y)+v f_{y}(x, y) f(x+u,y+v)=f(x,y)+ufx(x,y)+vfy(x,y)
I ( x + u , y + v ) ≈ I ( x , y ) + u I x + v I y I(x+u, y+v) \approx I(x, y)+u I_{x}+v I_{y} I(x+u,y+v)≈I(x,y)+uIx+vIy
I x = ∂ I ∂ x I y = ∂ I ∂ y \begin{aligned} I_{x} & =\frac{\partial I}{\partial x} \\ I_{y} & =\frac{\partial I}{\partial y} \end{aligned} IxIy=∂x∂I=∂y∂I
下面就是使用数学的知识对这个图像来进行一步的化简操作。
E ( u , v ) = ∑ x , y w ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E ( u , v ) ≈ ∑ x , y w ( x , y ) [ u I x + v I y ] 2 \begin{array}{l} E(u, v)=\sum_{x, y} w(x, y)[I(x+u, y+v)-I(x, y)]^{2} \\ E(u, v) \approx \sum_{x, y} w(x, y)\left[u I_{x}+v I_{y}\right]^{2} \end{array} E(u,v)=∑x,yw(x,y)[I(x+u,y+v)−I(x,y)]2E(u,v)≈∑x,yw(x,y)[uIx+vIy]2
E ( u , v ) = ∑ x , y w ( x , y ) ( u 2 I x 2 + 2 u v I x I y + v 2 I y 2 ) E(u, v)=\sum_{x, y} w(x, y)\left(u^{2} I_{x}^{2}+2 u v I_{x} I_{y}+v^{2} I_{y}^{2}\right) E(u,v)=x,y∑w(x,y)(u2Ix2+2uvIxIy+v2Iy2)
E ( u , v ) = w ( x , y ) [ u v ] ( ∑ x , y [ I x 2 I x I y I x I y I y 2 ] ) [ u v ] E(u, v)=w(x, y)\left[\begin{array}{ll} u & v \end{array}\right]\left(\sum_{x, y}\left[\begin{array}{cc} I_{x}^{2} & I_{x} I_{y} \\ I_{x} I_{y} & I_{y}^{2} \end{array}\right]\right)\left[\begin{array}{l} u \\ v \end{array}\right] E(u,v)=w(x,y)[uv](x,y∑[Ix2IxIyIxIyIy2])[uv]
从而得出了我们最后的一个推导结果:
E ( u , v ) = [ u v ] M [ u v ] M = ∑ x , y w ( x , y ) [ I x 2 I x I y I x I y I y 2 ] E(u, v)=\left[\begin{array}{ll} u & v \end{array}\right] \mathbf{M}\left[\begin{array}{l} u \\ v \end{array}\right] \quad \mathbf{M}=\sum_{x, y} w(x, y)\left[\begin{array}{cc} I_{x}^{2} & I_{x} I_{y} \\ I_{x} I_{y} & I_{y}^{2} \end{array}\right] E(u,v)=[uv]M[uv]M=x,y∑w(x,y)[Ix2IxIyIxIyIy2]
这个公式中的计算都是可以通过求导数来计算出来的。M就变成了十分重要的一个部分,也就是我们常见的一个二次型的矩阵。
我们的矩阵M上发生移动其实在数学上对应在不同的一个区域进行一个截面的操作得到的就是一个椭圆信息。
Harris角点并不需要直接求E(u,v)来判断是否是角点,而是可以通过求M矩阵的特征值来判断。
对于我们的椭圆来说我们会有一个长轴a和一个短轴b的信息。
数学上就是沿着这两个方向移动a和b我们的像素值(灰度值发生一次变换)
按照角点的定义我们希望这个椭圆越小越好,稍稍移动一点点就会发生很大的变换。
这个椭圆完成由二次型决定,进而由M决定 准确的来说是由我们的M矩阵的两个特征值来决定的
a
,
b
=
1
λ
a, b=\frac{1}{\sqrt{\lambda}}
a,b=λ1
当两个特征值越大代表的是在两个方向上变换都很大的时候,就很会满足角点的定义了。
我们在特征检测部分的概念中提到的三种情况,就对于下面的三种数学表示了。
到此我们的第一个角点检测算法的原理部分就变得十分的清晰了呀
我们在数学上引入了角点强度函数的概念来进行最后的判断。
R = λ x λ y − k ( λ x + λ y ) 2 = det ( M ) − k trace 2 ( M ) \begin{aligned} R & =\lambda_{x} \lambda_{y}-k\left(\lambda_{x}+\lambda_{y}\right)^{2} \\ & =\operatorname{det}(\mathbf{M})-k \operatorname{trace}^{2}(\mathbf{M}) \end{aligned} R=λxλy−k(λx+λy)2=det(M)−ktrace2(M)
解读一下这个公式也就是M矩阵的行列式的值减去M矩阵的迹的平方求出R我们根据R的值结合上面的图就能确定其中的各个点的类别了。
对于我们的角点来说在等高线区域其实它的值也是不发现变换的,意味着就是是角点也同样存在着一个刁钻的方向使得其灰度值不发生变换。
Harris角点检测算法流程
-
将原始图像转化为灰度影像;
-
应用高斯滤波器来平滑噪声;
-
应用Sobel算子寻找灰度图像中每个像素的x方向和y方向的梯度值:
-
对于灰度图像中的每个像素p,考虑其周围有一个3×3的窗口,并计算角点强度函数R)称之为Harris分数,
-
查找超过某个阈值并且是某窗口中局部最大值的像素
-
对于满足第(5)条标准的每个像素,计算一个特征描述符。
参考资料:https://mooc1.chaoxing.com/mooc-ans/nodedetailcontroller/visitnodedetail?courseId=216682762&knowledgeId=438972339&enc=&mooc2=1
这个角点检测算法的缺点在于
- 对亮度和对比度不敏感
- 不具有尺度不变性
SIFT关键点检测
SIFT全称:Scale-Invariant Feature Transform(与缩放无关的特征点转换)
不同时间内的两幅拍摄物体相同的图进行特征点的匹配操作。
首先这个技术出现的原因是什么呢?
Harris角点具有旋转不变的特性,但是却不具有尺度不变性。
从原来的角点检测为了一个边缘的区域。
算法简介
SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。
SIFT算法特点
- 具有较好的稳定性和不变形,能够适当旋转、尺度缩放、亮度的变化能在一定程度上不受视角变化、仿射变换、噪声的干扰。
- 区分性好,能够在海量特征数据库中进行快速准确的区分信息进行匹配
- 多属性,就算只有单个物体,也能产生大量特征向量
- 高速性,能够快速的进行特征向量匹配
- 可扩展性,能够与其它形式的特征向量进行联合
SIFT算法的基本步骤与实现
-
尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯差分函数来识别潜在的对于尺度和旋转不变的关键点。
-
关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。
-
关键点方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而保证了对于这些变换的不变性。
-
关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度作为关键点的描述符,它允许比较大的局部形状的变形或光照变化。
尺度空间极值检测。
图像金字塔
图像金字塔是一种以多分辨率来解释图像的结构,通过对原始图像进行多尺度像素采样的方式,生成N个不同分辨率的图像。把具有最高级别分辨率的图像放在底部,以金字塔形状排列,往上是一系列像素(尺寸)逐渐降低的图像,一直到金字塔的顶部只包含一个像素点的图像,这就构成了传统意义上的图像金字塔。
获得图像金字塔一般包括二个步骤:
-
利用低通滤波器平滑图像
-
对平滑图像进行抽样(采样)
有两种采样方式——上采样(分辨率逐级升高)和下采样(分辨率逐级降低)
在不同的尺度空间是不能使用相同的窗口检测极值点,对小的关键点使用小的窗口,对大的关键点使用大的窗口,为了达到上述目的,我们使用尺度空间滤波器。
高斯核是唯一可以产生多尺度空间的核函数。-《Scale-space theory: A basic tool for analysing structures at different scales》
一个图像的尺度空间L(x,y,σ),定义为原始图像I(x,y)与一个可变尺度的2维高斯函数G(x,y,σ)卷积运算,即:
L ( x , y , σ ) = G ( x , y , σ ) ∗ I ( x , y ) L(x, y, \sigma)=G(x, y, \sigma) * I(x, y) L(x,y,σ)=G(x,y,σ)∗I(x,y)
其中:
G ( x , y , σ ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x, y, \sigma)=\frac{1}{2 \pi \sigma^{2}} e^{-\frac{x^{2}+y^{2}}{2 \sigma^{2}}} G(x,y,σ)=2πσ21e−2σ2x2+y2
σ是尺度空间因子,它决定了图像的模糊的程度。在大尺度下(σ值大)表现的是图像的概貌信息,在小尺度下(值小)表现的是图像的细节信息。
对于参数σ,在Sift算子中取的是固定值1.6。
如何生成我们的不同尺度下的多个特征呢?我们需要通过不同的高斯核来构建高斯图像金字塔。
高斯金字塔:
下面我们构建图像的高斯金字塔
,它采用高斯函数
对图像进行模糊
以及降采样
处理得到的,高斯金字塔构建过程中,首先将图像扩大一倍
,在扩大的图像的基础之上
构建高斯金字塔
,然后对该尺寸下图像进行高斯模糊,
几幅模糊之后的图像集合构成了一个Octave
,然后对该Octave下选择一幅图像进行下采样
,长和宽分别缩短一倍,图像面积变为原来四分之一。这幅图像就是下一个Octave的初始图像
,在初始图像的基础上完成属于这个Octave的高斯模糊处理,以此类推完成整个算法所需要的所有八度构建,这样这个高斯金字塔就构建出来了,整个流程如下图所示:
参考资料:
为了加深印象和进一步的进行理解,我们对这个高斯金字塔的细节部分进行一定的描述
-
σ-1层:是可以选择性的来进行操作的,论文中其实提到的是我们取σ的值为1.6但是由于我们相机进行0.5的平滑处理,所有一般为1.25 (这里是为了保留更多的信息进行的2倍上采样)
-
我们要使用下面的公式来确定高斯金字塔的层数,我们的高斯金字塔的层数,之和原始的图像是有关系的。
O = [ log 2 min ( M , N ) ] − 3 O=\left[\log _{2} \min (M, N)\right]-3 O=[log2min(M,N)]−3
M 为原始图像的行高;N 为原始图像的列宽;O 为图像高斯金字塔的组数
- 为了保持高斯差分金字塔的尺度空间(即高斯模糊系数)的连续
性,下一个Octave(i+1)的第1层由上一个Octave(i)中倒数第3层直接降采样不需模糊产生;而同一组中素引号1之5的图像则是在本组的第1层基础上使用连续的模糊产生的,不需要降采样。
最后的一个问题个人认为是最为关键的一个问题,我们每一层的σ的倍率或者说是索引值是如何进行产生的呢?
- 结合下面的公式:
σ ( o , r ) = σ 0 2 o + r n o ∈ [ 0 , 1 , … , O − 1 ] , r ∈ [ 0 , 1 , … , n + 2 ] \begin{array}{l} \sigma(o, r)=\sigma_{0} 2^{o+\frac{r}{n}} \\ o \in[0,1, \ldots, O-1], r \in[0,1, \ldots, n+2] \end{array} σ(o,r)=σ02o+nro∈[0,1,…,O−1],r∈[0,1,…,n+2]
公式中,o 为组索引序号,r 为层索引序号,σ (o, r ) 为对应的图像的高斯模糊系数.σ 0为高斯模糊初始值,David G.Lowe 教授刚开始设置为1.6,考虑相机实际已对图像进行σ=0.5的模糊处理,故实际
σ 0 = 1. 6 2 − 0. 5 2 = 1.52 \sigma_{0}=\sqrt{1.6^{2}-0.5^{2}}=1.52 σ0=1.62−0.52=1.52
之后我们结合这个公式列举一下第0组 第1组 第2组…的实例便于理解
-
第0组的0 1 2 这里的n代表的是每一组中有的层数值
σ ( 0 , 0 ) = σ 0 2 0 + 0 n = σ 0 σ ( 0 , 1 ) = σ 0 2 0 + 1 n = σ 0 2 1 n σ ( 0 , 2 ) = σ 0 2 0 + 2 n = σ 0 2 1 n 2 1 n \begin{array}{c} \sigma(0,0)=\sigma_{0} 2^{0+\frac{0}{n}}=\sigma_{0} \\ \sigma(0,1)=\sigma_{0} 2^{0+\frac{1}{n}}=\sigma_{0} 2^{\frac{1}{n}} \\ \sigma(0,2)=\sigma_{0} 2^{0+\frac{2}{n}}=\sigma_{0} 2^{\frac{1}{n}} 2^{\frac{1}{n}} \end{array} σ(0,0)=σ020+n0=σ0σ(0,1)=σ020+n1=σ02n1σ(0,2)=σ020+n2=σ02n12n1 -
第一组的0 1 2
σ ( 1 , 0 ) = σ 0 2 1 + 0 n = 2 σ 0 σ ( 1 , 1 ) = σ 0 2 1 + 1 n = 2 σ 0 2 1 n σ ( 1 , 2 ) = σ 0 2 1 + 2 n = 2 σ 0 2 1 n 2 1 n \begin{array}{c} \sigma(1,0)=\sigma_{0} 2^{1+\frac{0}{n}}=2 \sigma_{0} \\ \sigma(1,1)=\sigma_{0} 2^{1+\frac{1}{n}}=2 \sigma_{0} 2^{\frac{1}{n}} \\ \sigma(1,2)=\sigma_{0} 2^{1+\frac{2}{n}}=2 \sigma_{0} 2^{\frac{1}{n}} 2^{\frac{1}{n}} \end{array} σ(1,0)=σ021+n0=2σ0σ(1,1)=σ021+n1=2σ02n1σ(1,2)=σ021+n2=2σ02n12n1
- 第二组的0 1 2
σ ( 2 , 0 ) = σ 0 2 2 + 0 S = 4 σ 0 σ ( 2 , 1 ) = σ 0 2 2 + 1 n = 4 σ 0 2 1 n σ ( 2 , 2 ) = σ 0 2 2 + 2 n = 4 σ 0 2 1 n 2 1 n \begin{array}{c} \sigma(2,0)=\sigma_{0} 2^{2+\frac{0}{S}}=4 \sigma_{0} \\ \sigma(2,1)=\sigma_{0} 2^{2+\frac{1}{n}}=4 \sigma_{0} 2^{\frac{1}{n}} \\ \sigma(2,2)=\sigma_{0} 2^{2+\frac{2}{n}}=4 \sigma_{0} 2^{\frac{1}{n}} 2^{\frac{1}{n}} \end{array} σ(2,0)=σ022+S0=4σ0σ(2,1)=σ022+n1=4σ02n1σ(2,2)=σ022+n2=4σ02n12n1
由上述计算,我们知道
- 每一组内,相邻层之间的高斯模糊系统相差 2的1 / n
这里我个人理解的原因是应为高斯函数可以融合的性质导致的,每一次融合的次数不断的减小就可以达到相同的效果了
- 第0组第0层,第1组第第0层,第2组第0层,…,的高斯模糊系数分别为σ0 , 2σ0 , 4σ0 , . . . .
之后的依次类推就可以得到最开始的高斯金字塔的示意图了。
利用LoG(高斯拉普拉斯方法),即图像的二阶导数,可以在不同的尺度下检测图像的关键点信息,从而确定图像的特征点。但LoG的计算量大,效率低。所以我们通过两个相邻高斯尺度空间的图像的相减,得到DoG(高斯差分)来近似LoG。
高斯差分金字塔
为了计算DoG我们构建高斯差分金字塔,该金字塔是在上述的高斯金字塔的基础上构建而成的,建立过程是:在高斯金字塔中每个Octave中相邻两层相减就构成了高斯差分金字塔。如下图所示
每一组有n层得到n-1
我们通过这个图就可以大体上看出这个高斯金字塔的作用究竟是做什么了?
在DoG 搞定之后,就可以在不同的尺度空间中搜索局部最大值了。对于图像中的一个像素点而言,它需要与自己周围的8邻域,以及尺度空间中上下两层中的相邻的18(2x9)个点相比。如果是局部最大值,它就可能是一个关键点。基本上来说关键点是图像在相应尺度空间中的最好代表。如下图所示:
关键点定位
由于DoG对噪声和边缘比较敏感,因此在上面高斯差分金字塔中检测到的局部极值点需经过进一步的检验才能精确定位为特征点。
使用尺度空间的泰勒级数展开来获得极值的准确位置, 如果极值点的 灰度值小于阈值 (一般为0.03或0.04)就会被忽略掉。 在 OpenCV 中这种阈值被称为 contrast Threshold。
关键点方向的确定
经过上述两个步骤,图像的关键点就完全找到了,这些关键点具有尺度不变性。为了实现旋转不变性,还需要为每个关键点分配一个方向角度,也就是根据检测到的关键点所在高斯尺度图像的邻域结构中求得一个方向基准。
对于任一关键点,我们采集其所在高斯金字塔图像以r为半径的区域内所有像素的梯度特征(幅值和幅角),半径为:
r
=
3
×
1.5
σ
r=3 \times 1.5 \sigma
r=3×1.5σ
其中σ是关键点所在octave的图像的尺度,可以得到对应的尺度图像。
梯度的模值和方向如下:
m ( x , y ) = ( L ( x + 1 , y ) − L ( x − 1 , y ) 2 + ( L ( x , y + 1 ) − L ( x , y − 1 ) ) 2 θ ( x , y ) = arctan ( L ( x , y + 1 ) − L ( x , y − 1 ) L ( x + 1 , y ) − L ( x − 1 ) , y ) \begin{array}{c} m(x, y)=\sqrt{\left(L(x+1, y)-L(x-1, y)^{2}+(L(x, y+1)-L(x, y-1))^{2}\right.} \\ \theta(x, y)=\arctan \left(\frac{L(x, y+1)-L(x, y-1)}{L(x+1, y)-L(x-1), y}\right) \end{array} m(x,y)=(L(x+1,y)−L(x−1,y)2+(L(x,y+1)−L(x,y−1))2θ(x,y)=arctan(L(x+1,y)−L(x−1),yL(x,y+1)−L(x,y−1))
采用梯度直方图统计法,统计以关键点为原点,一定区域内的图像像素点确定关键点方向。在完成关键点的梯度计算后,使用直方图统计邻域内像素的梯度和方向。梯度直方图将0~360度的方向范围分为36个柱,其中每柱10度。如下图所示,直方图的峰值方向代表了关键点的主方向,方向直方图的峰值则代表了该特征点处邻域梯度的方向,以直方图中最大值作为该关键点的主方向。为了增强匹配的鲁棒性,只保留峰值大于主方向峰值80%的方向作为该关键点的辅方向。
一般为36个方向,简单起见我们这里定义了8个方向来进行描述
m ( x , y ) = m ( x y ) ∗ G ( x , y , 1. 5 σ \begin{array}{l} \begin{array}{l} \mathrm{m}(\mathrm{x}, \mathrm{y})=\mathrm{m}(\mathrm{x} \\ \mathrm{y}) * \mathrm{G}(\mathrm{x}, \mathrm{y}, 1 . \end{array}\\ 5 \sigma \end{array} m(x,y)=m(xy)∗G(x,y,1.5σ
可以有一个主方向和多个辅方向来组成。
获得图像关键点主方向后,每个关键点有三个信息(x,y,0,θ):位置、尺度、方向。由此我们可以确定一个SIFT特征区域。通常使用一个带箭头的圆或直接使用箭头表示SIFT区域的三个值:中心表示特征点位置,半径表示关键点尺度,箭头表示方向。如下图所示:
关键点描述
上述过程,只是找到关键点并确定了其方向,但SIFT算法核心用途在于图像的匹配,我们需要对关键点进行数学层面的特征描述,也就是构建关键点描述符.
通过以上步骤,每个关键点就被分配了位置,尺度和方向信息。接下来我们为每个关键点建立一个描述符
,该描述符
既具有可区分性,又具有对某些变量的不变性
,如光照,视角等。而且描述符不仅仅包含关键点
,也包括关键点周围对其有贡献的的像素点
。主要思路就是通过将键点周围图像区域分块,计算块内的梯度直方图
,生成具有特征向量
,对图像信息进行抽象。
核心: 主要思路就是通过将键点周围图像区域分块,计算块内的
梯度直方图
,成具有特征向量
,对图像信息进行抽象。
描述符与特征点所在的尺度有关,所以我们在关键点所在的高斯尺度图像上生成对应的描述符。以特征点为中心,将其附近邻域划分为d* d个子区域(一般取d=4),每个子区域都是一个正方形,边长为3o,考虑到
实际计算时,需进行三次线性插值,所以特征点邻域的为3o(d+ 1*3o(d+1)的范围,如下图所示:
为了保证特征点的旋转不变性如下图所示:旋转为关键点的主方向。
计算子区域内的像素的梯度,并按照o=0.5d进行高斯加权,然后插值计算得到每个种子点的八个方向的梯度,插值方法如下图所示。
weight
=
w
∗
d
r
k
(
1
−
d
r
)
(
1
−
k
)
d
c
m
(
1
−
d
c
)
1
−
m
d
o
n
(
1
−
d
o
)
1
−
n
\text { weight }=w * d r^{k}(1-d r)^{(1-k)} d c^{m}(1-d c)^{1-m} d o^{n}(1-d o)^{1-n}
weight =w∗drk(1−dr)(1−k)dcm(1−dc)1−mdon(1−do)1−n
总结:
SIFT在图像的不变特征提取方面拥有无与伦比的优势,但并不完美,仍然存在实时性不高,有时特征点较少,对边缘光滑的目标无法准确提取特征点等缺陷,自SIFT算法问世以来,人们就一直对其进行优化和改进,其中最著名的就是SURF算法。