【OpenCV 中的坐标还原操作】仿射、透视、ROI

部署运行你感兴趣的模型镜像

在 OpenCV 中,坐标还原通常指将经过变换(如旋转、缩放、仿射/透视变换)后的图像中的坐标点,反向映射回原始图像中的对应位置。这在目标检测、图像配准、几何校正等场景中非常关键。


一、坐标还原的核心原理

坐标还原本质是 逆变换。若对图像应用了某种变换矩阵 ( M ),则还原坐标需使用其逆矩阵 ( M^{-1} )。

数学表示
  • 变换公式:( \text{dst}(x’, y’) = M \cdot \text{src}(x, y) )
  • 逆变换公式:( \text{src}(x, y) = M^{-1} \cdot \text{dst}(x’, y’) )

二、常见场景与实现方法

1. 仿射变换的坐标还原

仿射变换(如旋转、平移、缩放)使用 2x3 矩阵,可通过计算逆矩阵还原坐标。

步骤
  1. 生成逆变换矩阵
    OpenCV 提供 cv2.invertAffineTransform(M) 直接计算仿射矩阵的逆矩阵。
  2. 应用逆变换
    使用 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}")
2. 透视变换的坐标还原

透视变换(如投影校正)使用 3x3 矩阵,需计算逆矩阵或使用 cv2.perspectiveTransform()

步骤
  1. 生成逆矩阵
    使用 np.linalg.inv(M) 计算透视变换矩阵的逆矩阵 ( M^{-1} )。
  2. 应用逆变换
    使用 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}")
3. ROI(感兴趣区域)的坐标还原

若操作仅涉及图像裁剪(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})")

三、注意事项

  1. 矩阵可逆性

    • 仿射矩阵必须满足可逆条件(行列式不为零)。
    • 透视矩阵需为满秩矩阵。
  2. 浮点精度误差
    还原后的坐标可能为浮点数,需根据需求决定是否取整。

  3. 边界处理
    若变换后坐标超出原图范围,需进行有效性检查:

    if (0 <= x_restored < w) and (0 <= y_restored < h):
        # 坐标有效
    else:
        # 坐标越界
    
  4. 齐次坐标
    透视变换需使用齐次坐标(三维向量),还原后需归一化:

    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直接平移坐标图像裁剪后的坐标映射

掌握坐标还原技术能有效提升图像处理流程的灵活性,尤其在需要跨变换空间传递信息的任务中(如目标跟踪、增强现实)。

您可能感兴趣的与本文相关的镜像

Yolo-v5

Yolo-v5

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flos chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值