从单个2D视频重建飞行物体的3D轨迹

时间:2019-08-22 16:18:00

标签: python opencv computer-vision homography

enter image description here

我正在尝试仅使用广播提要来重建篮球的3D轨迹。 为此,我必须计算单应性矩阵,因此在每个帧中我都成功地跟踪了球,并在“真实世界”中将其位置称为6个点(在球场上为4个,在篮板上为2个),在图片中看到。

利用物理定律,我还估计了每一帧中球的z坐标。

现在,我想将球的位置从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])]

编辑:Is this how to calculate the basketball's height?

1 个答案:

答案 0 :(得分:1)

首先,我想澄清参考平面:

  1. 您拥有的视频是3D世界的2D投影(观看平面),是垂直于相机镜头中心线的平面。
  2. 射击弧嵌入垂直于真实(3D)地板的平面(射击平面)中,该平面由释放点(射击手的手)和接触点(篮板)定义。

您在视频中看到的镜头弧是从该镜头平面到观看平面的投影。

  

我想确保我们对您的最新情况有明确的了解   评论:所以假设我可以估算出   法院(x,y)。使用物理定律,我可以说出球在哪里   每帧(x,y)明智,然后从那开始,像素坐标I   可以提取高度坐标吗?

  1. 您确实可以估计(x,y)坐标。但是,我不会将我的方法归因于“物理定律”。我会使用解析几何。
  2. 您可以准确地估计释放点(从射手脚的已知(x,y,0)位置)和篮板上的终点(其角已知)的3D坐标。
  3. 将这些点中的每一个垂直于地面(z = 0)。地板上的那条线是弧到地板的垂直投影-这些是飞行中的球的(x,y)坐标。
  4. 对于每个视频帧,将投影的垂直于球的图像放置到地板上的那条线上... 为您提供球的(x,y)坐标,以了解其价值。
  5. 您具有视平面,视点(摄像机)和弧平面的定义(方程式)。要确定每个视频帧的球位置,请从视点穿过视平面上球的图像绘制一条线。确定这条线与弧平面的交点。 那个为您提供该帧中球的3D坐标。

这是否阐明了有用的攻击路线?