如题。具体算法不是很懂,但起码会用
以下源码为我根据各地的文章自己修修改改得到的,想要详细数据可以把注释里的print()
都放出来
import cv2
import matplotlib.pyplot as plt
import numpy as np
import glob
import re
def detect(image):
# 创建SIFT生成器
# descriptor是一个对象,这里使用的是SIFT算法
# 由于检查出来的特征点较多,这里选取最优的2000个
descriptor = cv2.SIFT_create(nfeatures=2000)
# 检测特征点及其描述子(128维向量)
kps, features = descriptor.detectAndCompute(image, None)
return (kps,features)
def match_keypoints(kps_left, kps_right, features_left, features_right, ratio, threshold, k=50):
# 建立暴力匹配器
matcher = cv2.DescriptorMatcher_create("BruteForce")
# 使用knn检测,匹配left,right图的特征点
raw_matches = matcher.knnMatch(features_left, features_right, 2)
#print(len(raw_matches))
# 筛选匹配点 方法二 最优排序,选前k个
matches_list = list(raw_matches)
matches_list.sort(key=lambda m: (m[0].distance / m[1].distance))
good = [[m[0]] for m in matches_list[:k]]
matches = [(m[0].queryIdx, m[0].trainIdx) for m in matches_list[:k]]
# end
# 特征点对数大于4就够用来构建变换矩阵
kps_left = np.float32([kp.pt for kp in kps_left])
kps_right = np.float32([kp.pt for kp in kps_right])
#print("特征点对数", len(matches))
if len(matches) > 4:
# 获取匹配点坐标
pts_left = np.float32([kps_left[i] for (i, _) in matches])
pts_right = np.float32([kps_right[i] for (_, i) in matches])
diff_list1=[]
diff_list2 = []
for i in range(len(pts_left)):
diff_list1.append(pts_left[i][0] - pts_right[i][0])
diff_list2.append(pts_left[i][1] - pts_right[i][1])
res=0
for i in range(len(diff_list1)):
res+=diff_list1[i]
if max(diff_list1)-min(diff_list1)>100 or max(diff_list2) - min(diff_list2)>100:
#print('匹配失败')
return None
#print("水平位移距离范围", min(diff_list1), '~', max(diff_list1))
x = res / len(diff_list1)
#print("水平位移均值",x)
#print("误差范围",max(diff_list1)-min(diff_list1))
res = 0
for i in range(len(diff_list2)):
res += diff_list2[i]
#print("竖直位移距离范围", min(diff_list2), '~', max(diff_list2))
y=res / len(diff_list2)
#print("竖直位移均值", y)
#print("误差范围", max(diff_list2) - min(diff_list2))
#print()
# 计算变换矩阵(采用ransac算法从pts中选择一部分点)
H, status = cv2.findHomography(pts_right, pts_left, cv2.RANSAC, threshold)
return x,y
#return (matches, H, good)
return None
def extract_and_sort(path):
# 使用正则表达式提取路径中的数字部分
match = re.search(r'\[(\d+)\]', path)
if match:
number = int(match.group(1)) # 将提取的数字部分转换为整数
return number
return 0 # 如果路径中没有找到数字,默认返回0
# 根据数字部分排序路径列表
if __name__ == '__main__':
img_left = cv2.imread(r"图0", 1)
img_left = cv2.cvtColor(img_left, cv2.COLOR_BGR2RGB)
height, width = img_left.shape[:2]
img_left = img_left[50:height - 100, :]
img_right = cv2.imread(r"图1", 1)
img_right = cv2.cvtColor(img_right, cv2.COLOR_BGR2RGB)
height, width = img_right.shape[:2]
img_right = img_right[50:height - 100, :]
kps_left, features_left = detect(img_left)
kps_right, features_right = detect(img_right)
x, y = match_keypoints(kps_left, kps_right, features_left, features_right, 0.5, 0.99)
print(x,y)