(一)SIFT算法分解为如下四步:
1.尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。
2.关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。
3.方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。
4.关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。
(二)OpenCV+Python实现
(SIFT算法是一个有专利的算法,在商业用途上是收费的。不过,在python当中使用SIFT算法和版本之间有不少关系,源文档当中使用opencv版本是2.4.9版本,此版本可以随意使用SIFT算法。但是,在opencv3当中就没那么幸运了,opencv中的很多特征点提取算法都和cv2中的库分离开,必须要添加opencv-contrib才可以使用,只要在VS的Python环境中pip install opencv-contrib-python即可。)
1.函数描述
算法分成了两步,第一步特征提取,第二步计算描述符:
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(img_gray, None)
2.程序代码
(1)只检测关键点并绘制:
import cv2
import numpy as np
img = cv2.imread('img.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#sift特征计算
sift = cv2.xfeatures2d.SIFT_create()
#detect方法找到关键点
kp,res = sift.detectAndCompute(gray,None)
#drawKeypoints方法绘制关键点
img=cv2.drawKeypoints(gray,kp,img)
cv2.imshow('Sift',img)
cv2.waitKey(0)
(2)提取sift特征并进行匹配:
import cv2
import numpy as np
img_orign = cv2.imread('img.jpg')
img=cv2.imread('img2.jpg')
rows,cols = img.shape[:2]
gray_orign= cv2.cvtColor(img_orign,cv2.COLOR_BGR2GRAY)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#SIFT特征计算
sift=cv2.xfeatures2d.SIFT_create()
# 蛮力匹配算法,有两个参数,距离度量(L2(default),L1),是否交叉匹配(默认false)
kp1, des1 = sift.detectAndCompute(gray_orign, None)
kp2, des2 = sift.detectAndCompute(gray, None)
#返回k个最佳匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < 0.5* n.distance:
good.append([m])
img3 = cv2.drawMatchesKnn(img_orign, kp1, img, kp2, good[:20], None, flags=2)
cv2.imshow('img',img3)
#等待按键按下
cv2.waitKey(0)
#清除所有窗口
cv2.destroyAllWindows()
注:
knnMatch(des1, des2,k=2) 函数执行特征点匹配, k = 2 定义基准图像上的一个点会在另一幅图像上有2个匹配结果。good是经过筛选的优质配对,如果2个配对中第一匹配的距离小于第二匹配的距离的0.5,基本可以说明这个第一配对是两幅图像中独特的,不重复的特征点。当然并不能保证good保留的就是最优匹配。OpenCV3中有drawMatchesKnn()函数,可以直接拼接显示配对点。