如何以最简方式检测两张同尺寸(184,184)图像间的旋转角度?
检测两张184x184图像旋转角度的简便方法
不需要复杂的单应性分解,下面几个方法更易实现,结合NumPy、Pillow和轻量的计算机视觉工具就能完成:
方法一:傅里叶相位相关法
利用傅里叶变换的旋转不变性,频域的相位差直接对应空域的旋转角度,适合无缩放、平移的纯旋转场景:
- 用Pillow读取图像转为灰度图,再转NumPy数组
- 通过OpenCV的相位相关函数计算偏移量,推导旋转角度
代码示例:
from PIL import Image import numpy as np import cv2 # 读取图像并转为灰度NumPy数组 img1 = np.array(Image.open("图1.png").convert("L")) img2 = np.array(Image.open("图2.png").convert("L")) # 傅里叶相位相关计算 shift, _, _ = cv2.phaseCorrelate(np.float32(img1), np.float32(img2)) # 基于图像中心(92,92)计算旋转角度 angle = np.arctan2(shift[1], shift[0]) * (180 / np.pi) print(f"旋转角度:{angle:.2f}度")
方法二:ORB特征点匹配法
ORB是轻量的特征检测算法,无需复杂配置,通过匹配特征点计算旋转矩阵,提取角度:
- 读取图像转灰度数组,初始化ORB检测器
- 检测特征点并匹配,用匹配点计算旋转矩阵
- 从矩阵中提取旋转角度
代码示例:
from PIL import Image import numpy as np import cv2 # 读取图像转灰度数组 img1 = np.array(Image.open("图1.png").convert("L")) img2 = np.array(Image.open("图2.png").convert("L")) # 初始化ORB检测器并提取特征 orb = cv2.ORB_create(500) kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) # 匹配特征点 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = sorted(bf.match(des1, des2), key=lambda x: x.distance) # 提取匹配点坐标 src_pts = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) # 计算旋转矩阵并提取角度 M, _ = cv2.estimateAffinePartial2D(src_pts, dst_pts) angle = np.arctan2(M[1, 0], M[0, 0]) * (180 / np.pi) print(f"旋转角度:{angle:.2f}度")
方法三:图像互相关暴力匹配法
适合图像内容高度相似的场景,通过遍历旋转角度、计算互相关值找到最优解:
- 读取图像转灰度数组
- 遍历0-360度旋转目标图像,计算与参考图的互相关
- 互相关值最大的角度即为旋转角度
代码示例:
from PIL import Image import numpy as np def rotate_img(arr, angle): return np.array(Image.fromarray(arr).rotate(angle, expand=False)) # 读取图像转灰度数组 img1 = np.array(Image.open("图1.png").convert("L")) img2 = np.array(Image.open("图2.png").convert("L")) max_corr = -1 best_angle = 0 # 遍历角度(步长可根据精度调整) for angle in range(0, 360): rotated = rotate_img(img1, angle) corr = np.sum(rotated * img2) if corr > max_corr: max_corr = corr best_angle = angle print(f"旋转角度:{best_angle}度")
注意:方法三精度取决于遍历步长,步长越小精度越高但耗时越长;前两种方法精度更高、速度更快,优先推荐。
内容的提问来源于stack exchange,提问作者codequestion
相关产品推荐
相关产品推荐

