尺度不变特征变换(Scale-Invariant Feature Transform,SIFT)是用于图像处理领域的一种描述,是一种局部特征描述子,具有尺度不变性,可在图像中检测出关键点。
SIFT算法是用于提取图像局部特征的经典算法,其实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。
SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换(Affine Transformation)和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。
OpenCV内置了SIFT算法的诸多函数,包括:
- 实例化SIFT类的函数:
cv2.xfeatures2d.SIFT_create() - 在图像中查找关键点的函数:
sift.detect(gray, None) - 计算找到的关键点的描述符的函数:
sift.compute(kp) - 在图中画出关键点的函数:
cv2.drawKeypoints(gray, kp, img)
基于SIFT算法的图像特征检测:
import cv2
import numpy as np
'''
OpenCV2.4.13中没有drawMatchesKnn()函数,你需要从 https://github.com/opencv/opencv/blob/4.x/samples/python/ 中下载common.py和find_obj.py两个文件到当前程序所在的目录
'''
from find_obj import filter_matches,explore_match
from matplotlib import pyplot as plt
def getSift():
'''
定义函数用于获取并查看SIFT特征
'''
img_path1 = "C:\\Users\\libei\\Pictures\\e.jpg"
#读取图像
img = cv2.imread(img_path1)
#将其转换为灰度图像
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#创建SIFT的类
sift = cv2.xfeatures2d.SIFT_create()
#在图像中找到关键点
kp = sift.detect(gray,None)
#Keypoint数据类型分析
print(kp[0].pt)
#计算每个关键点的SIFT特征
des = sift.compute(gray,kp)
print(type(kp),type(des))
#des[0]为关键点的list,des[1]为特征向量的矩阵
print (type(des[0]), type(des[1]))
print (des[0],des[1])
print (des[1].shape)
#在灰度图像中画出这些关键点
img=cv2.drawKeypoints(gray,kp,np.array([]),(255,0,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
plt.imshow(img)
plt.show()
if __name__ == '__main__':
getSift()
输出结果如图所示

接着将两幅图像中的SIFT特征值进行匹配
import cv2
from matplotlib import pyplot as plt
img1 = cv2.imread("C:\\Users\\libei\\Pictures\\test.jpg",0) #载入第1幅测试图像
img2 = cv2.imread("C:\\Users\\libei\\Pictures\\e.jpg",0) #载入第2幅测试图像
# 初始化SIFT检测器
sift=cv2.xfeatures2d.SIFT_create()
# 通过SIFT检测器找到关键点kp和描述子des
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# 蛮力匹配算法,有两个参数,距离度量(L2(default),L1),是否交叉匹配(默认为false)
bf = cv2.BFMatcher()
#返回k个最佳匹配
matches = bf.knnMatch(des1,des2,k=2)
'''
OpenCV3.0的drawMatchesKnn()函数
比值测试,首先获取与A距离最近的点B(最近)和C(次近),只有当B/C小于阈值(示例中为0.75)时才被认为是匹配,
因为假设匹配是一一对应的,真正匹配的理想距离为0
'''
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good[:10], None,flags=2)
plt.axis('off')
plt.imshow(img3)
#plt.savefig('test1.jpg', dpi=300)
plt.show()
输出结果如图所示

其中的连线代表左边小图与右边小图之间SIFT特征可以匹配的图像点。

2511

被折叠的 条评论
为什么被折叠?



