1、SIFT描述子介绍
1.1 SIFT描述子定义
SIFT的全称是Scale Invariant Feature Transform,尺度不变特征变换,由加拿大教授David G.Lowe提出的。SIFT特征对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征。
1.2 SIFT特征
1、图像的局部特征,对旋转、尺度缩放、亮度变化保持不变,对视角变化、仿射变换、噪声也保持一定程度的稳定性。
2、独特性好,信息量丰富,适用于海量特征库进行快速、准确的匹配。
3、 多量性,即使是很少几个物体也可以产生大量的SIFT特征
4、高速性,经优化的SIFT匹配算法甚至可以达到实时性
5、 扩招性,可以很方便的与其他的特征向量进行联合。
1.3 SIFT检测过程
1.构造高斯差分空间图像。
2.寻找极大极小值点
3.精确定位极值点
4.选取特征点主方向
5. 构造特征点描述算子。
1.4算法介绍
1.尺度空间极值检测——即找特征点
对于二维图像I(x,y),建立图像的DOG (difference of guassians,即高斯差分)金字塔,DOG尺度空间含义为:可以用一个尺度空间的高斯函数和图像的卷积来表示。
G为尺度可变的高斯函数,***I***为空间坐标,其中西伽马为尺度。
为确定特征点所在的位置,首先需要建立一个高斯金字塔。
得到高斯金字塔后,再通过两个相邻的高斯尺度空间做差,得到高斯差分DOC金字塔,整个过程的公式如下:
高斯差分金字塔建立后,特征点就是DOG尺度空间众多极值点,(个人认为对其进行求偏导数即可得到特征点的位置坐标),查找该极值点需要把每个点与邻域内的周围的26个点进行比较,这些点包括,在同一尺度上相邻的8个点,以及相邻尺度上相邻的18个点。
2.特征点的尺度方向的确定
得到了特征点的坐标是完全不够的,必须要增加方向尺度信息。
· 采用有限差分的方法,求出在以特征点为圆心,以3倍西伽马为半径的范围内的图像梯度的幅值和相位。
· 利用直方图统计方法,求助邻域内所有像素点的梯度方向以及幅值。特征点的主方向就是直方图的峰值所代表的方向,确定了主方向就可以使SIFT算法具备旋转不变性。
3.特征向量的生成
特征向量最终是通过求得的特征点的邻域梯度信息来计算的。
· 先把坐标轴位置旋转到特征点所在的主方向上
· 接着以特征点为圆心,选择特征点附近的16个点作为种子点,分别求出8个方向上的梯度大小
· 最后得到的128维向量即为所求的特征向量
4.特征点的匹配
通常采用最邻近的方法,即查找每一个特征点在另外一副图像中的最邻近,即最短的欧式距离。
欧式距离的含义就是:两点连线的距离长度
具体如下:
对目标图像A中的某个特征点,求出该点与图像B中的所有特征点的特征向量的欧式距离;
· 将所求得的欧式距离值的大小进行排序;
· 找出最小的和次小(倒数第二小的)欧式距离值对于的目标图B中的特征点,并对这两个距离的比值进行计算;
· 假设该比值小于某个阈值,则这两个点为匹配点,否则不匹配。
(注:该阈值是一个经验阈值:是影响误匹配的主要原因,实验中一般选取的阈值大小是0.6左右)
2、数据集准备
由于疫情原因,拍摄了家里及周围的场景共15张作为本次实验的数据集
3、图片的SIFT特征提取并展示特征点
3.1 代码实现
# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from PCV.localdescriptors import sift
from PCV.localdescriptors import harris
# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
imname = r'C:\Users\13799\PycharmProjects\untitled1\pic\4.jpg'
im = array(Image.open(imname).convert('L'))
sift.process_image(imname, 'empire.sift')
l1, d1 = sift.read_features_from_file('empire.sift')
figure()
gray()
subplot(131)
sift.plot_features(im, l1, circle=False)
title(u'SIFT特征',fontproperties=font)
subplot(132)
sift.plot_features(im, l1, circle=True)
title(u'用圆圈表示SIFT特征尺度',fontproperties=font)
# 检测harris角点
harrisim = harris.compute_harris_response(im)
subplot(133)
filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
imshow(im)
plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
axis('off')
title(u'Harris角点',fontproperties=font)
show()
3.2 结果展示