从单个 2D 视频重建飞行 object 的 3D 轨迹
Reconstructing a flying object's 3D trajectory off a single 2D-video
我正在尝试重建篮球的 3D 轨迹,仅使用广播信号。
为此,我必须计算单应矩阵,因此在每一帧中我都成功地跟踪了球,并且在 "real world" 中已知它们位置的 6 个点(球场本身有 4 个,篮板上有 2 个)如图所示。
利用物理定律,我还估算了每一帧中球的 z-coordinate。
现在我想将球的位置从 2D 像素坐标映射到现实世界。我现在拥有的代码(稍后附上)输入像素位置(u,v)和高度(z)并输出 x,y,z 位置。它适用于球场上的点(意味着 z=0),但是当我需要跟踪空中的东西(球)时,结果就没有意义了。如果有人可以帮助告诉我我需要做什么才能获得映射,我将不胜感激。
# Make empty list for ball's 3D location
ball_3d_location = []
# Fixed things
size = frame_list[0].shape
focal_length = size[1]
center = (size[1]/2, size[0]/2)
camera_matrix= np.array(
[[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype = "double"
)
def groundProjectPoint(image_point, z = 0.0):
camMat = np.asarray(camera_matrix)
iRot = np.linalg.inv(rotMat)
iCam = np.linalg.inv(camMat)
uvPoint = np.ones((3, 1))
# Image point
uvPoint[0, 0] = image_point[0]
uvPoint[1, 0] = image_point[1]
tempMat = np.matmul(np.matmul(iRot, iCam), uvPoint)
tempMat2 = np.matmul(iRot, translation_vector)
s = (z + tempMat2[2, 0]) / tempMat[2, 0]
wcPoint = np.matmul(iRot, (np.matmul(s * iCam, uvPoint) - translation_vector))
# wcPoint[2] will not be exactly equal to z, but very close to it
assert int(abs(wcPoint[2] - z) * (10 ** 8)) == 0
wcPoint[2] = z
return wcPoint
dist_coeffs = np.zeros((4,1)) # Assuming no lens distortion
# The tracked points coordinates in the "Real World"
model_points = np.array([
(0,1524/2,0), #Baseline-sideline
(0,-244,0), #Paint-sideline
(579,-244,0), #Paint-FT
(579,1524/2,0), #Sideline-FT
(122,-182.9/2,396.32),#Top Left Backboard
(122,182.9/2,396.32)],dtype=np.float32 #Top Right BackBoard
)
for i,frame in enumerate(bball_frames):
f =frame
#This array has the pixel coordinates of the court & backboard points
image_points =np.array([f.baseline_sideline,
f.paint_sideline,
f.paint_ft,
f.sideline_ft,
f.top_left_backboard,
f.top_right_backboard],dtype=np.float32)
(success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE)
rotMat, _ = cv2.Rodrigues(rotation_vector)
#We assume we know the ball's height in each frame due to the laws of physics.
ball_3d_location+=[groundProjectPoint(image_point=ball_2d_location[i],z = ball_height[i])]
编辑:
首先,我想澄清一下参考平面:
- 您的视频是 3D 世界的 2D 投影(观看平面),作为垂直于相机镜头中心线的平面。
- 投篮弧嵌入一个平面(投篮平面)中,该平面垂直于真实世界 (3D) 地板,由释放点(射手的手)和接触点(篮板)定义。
您在视频中看到的镜头弧线是该镜头平面在观察平面上的投影。
I want to make sure we're clear with respect to your most recent
comment: So let's say I can estimate the shooting location on the
court (x,y). using the laws of physics I can say where the ball is in
each frame (x,y) wise and then from that and the pixel coordinates I
can extract the height coordinate?
- 您确实可以估计 (x,y) 坐标。但是,我不会将我的方法归因于 "the laws of physics"。我会使用解析几何。
- 您可以非常准确地估计出手点(从射手脚的已知 (x, y, 0) 位置)和篮板上的终点(其角已知)的 3D 坐标).
- 从这些点中的每一个点到地板 (z=0) 垂下一条垂线。地板上的那条线是弧线到地板的垂直投影——这些是飞行中球的 (x,y) 坐标。
- 对于每个视频帧,从球的图像投射垂直线到地板上的那条线...那 给你球的 (x,y) 坐标, 物有所值。
- 你有视平面、视点(相机)和圆弧平面的定义(方程)。要为每个视频帧确定球的位置,请从视点画一条线,穿过视图平面上的球图像。确定这条线与圆弧平面的交点。 那 为您提供该帧中球的 3D 坐标。
这是否阐明了有用的攻击路线?
我正在尝试重建篮球的 3D 轨迹,仅使用广播信号。 为此,我必须计算单应矩阵,因此在每一帧中我都成功地跟踪了球,并且在 "real world" 中已知它们位置的 6 个点(球场本身有 4 个,篮板上有 2 个)如图所示。
利用物理定律,我还估算了每一帧中球的 z-coordinate。
现在我想将球的位置从 2D 像素坐标映射到现实世界。我现在拥有的代码(稍后附上)输入像素位置(u,v)和高度(z)并输出 x,y,z 位置。它适用于球场上的点(意味着 z=0),但是当我需要跟踪空中的东西(球)时,结果就没有意义了。如果有人可以帮助告诉我我需要做什么才能获得映射,我将不胜感激。
# Make empty list for ball's 3D location
ball_3d_location = []
# Fixed things
size = frame_list[0].shape
focal_length = size[1]
center = (size[1]/2, size[0]/2)
camera_matrix= np.array(
[[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype = "double"
)
def groundProjectPoint(image_point, z = 0.0):
camMat = np.asarray(camera_matrix)
iRot = np.linalg.inv(rotMat)
iCam = np.linalg.inv(camMat)
uvPoint = np.ones((3, 1))
# Image point
uvPoint[0, 0] = image_point[0]
uvPoint[1, 0] = image_point[1]
tempMat = np.matmul(np.matmul(iRot, iCam), uvPoint)
tempMat2 = np.matmul(iRot, translation_vector)
s = (z + tempMat2[2, 0]) / tempMat[2, 0]
wcPoint = np.matmul(iRot, (np.matmul(s * iCam, uvPoint) - translation_vector))
# wcPoint[2] will not be exactly equal to z, but very close to it
assert int(abs(wcPoint[2] - z) * (10 ** 8)) == 0
wcPoint[2] = z
return wcPoint
dist_coeffs = np.zeros((4,1)) # Assuming no lens distortion
# The tracked points coordinates in the "Real World"
model_points = np.array([
(0,1524/2,0), #Baseline-sideline
(0,-244,0), #Paint-sideline
(579,-244,0), #Paint-FT
(579,1524/2,0), #Sideline-FT
(122,-182.9/2,396.32),#Top Left Backboard
(122,182.9/2,396.32)],dtype=np.float32 #Top Right BackBoard
)
for i,frame in enumerate(bball_frames):
f =frame
#This array has the pixel coordinates of the court & backboard points
image_points =np.array([f.baseline_sideline,
f.paint_sideline,
f.paint_ft,
f.sideline_ft,
f.top_left_backboard,
f.top_right_backboard],dtype=np.float32)
(success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE)
rotMat, _ = cv2.Rodrigues(rotation_vector)
#We assume we know the ball's height in each frame due to the laws of physics.
ball_3d_location+=[groundProjectPoint(image_point=ball_2d_location[i],z = ball_height[i])]
编辑:
首先,我想澄清一下参考平面:
- 您的视频是 3D 世界的 2D 投影(观看平面),作为垂直于相机镜头中心线的平面。
- 投篮弧嵌入一个平面(投篮平面)中,该平面垂直于真实世界 (3D) 地板,由释放点(射手的手)和接触点(篮板)定义。
您在视频中看到的镜头弧线是该镜头平面在观察平面上的投影。
I want to make sure we're clear with respect to your most recent comment: So let's say I can estimate the shooting location on the court (x,y). using the laws of physics I can say where the ball is in each frame (x,y) wise and then from that and the pixel coordinates I can extract the height coordinate?
- 您确实可以估计 (x,y) 坐标。但是,我不会将我的方法归因于 "the laws of physics"。我会使用解析几何。
- 您可以非常准确地估计出手点(从射手脚的已知 (x, y, 0) 位置)和篮板上的终点(其角已知)的 3D 坐标).
- 从这些点中的每一个点到地板 (z=0) 垂下一条垂线。地板上的那条线是弧线到地板的垂直投影——这些是飞行中球的 (x,y) 坐标。
- 对于每个视频帧,从球的图像投射垂直线到地板上的那条线...那 给你球的 (x,y) 坐标, 物有所值。
- 你有视平面、视点(相机)和圆弧平面的定义(方程)。要为每个视频帧确定球的位置,请从视点画一条线,穿过视图平面上的球图像。确定这条线与圆弧平面的交点。 那 为您提供该帧中球的 3D 坐标。
这是否阐明了有用的攻击路线?