如何通过OpenCV Homography获取目标在变换后图像的新坐标?
问题描述
我正在使用**Homography(单应性变换)**进行篮球场检测,已在原始图像中检测到球员目标,现需获取该球员在透视变换后图像中的新坐标,用于构建小地图系统。
当前代码
import cv2 import numpy as np import matplotlib.pyplot as plt #player coordinates - multiple players x_coords = [] y_coords = [] print(x_coords) print(y_coords) #basketball court, size-1830, 910 pts_src = np.array([ [394, 412], # top left corner [0, 500], [0, 670], [910, 770], [1830, 720], [1830,545], [1540, 450] # top right corner ]) #minimap, size-500,300 pts_dst = np.array([ [0, 0], # top left corner [0, 275], [25, 300], [250, 300], [475, 300], [500, 275], [500, 0] # top right corner ]) #find homography h, status = cv2.findHomography(pts_src, pts_dst) img_src2 = cv2.imread('basketball_court.png') img_out = cv2.warpPerspective(img_src2, h, (img_dst.shape[1], img_dst.shape[0])) cv2.imshow("Warped", img_out) cv2.waitKey(0)
已尝试参考资料
- 利用OpenCV单应性从像素坐标转换为全局XY坐标
- OpenCV 2.4官方文档:从齐次坐标转换点的说明
解决方案
要实现球员坐标从原始图像到小地图的转换,核心是用已求得的单应矩阵h对球员坐标进行齐次变换,具体步骤如下:
- 整理球员坐标格式:将检测到的球员(x,y)坐标转换为OpenCV要求的N×1×2格式numpy数组,示例:
# 替换为实际检测到的球员坐标 x_coords = [150, 400, 650] y_coords = [300, 550, 700] players = np.array(list(zip(x_coords, y_coords)), dtype=np.float32).reshape(-1,1,2)
- 应用单应变换:使用
cv2.perspectiveTransform()函数完成坐标转换:
transformed_players = cv2.perspectiveTransform(players, h)
- 提取最终坐标:将变换后的结果转换为普通(x,y)格式,方便后续使用:
new_coords = transformed_players.reshape(-1,2).tolist()
- 整合后的完整代码:
import cv2 import numpy as np import matplotlib.pyplot as plt # 替换为实际检测到的球员坐标 x_coords = [150, 400, 650] y_coords = [300, 550, 700] # 转换为OpenCV要求的格式 players = np.array(list(zip(x_coords, y_coords)), dtype=np.float32).reshape(-1,1,2) #basketball court, size-1830, 910 pts_src = np.array([ [394, 412], # top left corner [0, 500], [0, 670], [910, 770], [1830, 720], [1830,545], [1540, 450] # top right corner ], dtype=np.float32) #minimap, size-500,300 pts_dst = np.array([ [0, 0], # top left corner [0, 275], [25, 300], [250, 300], [475, 300], [500, 275], [500, 0] # top right corner ], dtype=np.float32) #find homography h, status = cv2.findHomography(pts_src, pts_dst) # 转换球员坐标并打印结果 transformed_players = cv2.perspectiveTransform(players, h) new_coords = transformed_players.reshape(-1,2).tolist() print("球员在小地图中的坐标:") for idx, (x,y) in enumerate(new_coords): print(f"球员{idx+1}: ({round(x,2)}, {round(y,2)})") # 透视变换图像(修正原代码中img_dst未定义的问题) img_src2 = cv2.imread('basketball_court.png') img_out = cv2.warpPerspective(img_src2, h, (500, 300)) cv2.imshow("Warped", img_out) cv2.waitKey(0) cv2.destroyAllWindows()
关键注意事项
- 所有参与变换的坐标数组需指定
dtype=np.float32,否则会触发类型错误 cv2.perspectiveTransform()会自动处理齐次坐标转换,无需手动调用convertPointsFromHomogeneous- 原代码中
img_dst未定义,因此warpPerspective的输出尺寸直接使用小地图的(500,300)即可
内容的提问来源于stack exchange,提问作者gasper vaupot
相关产品推荐
相关产品推荐

