
在 OpenCV 中,坐标还原通常指将经过变换(如旋转、缩放、仿射/透视变换)后的图像中的坐标点,反向映射回原始图像中的对应位置。这在目标检测、图像配准、几何校正等场景中非常关键。
坐标还原本质是 逆变换。若对图像应用了某种变换矩阵 ( M ),则还原坐标需使用其逆矩阵 ( M^{-1} )。
仿射变换(如旋转、平移、缩放)使用 2x3 矩阵,可通过计算逆矩阵还原坐标。
cv2.invertAffineTransform(M) 直接计算仿射矩阵的逆矩阵。cv2.transform() 或手动矩阵乘法还原坐标。import cv2
import numpy as np
# 原图尺寸
h, w = 400, 600
# 定义仿射变换矩阵(旋转45度)
center = (w//2, h//2)
M = cv2.getRotationMatrix2D(center, angle=45, scale=1.0)
# 变换后的图像
rotated = cv2.warpAffine(img, M, (w, h))
# 计算逆矩阵
M_inv = cv2.invertAffineTransform(M)
# 假设变换后图像中的点 (x_dst, y_dst)
x_dst, y_dst = 100, 200
# 还原到原图坐标
src_point = np.array([[x_dst, y_dst]], dtype=np.float32)
restored_point = cv2.transform(src_point.reshape(1, -1, 2), M_inv).squeeze()
print(f"变换后坐标: ({x_dst}, {y_dst}) -> 原图坐标: {restored_point}")透视变换(如投影校正)使用 3x3 矩阵,需计算逆矩阵或使用 cv2.perspectiveTransform()。
np.linalg.inv(M) 计算透视变换矩阵的逆矩阵 ( M^{-1} )。cv2.perspectiveTransform() 处理齐次坐标。# 定义透视变换矩阵(假设已通过cv2.getPerspectiveTransform获取)
M_perspective = cv2.getPerspectiveTransform(src_pts, dst_pts)
# 变换后的图像
warped = cv2.warpPerspective(img, M_perspective, (w, h))
# 计算逆矩阵
M_perspective_inv = np.linalg.inv(M_perspective)
# 变换后图像中的点 (x_dst, y_dst)
x_dst, y_dst = 150, 300
# 齐次坐标转换
dst_point = np.array([[[x_dst, y_dst]]], dtype=np.float32)
restored_point = cv2.perspectiveTransform(dst_point, M_perspective_inv).squeeze()
print(f"变换后坐标: ({x_dst}, {y_dst}) -> 原图坐标: {restored_point}")若操作仅涉及图像裁剪(ROI),坐标还原只需 平移操作。
# 定义ROI区域 (x, y, width, height)
roi_x, roi_y, roi_w, roi_h = 100, 50, 200, 150
roi = img[roi_y:roi_y+roi_h, roi_x:roi_x+roi_w]
# 在ROI中检测到点的局部坐标 (x_local, y_local)
x_local, y_local = 30, 40
# 还原到原图全局坐标
x_global = roi_x + x_local
y_global = roi_y + y_local
print(f"ROI坐标: ({x_local}, {y_local}) -> 原图坐标: ({x_global}, {y_global})")矩阵可逆性:
浮点精度误差: 还原后的坐标可能为浮点数,需根据需求决定是否取整。
边界处理: 若变换后坐标超出原图范围,需进行有效性检查:
if (0 <= x_restored < w) and (0 <= y_restored < h):
# 坐标有效
else:
# 坐标越界齐次坐标: 透视变换需使用齐次坐标(三维向量),还原后需归一化:
restored_point_homogeneous = np.dot(M_inv, [x_dst, y_dst, 1])
x_restored = restored_point_homogeneous[0] / restored_point_homogeneous[2]
y_restored = restored_point_homogeneous[1] / restored_point_homogeneous[2]场景:在旋转后的图像中检测目标框,还原坐标到原图。
# 旋转图像
M = cv2.getRotationMatrix2D((w//2, h//2), 30, 1.0)
rotated = cv2.warpAffine(img, M, (w, h))
# 在旋转后的图像中检测目标框 (x1, y1, x2, y2)
box_rotated = [50, 80, 200, 300]
# 还原四个顶点坐标
points_dst = np.array([
[box_rotated[0], box_rotated[1]],
[box_rotated[2], box_rotated[1]],
[box_rotated[2], box_rotated[3]],
[box_rotated[0], box_rotated[3]]
], dtype=np.float32)
M_inv = cv2.invertAffineTransform(M)
points_src = cv2.transform(points_dst.reshape(1, -1, 2), M_inv).squeeze()
# 在原图中绘制还原后的框
cv2.polylines(img, [points_src.astype(np.int32)], True, (0, 255, 0), 2)
cv2.imshow('Restored Box', img)
cv2.waitKey(0)变换类型 | 核心方法 | 关键函数 | 适用场景 |
|---|---|---|---|
仿射变换 | 计算逆仿射矩阵 | cv2.invertAffineTransform() | 旋转、平移、缩放 |
透视变换 | 计算逆透视矩阵 + 齐次坐标归一化 | cv2.perspectiveTransform() | 投影校正、视角变换 |
ROI | 直接平移坐标 | 无 | 图像裁剪后的坐标映射 |
掌握坐标还原技术能有效提升图像处理流程的灵活性,尤其在需要跨变换空间传递信息的任务中(如目标跟踪、增强现实)。