如何将warped图像中Hello的bounding box坐标映射回原始图像?
嘿,这个问题其实很好解决——核心就是利用透视变换的可逆性,把你在warped图上的边界框坐标映射回原始图像就行。我给你一步步讲清楚怎么做:
核心思路
你在执行四点透视变换时,会得到一个透视变换矩阵M(一般是通过cv2.getPerspectiveTransform计算的),它负责把原始图像的坐标映射到warped图像。那反过来,这个矩阵的逆矩阵M_inv,就能把warped图像上的坐标转换回原始图像的对应位置。
具体操作步骤
修改四点变换函数,保留变换矩阵M
你之前的four_point_transform应该只返回了warped图像,现在得让它同时返回变换矩阵M。修改后的函数大概是这样:def four_point_transform(image, pts): # 原有的计算逻辑(排序四点、计算目标宽高)不变 (tl, tr, br, bl) = pts maxWidth = max(int(np.linalg.norm(tr - tl)), int(np.linalg.norm(br - bl))) maxHeight = max(int(np.linalg.norm(bl - tl)), int(np.linalg.norm(br - tr))) # 定义目标图像的四点坐标 dst = np.array([ [0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1] ], dtype="float32") # 计算透视变换矩阵M M = cv2.getPerspectiveTransform(pts, dst) warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight)) # 同时返回warped图像和变换矩阵M return warped, M计算逆变换矩阵M_inv
拿到M之后,用OpenCV的cv2.invert函数计算它的逆矩阵:# 假设你已经有原始图像original_image,以及变换用的四个点pts warped, M = four_point_transform(original_image, pts) # 计算逆矩阵,第二个返回值是逆矩阵的状态(我们这里不用关注) M_inv, _ = cv2.invert(M)准备warped图中边界框的四个顶点
你画的矩形是从(37,20)到(222,97),对应的四个顶点按顺序(左上、右上、右下、左下)定义出来:warped_bbox_pts = np.array([ [37, 20], # 左上 [222, 20], # 右上 [222, 97], # 右下 [37, 97] # 左下 ], dtype=np.float32)把warped坐标映射回原始图像
用cv2.perspectiveTransform做坐标转换,注意要把点转换成函数要求的形状((1, N, 2)):# 调整形状以满足透视变换的输入要求 warped_bbox_pts = warped_bbox_pts.reshape((1, 4, 2)) # 应用逆变换得到原始图像中的坐标 original_bbox_pts = cv2.perspectiveTransform(warped_bbox_pts, M_inv) # 把浮点坐标转成整数(图像坐标都是整数) original_bbox_pts = np.int32(original_bbox_pts)在原始图像上绘制边界框
因为逆变换后的点可能不再是严格的矩形(透视变换会让形状畸变),所以用cv2.polylines绘制闭合四边形更准确:# 在原始图像上画红色的边界框,线宽2 cv2.polylines(original_image, original_bbox_pts, isClosed=True, color=(0, 0, 255), thickness=2)
完整的代码片段参考
把这些步骤整合起来,大概是这样的:
import cv2 import numpy as np def four_point_transform(image, pts): (tl, tr, br, bl) = pts maxWidth = max(int(np.linalg.norm(tr - tl)), int(np.linalg.norm(br - bl))) maxHeight = max(int(np.linalg.norm(bl - tl)), int(np.linalg.norm(br - tr))) dst = np.array([ [0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1] ], dtype="float32") M = cv2.getPerspectiveTransform(pts, dst) warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight)) return warped, M # 加载原始图像(替换成你的图像路径) original_image = cv2.imread("your_image_path.jpg") # 假设你已经有四点变换的四个点pts(比如手动标注或检测得到) pts = np.array([[x1,y1], [x2,y2], [x3,y3], [x4,y4]], dtype="float32") # 执行四点变换,得到warped图像和变换矩阵M warped, M = four_point_transform(original_image, pts) # 在warped图上绘制原有的蓝色边界框 cv2.rectangle(warped, (37, 20), (222, 97), (255, 0, 0), 2) # 计算逆变换矩阵 M_inv, _ = cv2.invert(M) # 定义warped图中边界框的四个顶点 warped_bbox_pts = np.array([ [37, 20], [222, 20], [222, 97], [37, 97] ], dtype=np.float32) # 坐标映射转换 warped_bbox_pts = warped_bbox_pts.reshape((1, 4, 2)) original_bbox_pts = cv2.perspectiveTransform(warped_bbox_pts, M_inv) original_bbox_pts = np.int32(original_bbox_pts) # 在原始图像上绘制红色边界框 cv2.polylines(original_image, original_bbox_pts, isClosed=True, color=(0, 0, 255), thickness=2) # 显示结果 cv2.imshow("Warped Image", warped) cv2.imshow("Original Image with BBox", original_image) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者Himansingh
相关产品推荐
相关产品推荐

