1、SIFT算法简介
SIFT算法又叫尺度不变特征变换,是用于图像处理领域的一种描述方式。这种描述具有尺度不变性,可以在图像中检测处关键点,是一种局部特征描述子。
SIFT特点:
- SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性;
- SIFT特征在应对视角变化、仿射变换、噪声也具有较好的稳定性;
- 特征描述表达的信息量高,有比较大的区分度,能够在大量的特征数据中有更准确的匹配。
- sift 提取特征点数目多,不容易产生提取不到特征点的情况
- sift 速度相对较快,优化后的sift,可以达到实时级的要求。
- 可扩展性高,sift最后提出的是特征向量,可以很方便的与其他形式的特征向量进行联合。
2、SIFT详细流程
参考网址:
2.1 图像金字塔
构建高斯金字塔和高斯差分金字塔。高斯核是唯一的线性核。高斯卷积核的核函数如下:
在sift算法中,σ 取1.6。
2.1.1 构建高斯金字塔
首先使用线性插值,将原图的长和宽变为原来的二倍,这是第一张图片,自己一行的那一张。这个步骤可要可不要,不是必须的。
随后使用高斯卷积模糊该图片,下图中的橙色箭头所示。接下来是一系列标准差递增的进一步卷积操作,更右边的每张图片都是其左邻图片卷积的结果,如绿色箭头所示。
最后对每行的倒数第三张图像进行下采样,如下图蓝色箭头。
我们现在构建的称为尺度空间。这样做的目的是模拟不同的观察尺度(当您在表格中进一步向下移动时)并抑制精细尺度结构(当您向右移动时)。
如上图,我们将得到4组金字塔(共有4行),每组有6个尺度(共有6列)。接下来我们构造高斯差分金字塔。高斯差分金字塔是由高斯金字塔两两相减得到的,对每一组金字塔,两两相减,得到高斯差分金字塔。我们一共可以得到4组高斯差分金字塔,每组有5张图像。
2.2 极值点定位
2.2.1 局部极值点
关键点是由DoG空间的局部极值点组成的,关键点的初步探查是通过同一组内各DoG相邻两
层图像之间比较完成的。每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度域
的相邻点大或者小。因此检测点所需要比较的点共26个点,分别为同尺度的8邻域内的点,和上下
相邻尺度对应的9*2个点。
我们发现的极值标记如下。(有些用黄色圆圈标记。这些确实是极值,但它们的绝对值非常小,以至于我们在继续之前会丢弃它们。该算法假设这些极值可能只是由于图像噪声而存在。
2.2.2 极值点微调
到目前为止我们发现的极值当然会有离散的坐标。我们现在尝试优化这些坐标。这是通过近似尺度空间函数的二次泰勒展开并计算其极值来完成的(对于每个极值)。(梯度和黑森是使用有限差值近似的。这是一个迭代过程,要么我们能够优化位置,要么我们在几个步骤后放弃并放弃该点。
2.3 计算描述子
如果可能,该算法现在会为剩余的每个关键点分配其参考方向。 粗略地说,我们观察到直接邻域中的所有梯度 这样的点,看看他们中的许多人是否具有大致相同的方向。
(技术细节如下:对于关键点周围方形斑块中的每个像素,我们使用有限差分近似梯度。回想一下,梯度点在最大增加的方向上,其大小是该方向上的斜率。从 0 到 360 度的间隔被划分为固定数量的条柱(默认为 36 个),梯度方向所属的条柱的值在乘以高斯权重后按梯度的大小递增。后者是为了减少更远像素的贡献。然后对生成的直方图(即箱列表)进行平滑处理 通过重复的框模糊。最后,如果该直方图的值超过某个阈值,则识别并选择该直方图的极值。然后计算为直方图极值的二次插值及其两个相邻箱中的值的最大值,从而计算出参考方向的更好近似值。
图像边框附近没有足够的相邻像素来计算参考方向的关键点将被丢弃。没有主导方向的关键点也被丢弃。另一方面,具有多个主导方向的关键点可能会在接下来的步骤中出现多次,即每个方向一次。
3、调库代码示例
代码如下:
import cv2
img = cv2.imread("1.jpg")
sift = cv2.SIFT.create()
kp,des = sift.detectAndCompute(img,None)
cv2.drawKeypoints(img, kp, img, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("sift",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.1 匹配方法
Opencv中关键点匹配的方法有两种match的方式:
- BFMatcher (Brute-Force matcher)暴力法
- FlannBasedMatcher (Flann-based matcher) 使用快速近似最近邻搜索算法寻找(用快速的第三方库近似最近邻搜索算法)
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
matches = bf.match(descriptors1, descriptors2)
# 绘制匹配结果
match_image = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches, None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS,
matchColor=(0, 0, 255))
4、总结
sift算法在当时算力不够强大时,解决了很多的难题,优化的sift算法几乎可以做到实时检测出结果。sift后续的优化还有surf和PCA-SIFT。
SIFT | SURF | |
---|---|---|
特征点检测 | 用不同尺度的图片与高斯函数做卷积 | 用不同大小的box filter与原始图像(integral image)做卷积,易于并行 |
方向 | 特征点邻接矩形区域内,利用梯度直方图计算 | 特征点邻接圆域内,计算x、y方向上的Haar小波响应 |
描述符生成 | 20*20(单位为pixel)区域划分为4*4(或2*2)的子区域,每个子域计算8bin直方图 | 20*20(单位为sigma)区域划分为4*4子域,每个子域计算5*5个采样点的Haar小波响 应,记录∑dx, ∑dy, ∑|dx|,∑|dy|。 |
下面是几种算法的优缺点性能比较:
method | Time | Scale | Rotation | Blur | Illumination | Affine |
---|---|---|---|---|---|---|
SIFT | common | best | best | common | common | good |
PCA-SIFT | good | good | good | best | good | best |
SURF | best | common | common | good | best | good |