You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于已知3D起止点的2D球坐标转真实3D坐标技术问询

棒球轨迹像素坐标转3D坐标并绘制轨迹的Python实现

核心思路

已知释放点RP(x₁,0,z₁)和落地点LP(x₂,60.5,z₂)的真实3D坐标,以及这两个点对应的图像像素坐标(u₁,v₁)、(u₂,v₂),基于透视投影的射线特性推导映射关系:

  • 每个图像像素(u,v)对应一条从相机光心出发的射线,棒球的3D位置必然在这条射线上
  • 结合棒球运动的y轴位置(从0到60.5英尺的线性分布,也可替换为物理抛物线模型提升精度),计算对应3D点的x和z坐标

实现步骤

1. 定义已知参数

整理真实3D坐标、对应像素坐标及图像尺寸:

# 已知真实3D坐标(单位:英尺)
rp_3d = (1.5, 0.0, 5.0)  # 释放点RP(x1,y1,z1),y1=0
lp_3d = (-1.2, 60.5, 4.8)  # 落地点LP(x2,y2,z2),y2=60.5

# 对应图像像素坐标(目标检测输出结果)
rp_pixel = (620, 350)  # (u1, v1)
lp_pixel = (640, 680)  # (u2, v2)

# 图像尺寸
img_width = 1280
img_height = 720

# 所有轨迹点的像素坐标列表(示例数据)
trajectory_pixels = [
    (620, 350), (625, 400), (630, 450), (635, 500),
    (638, 550), (640, 600), (640, 680)
]

2. 实现像素到3D坐标的转换函数

基于透视投影的相似性,将像素坐标映射为真实3D坐标:

def pixel_to_3d(u, v, rp_3d, lp_3d, rp_pixel, lp_pixel):
    # 提取坐标分量
    x1, y1, z1 = rp_3d
    x2, y2, z2 = lp_3d
    u1, v1 = rp_pixel
    u2, v2 = lp_pixel
    
    # 计算像素点在RP-LP像素线段上的归一化比例t(基于垂直方向v坐标)
    t = (v - v1) / (v2 - v1) if v2 != v1 else 0.0
    
    # 映射得到y坐标(线性插值,若需物理精度可替换为抛物线模型)
    y = y1 + t * (y2 - y1)
    
    # 利用透视相似比例计算x、z坐标
    x = x1 + (x2 - x1) * ((u - u1)/(u2 - u1)) * (y/y2) if u2 != u1 else x1
    z = z1 + (z2 - z1) * ((v - v1)/(v2 - v1)) * (y/y2) if v2 != v1 else z1
    
    return (x, y, z)

3. 批量转换所有轨迹点

遍历轨迹像素列表,生成对应的3D坐标:

trajectory_3d = [pixel_to_3d(u, v, rp_3d, lp_3d, rp_pixel, lp_pixel) for u, v in trajectory_pixels]

4. 绘制3D运动轨迹

使用matplotlib绘制轨迹图:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 创建3D绘图对象
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

# 提取3D坐标分量
x_coords = [p[0] for p in trajectory_3d]
y_coords = [p[1] for p in trajectory_3d]
z_coords = [p[2] for p in trajectory_3d]

# 绘制轨迹线与关键点
ax.plot(x_coords, y_coords, z_coords, label='棒球轨迹', linewidth=2, color='red')
ax.scatter(rp_3d[0], rp_3d[1], rp_3d[2], color='green', s=100, label='释放点RP')
ax.scatter(lp_3d[0], lp_3d[1], lp_3d[2], color='blue', s=100, label='落地点LP')

# 设置坐标轴与标题
ax.set_xlabel('X (英尺)')
ax.set_ylabel('Y (英尺)')
ax.set_zlabel('Z (英尺)')
ax.set_title('棒球3D运动轨迹')
ax.legend()

plt.show()

优化提示

  • 若需要更高精度,可将y坐标的线性插值替换为物理抛物线模型:结合棒球运动的重力加速度,基于RP、LP拟合抛物线方程,再通过射线与抛物线相交求解3D坐标
  • 若RP与LP的像素坐标垂直方向重合,可改用x坐标计算归一化比例t

内容的提问来源于stack exchange,提问作者Carlos Marcano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:31:21