python 3.7.11
opencv3.4.2.16
import numpy as np import cv2 from matplotlib import pyplot as plt def img_match_first(src,dst): # sift特征提取 sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(src, None) kp2, des2 = sift.detectAndCompute(dst, None) # FLANN最近邻匹配 flann_index_kdtree = 0 index_params = dict(algorithm=flann_index_kdtree, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1, des2, k=2) # Lowe's ratio test 算法 good = [] for m, n in matches: if m.distance <0.7 * n.distance: good.append(m) print('第一次,ratioWithNoRansac', len(good) / len(matches)) inLiner = 0 if len(good) > 10: src_pts = np.float32([kp1[i.queryIdx].pt for i in good]).reshape(-1, 1, 2) #将所有好的匹配的对应点的坐标存储下来 dst_pts = np.float32([kp2[i.trainIdx].pt for i in good]).reshape(-1, 1, 2) #将所有好的匹配的对应点的坐标存储下来 ransacReprojThreshold = 10.0 M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, ransacReprojThreshold) #计算变化矩阵和mask matchesMask = mask.ravel().tolist() for i in range(len(matchesMask)): if matchesMask[i] == 1: inLiner += 1 ratio = inLiner / len(matchesMask) print('第一次,足够好的好点数量:', inLiner, '好点数量:', len(matchesMask), '匹配率:', ratio) imgOut = cv2.warpPerspective(dst, M, (src.shape[1],src.shape[0]),flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP) return imgOut else: return None def img_match_second(img1,img2): # sift特征提取 sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) # FLANN最近邻匹配 flann_index_kdtree = 0 index_params = dict(algorithm=flann_index_kdtree, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1, des2, k=2) # Lowe's ratio test 算法 good = [] for m, n in matches: if m.distance < 0.7 * n.distance: good.append(m) print('ratioWithNoRansac',len(good)/len(matches)) # ransac 随机抽样一直过滤 min_match_count = 10 # ransac阈值,期望匹配的好点最低数目 (根据项目判断) inLiner = 0 # 符合ransac算法变换矩阵的好点 if len(good) > min_match_count: src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2) # M: 3x3 变换矩阵. M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) matchesMask = mask.ravel().tolist() for i in range(len(matchesMask)): if matchesMask[i] == 1: inLiner += 1 ratio = inLiner / len(matchesMask) print('第二次,足够好的好点数量:', inLiner, '好点数量:', len(matchesMask), '匹配率:', ratio) h, w = img1.shape pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2) dst = cv2.perspectiveTransform(pts, M) img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA) plt.show() else: # 没有足够多的好点可以认为直接不匹配 print("第二次,好点匹配数量不够多 - %d/%d" % (len(good), min_match_count)) matchesMask = None if __name__ == "__main__": # 图片读取 img1 = cv2.imread('1.jpg', 0) img2 = cv2.imread('2.jpg', 0) img_match_second(img1, img_match_first(img1, img2))