基于SIFT/ORB计算图像的旋转角度和缩放比例

计算图像间的旋转角度可以通过提取特征点、匹配特征点,然后用 OpenCV 的 estimateAffinePartial2D 函数来计算仿射变换矩阵。最后从该矩阵中提取旋转角度。

步骤

  1. 提取特征点和描述符:使用 SIFT 或 ORB 算法提取图像的特征点和描述符。

  2. 匹配特征点:使用 BFMatcher 或其他匹配算法匹配两幅图像的特征点。

  3. 计算仿射变换矩阵:使用 estimateAffinePartial2D 函数,从匹配的特征点对中计算部分仿射变换矩阵(允许旋转、平移和缩放)。

  4. 提取旋转角度:从仿射变换矩阵中提取旋转角度。

以下是完整的代码示例,分别使用 SIFT 和 ORB 特征:

使用 SIFT 特征

import cv2
import numpy as np

# 读取图像
image1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
image2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)

# 初始化 SIFT 特征检测器
sift = cv2.SIFT_create()

# 检测关键点并计算描述符
keypoints1, descriptors1 = sift.detectAndCompute(image1, None)
keypoints2, descriptors2 = sift.detectAndCompute(image2, None)

# 使用 BFMatcher 进行特征匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(descriptors1, descriptors2, k=2)

# 应用比率测试筛选匹配点
good_matches = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good_matches.append(m)

# 提取匹配点的坐标
src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 2)
dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 2)

# 计算部分仿射变换矩阵
affine_matrix, inliers = cv2.estimateAffinePartial2D(src_pts, dst_pts)

result_dict = {}
if affine_matrix is not None:
    # 提取旋转角度
    theta = np.arctan2(affine_matrix[1, 0], affine_matrix[0, 0]) * 180 / np.pi
    print("旋转角度为:{:.2f} 度".format(theta))

    # 计算缩放比例的大小
    if affine_matrix[0, 0] != 0:
        scale_x = np.sqrt(affine_matrix[0, 0] ** 2 + affine_matrix[0, 1] ** 2)
        scale_y = np.sqrt(affine_matrix[1, 0] ** 2 + affine_matrix[1, 1] ** 2)
        print("X 缩放比例为:{:.2f}".format(scale_x))
        print("Y 缩放比例为:{:.2f}".format(scale_y))
    else:
        print("无法计算缩放比例")
else:
    print("无法计算变换矩阵")

使用 ORB 特征

import cv2
import numpy as np

# 读取图像
image1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
image2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)

# 初始化 ORB 特征检测器
orb = cv2.ORB_create()

# 检测关键点并计算描述符
keypoints1, descriptors1 = orb.detectAndCompute(image1, None)
keypoints2, descriptors2 = orb.detectAndCompute(image2, None)

# 使用 BFMatcher 进行特征匹配
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(descriptors1, descriptors2)

# 按距离排序匹配结果并选择前 N 个最佳匹配
matches = sorted(matches, key=lambda x: x.distance)
good_matches = matches[:30]  # 选择前 30 个最佳匹配

# 提取匹配点的坐标
src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 2)
dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 2)

# 计算部分仿射变换矩阵
affine_matrix, inliers = cv2.estimateAffinePartial2D(src_pts, dst_pts)

result_dict = {}
if affine_matrix is not None:
    # 提取旋转角度
    theta = np.arctan2(affine_matrix[1, 0], affine_matrix[0, 0]) * 180 / np.pi
    print("旋转角度为:{:.2f} 度".format(theta))

    # 计算缩放比例的大小
    if affine_matrix[0, 0] != 0:
        scale_x = np.sqrt(affine_matrix[0, 0] ** 2 + affine_matrix[0, 1] ** 2)
        scale_y = np.sqrt(affine_matrix[1, 0] ** 2 + affine_matrix[1, 1] ** 2)
        print("X 缩放比例为:{:.2f}".format(scale_x))
        print("Y 缩放比例为:{:.2f}".format(scale_y))
    else:
        print("无法计算缩放比例")
else:
    print("无法计算变换矩阵")

注意事项

  • 特征匹配质量:特征匹配的质量会直接影响变换矩阵的准确性。确保图像中有足够的特征点可供匹配。

  • 旋转范围estimateAffinePartial2D 计算出的旋转角度会在 [-90, 90] 度范围内,如果实际旋转角度超过这个范围,可能需要进一步调整计算结果。

  • 性能考虑:SIFT 特征计算较为耗时,但对于复杂图像效果较好;ORB 特征计算速度快,适合实时应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值