SIFT 特征点提取

SIFT 是一种从图像中提取独特不变特征的方法,其特点为基于图像的一些局部特征,而与图像整体的大小和旋转无关。并且该方法对于光照、噪声、仿射变换具有一定鲁棒性,同时能生成大量的特征点。

SIFT 的具体步骤

  • 尺度空间极值检测: 使用差分高斯函数识别潜在的兴趣点
  • 特征点定位:剔除对比度不高和处于边界位置的特征点
  • 分配方向:计算特征点的方向用于下一步构建描述
  • 特征点描述:

尺度空间极值检测

尺度空间极值检测的作用就是发掘同一图像在不同尺度下都存在的特征点。通过对原始图像进行不断地降采样和平滑操作,生成一串不同尺度的图片,然后再找出每张图片都存在的特征点。

高斯尺度空间

作者在论文中提出,高斯核是唯一可以产生多尺度的核。对图像使用不同尺度空间因子(标准差)的高斯核进行卷积,能够得到不同模糊程度的图像,也就是将图像转换到高斯尺度空间。
sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python
其中,sift提取并保存点 python sift特征提取的步骤_差分_02 是高斯核函数:
sift提取并保存点 python sift特征提取的步骤_差分_03

而 $ * $ 代表卷积, sift提取并保存点 python sift特征提取的步骤_特征点_04 代表图像的高斯尺度空间。检测特征点的算子中较好的算子是高斯拉普拉斯算子 sift提取并保存点 python sift特征提取的步骤_特征点_05 ,但是其运算代价较大,故使用差分高斯(DoG, Difference of Gaussina)来近似替代。
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ D(x, y, \sigma…
在上述公式中, sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_06

高斯金字塔与高斯差分金字塔

为了从不同的空间尺度获取图片的特征点信息,首先要在同一图片大小上使用不同的高斯核进行卷积运算,再进行差分计算。然后再进行将图片降采样,到更小的尺度上再次进行高斯卷积运算,并同样进行差分计算。重复上述过程,即可得到高斯金字塔与高斯差分金字塔。


sift提取并保存点 python sift特征提取的步骤_特征点_07

DoG 空间极值检测

即找出差分金字塔中,每一层中每一个点的 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_08

sift提取并保存点 python sift特征提取的步骤_差分_09

参数取值

为了使每一层之间都只差一个比例因子 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_06 ,同时高斯金字塔下方一组的最上层和上方一组的最下层也只差一个比例因子 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_06 ,则设置
sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_12
则每一组的最上方一层的比例因子即为 sift提取并保存点 python sift特征提取的步骤_差分_13,直接让对这层进行降采样,即可得到下一组最下方一层的原始图片,如图所示:

sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_14

在 DoG 空间极值检测中可以发现,若最后指定需要寻找 sift提取并保存点 python sift特征提取的步骤_特征点_15 层的特征点,那么最上层与最下层由于在边缘,其邻域将会少一层。那么为了能够在这两层也能有完整的邻域,则高斯差分金字塔中每组都需要有 s+2 层,那么高斯金字塔则需要更多一层,即 sift提取并保存点 python sift特征提取的步骤_极值_16

sift提取并保存点 python sift特征提取的步骤_特征点_17

需要注意的是,由于在最后又添加了两层,所以向下一组进行下采样的不是最后一层,而是倒数第三层了。

那么一共需要多少组呢,由于第一组的图片是原始尺寸,但每组都会使图片的尺寸缩小一倍,且在极值检测时还需要考虑 3 × 3 的邻域,则最后一组的图片尺寸需要大于 3,则有:
sift提取并保存点 python sift特征提取的步骤_特征点_18
其中 sift提取并保存点 python sift特征提取的步骤_极值_19 表示组数,则对两侧求对数,即可得到 sift提取并保存点 python sift特征提取的步骤_极值_19

int(floor(log2(min(w, h) * 2 / 3)))

则对于一张尺寸为 sift提取并保存点 python sift特征提取的步骤_特征点_21

o = int(floor(log2(min(w, h) * 2 / 3)))		    # 组数
s = 3									     	# 极值检测层数,作者设定为 3
ipo = S + 3										# 每组的层数
sigma_0 = 1.6									# 高斯核方差基数,作者设定为1.6

特征点定位

特征点定位中包含了三个操作

  • 特征点真实坐标与真实值的计算
  • 低对比度特征点消除
  • 边缘效应消除

有限差分求导法

sift提取并保存点 python sift特征提取的步骤_特征点_22

sift提取并保存点 python sift特征提取的步骤_极值_23

sift提取并保存点 python sift特征提取的步骤_差分_24sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_25

特征点定位与低对比度特征点消除

使用DoG空间极值检测所得到的特征点坐标是离散的,并不是极值点真正的坐标。这里使用了泰勒展开公式,对极值点进行拟合。已知二阶展开的泰勒展开式为:
sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_26
现在使已得到的每个点为向量 sift提取并保存点 python sift特征提取的步骤_特征点_27 ,$\hat x $ 则为想要得到的极值的真实坐标,将泰勒展开改写为矩阵形式:
sift提取并保存点 python sift特征提取的步骤_差分_28
由于 sift提取并保存点 python sift特征提取的步骤_极值_29 处为极值,sift提取并保存点 python sift特征提取的步骤_特征点_30

sift提取并保存点 python sift特征提取的步骤_极值_31

则得到了极值点的坐标,接着将 $ \hat x - x_0$ 带入泰勒展开式即可得到:

sift提取并保存点 python sift特征提取的步骤_差分_32

显然 sift提取并保存点 python sift特征提取的步骤_特征点_33

通过以上方法,就可以得到该极值点的真实值,该点含义就是通过差分操作得到的邻域中最具有特征的点,该点的值可以理解为对比度。而不是每个极值都具有大的对比度,如白墙上的一个不那么白的点,虽然它是极值点,但是很容易受到噪声的影响,所以设定一个阈值 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_34,当 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_35

消除边缘效应

单纯地去除低对比度的点是不够的,考虑一条垂直的边界线,在横向上的变化很大,但是在纵向的变化却很小。这种点不能很好地反映特征,所以要把这些点给去除。去除的方法是使用黑塞矩阵,黑塞矩阵即为多元二阶导数矩阵,处于边缘的点特征值的比值较大,则特征值可以反应该点是否处于边缘 (此处不考虑 sift提取并保存点 python sift特征提取的步骤_特征点_36轴 )。
sift提取并保存点 python sift特征提取的步骤_差分_37
该黑塞矩阵有两个特征值 sift提取并保存点 python sift特征提取的步骤_极值_38 ,则有:
sift提取并保存点 python sift特征提取的步骤_差分_39
假设 sift提取并保存点 python sift特征提取的步骤_极值_40 ,同时 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_41 ,此处需要的就是 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_42 小于某个阈值,让两个特征值的比值不要太大,有
sift提取并保存点 python sift特征提取的步骤_特征点_43
当比值最小时,sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_44 ,则设置一个阈值,只要 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_42 小于这个阈值即可说明该点非边缘位置。由于 $\gamma $ 增大时,sift提取并保存点 python sift特征提取的步骤_特征点_46 也增大,则只需要观测当前黑塞矩阵的 sift提取并保存点 python sift特征提取的步骤_特征点_46 是否小于 sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_48 阈值时,sift提取并保存点 python sift特征提取的步骤_极值_49 的值即可,作者设置该阈值 sift提取并保存点 python sift特征提取的步骤_极值_50 ,即有效的特征点需要满足:
sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_51

分配方向

获得特征点后,需要根据特征点附近的数据,来给特征点分配方向。

sift提取并保存点 python sift特征提取的步骤_极值_52

如图,在高斯金字塔中,以特征点像素左上角坐标为中心,sift提取并保存点 python sift特征提取的步骤_差分_53 为边长,画出一个正方形,计算该正方形中每一个像素位置的梯度的方向角与幅值,计算公式如下:
sift提取并保存点 python sift特征提取的步骤_特征点_54

将每个点的角度和幅值计算出来以后,再将幅值乘以一个权值作为新的幅值,从而反应与特征点的远近关系,如图中蓝色圈。离圆心越远权值越小,离圆心越近,权值越大。该权值的计算公式为:
sift提取并保存点 python sift特征提取的步骤_极值_55
将每个点的幅值与该点对应的权值相乘得到新的幅值以后,就可以对这些点进行统计。统计的方式为,以这些点的角度作为横坐标,幅值与权值之积作为纵坐标。由于统计时角度是离散的。所以将角度分为 36 组,每 10° 为一组,如图:

sift提取并保存点 python sift特征提取的步骤_sift提取并保存点 python_56

图中仅分为了8组以供参考,实际操作过程中常分为 36 组。完成统计工作后,需要对统计的数据进行平滑操作,平滑操作的方法如公式:
sift提取并保存点 python sift特征提取的步骤_极值_57
接着就可以在统计的结果中,找到幅值之和最大的那个方向,这个方向就是该特征点的主方向。而其他方向中,所有大于主方向幅值之和 80% 的方向,被称为辅方向。具有辅方向的特征点约占 15% 左右,但这些点对于特征匹配的稳定性起到了很大的作用。对于这种具有辅方向的特征点,我们需要额外创建一个位置相同的特征点,而其梯度数据则是辅方向的角度与幅值。

最后还需要做的是,将离散的角度进行连续化,让最接近每个峰值的3个统计值拟合成抛物线,以插值出峰值位置以获得更好的精度。拟合公式为:
sift提取并保存点 python sift特征提取的步骤_极值_58
将得出的值还原到 360° 的尺度上,并更新特征点的角度信息,这一部分就完成了。

特征点描述