SIFT (Scale Invariant Feature Transform) 算法,即尺度不变特征算法。
特点:该算法对图像存在的旋转、仿射变换,光照变化等能够保持不变性,对噪声的敏感度低,具有很强的鲁棒性。
缺点:
① 由于该算法主要是利用了所提取的特征点的局部邻域梯度信息,当待匹配图像中出现相似的部分时,此时会出现一 对多的现象。 (注:即A中一个特征点与B中多个相似的特征点进行了匹配)
② 此外,由于算法的原因,还存在较多的误匹配的点。
(注:针对这个问题,众多学者提出了改进了SIFT算法,**文献[1]**中提出,在进行SIFT算法之后,利用马氏距离进行二次特征点匹配,**文献[2]**中提出引入RANSAC算法进行剔除错误匹配点)
①尺度空间极值检测——即找特征点
对于二维图像***I***(x,y),建立图像的DOG (difference of guassians,即高斯差分)金字塔,DOG尺度空间含义为:可以用一个尺度空间的高斯函数和图像的卷积来表示。
G为尺度可变的高斯函数,***I***为空间坐标,其中西伽马为尺度。
为确定特征点所在的位置,首先需要建立一个高斯金字塔。具体可以参考文献。
得到高斯金字塔后,再通过两个相邻的高斯尺度空间做差,得到高斯差分DOC金字塔,整个过程的公式如下:
高斯差分金字塔建立后,特征点就是DOG尺度空间众多极值点,(个人认为对其进行求偏导数即可得到特征点的位置坐标),查找该极值点需要把每个点与邻域内的周围的26个点进行比较,这些点包括,在同一尺度上相邻的8个点,以及相邻尺度上相邻的18个点。
②特征点的尺度方向的确定
得到了特征点的坐标是完全不够的,必须要增加方向尺度信息。
④特征点的匹配
通常采用最邻近的方法,即查找每一个特征点在另外一副图像中的最邻近。即最短的欧式距离。
欧式距离的含义就是:两点连线的距离长度
具体如下:
主要引用**文献[3]中,源代码见文献[4]**中, (注:源代码链接见参考文献)
import cv2
from matplotlib import pyplot as plt
img1 = cv2.imread('box.png',0) # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2,k=2)
# Apply ratio test
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
# cv2.drawMatchesKnn expects list of lists as matches
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2)
plt.imshow(img3)
源代码如下图,见链接https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html#matcher
运行后结果如下图所示:
代码引用博客上我第一个认识的大神的代码,见文献[5]: (注:源代码链接见参考文献)
import cv2
imgpath = '5.jpg'
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(gray, None)
img = cv2.drawKeypoints(image=img, outImage=img, keypoints=keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
color=(51, 163, 236))
cv2.imshow('IMAGE', img)
while True:
if cv2.waitKey() & 0xff == ord('q'):
break
cv2.destroyAllWindows()
本文本想针对SIFT算法的误匹配问题,结合文献[6],介绍SIFT算法匹配后,引入RANSAC算法进行误匹配点的剔除过程。但是此部分的代码还没搞明白,明白后结合原理及代码再写。
[1]傅卫平,秦川,刘佳,杨世强,王雯. 基于SIFT算法的图像目标匹配与定位[J].仪器仪表学报,2011,32(01):163-169.
[2]完文韬,杨成禹. 改进的SIFT算法在图像特征点匹配中的应用[J].长春理工大学学报(自然科学 版),2018,41(01):44-47+52.
[3]1000sprites. 图像特征匹配总结[net].CSDN博客,2017,5,22:https://blog.csdn.net/ssw_1990/article/details/72629655.
[4]opencv. Feature Matching[net].https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html#goal.
[5]肥宅_Sean. SIFT角点检测(python)[net], CSDN博客,2018,7,25:https://blog.csdn.net/a19990412/article/details/81197354
[6]涂梅林,郭太良,林志贤.基于ORB特征的改进RANSAC匹配点提纯算法[J].有线电视技术,2018(08):18-22.