import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
MIN_MATCH_COUNT = 10 # 设置最小的匹配点
img1 = cv.imread('./data/box.png',0) # 都读入原始的图片
img2 = cv.imread('./data/box_in_scene.png',0) # 读入需要查询的图片
## 计算特征和描述
sift = cv.xfeatures2d.SIFT_create() # 创建SIFT检测器
kp1, des1 = sift.detectAndCompute(img1,None) # 提取特征
kp2, des2 = sift.detectAndCompute(img2,None) # 提取特征
# 匹配
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) # 选择匹配的算法
search_params = dict(checks = 50)
flann = cv.FlannBasedMatcher(index_params, search_params) # 初始化比对模型
matches = flann.knnMatch(des1,des2,k=2) #进行比对,函数返回一个训练集和询问集的一致性列表
good = [] # 存储相似的点
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
if len(good)>MIN_MATCH_COUNT: # 如果特征点数量大于阈值
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,2) # 原始图片像素点
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,2) # 目标函数像素点
M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC,5.0) #M是转换矩阵,mask是匹配的特征点
matchesMask = mask.ravel().tolist() # 相同像素
h,w = img1.shape # 原图的形状
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) # 获得四个角的像素点
dst = cv.perspectiveTransform(pts,M) # 将原图的四个角的坐标点转换为匹配图的坐标点
img2 = cv.polylines(img2,[np.int32(dst)],True,255,3, cv.LINE_AA) # 画出原图和匹配图的关系
plt.imshow(img2, 'gray'), plt.show()
else:
print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
matchesMask = None
draw_params = dict(matchColor = (0,255,0), # 使用绿线作图
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
img3 = cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3, 'gray'),plt.show()
参考文献:
https://docs.opencv.org/3.4.3/d1/de0/tutorial_py_feature_homography.html