基于SIFT的图像配准(图片偏移测量)

如题。具体算法不是很懂,但起码会用

以下源码为我根据各地的文章自己修修改改得到的,想要详细数据可以把注释里的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)

点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注