0

背景

我已经定义了一个带有 3D 点的网球场,并且我正在尝试使用 OpenCV 将 3D 点投影为 2D 图像。

下面是我用来定义网球场的 3D 点。以供参考:

  • 场上左边是-X,右边是+X,
  • 向上是-Y,向下是+Y,并且
  • 网的远端是+Z,近端是-Z。
  • 点(0,0,0)是左侧线与网线(基本上是左侧网柱)的交点。
def DefineCourtPoints():
    objp = {}
    objp[1] = [0,0,39] # 1.  Intersection of the upper base line with the left side line
    objp[2] = [0,0,-39] # 2.  Intersection of the lower base line with the left side line
    objp[3] = [36,0,-39] # 3.  Intersection of the lower base line with the right side line
    objp[4] = [36,0,39] # 4.  Intersection of the upper base line with the right side line  
    objp[5] = [4.5,0,39] # 5.  Intersection of the upper base line with the left singles line
    objp[6] = [4.5,0,-39] # 6.  Intersection of the lower base line with the left singles line
    objp[7] = [31.5,0,-39] # 7.  Intersection of the lower base line with the right singles line
    objp[8] = [31.5,0,39] # 8.  Intersection of the upper base line with the right singles line
    objp[9] = [4.5,0,21] # 9.  Intersection of the left singles line with the upper service line
    objp[10] = [31.5,0,21] # 10.  Intersection of the right singles line with the upper service line
    objp[11] = [4.5,0,-21] # 11.  Intersection of the left singles line with the lower service line
    objp[12] = [31.5,0,-21] # 12.  Intersection of the right singles line with the lower service line
    objp[13] = [18,0,21] # 13.  Intersection of the upper service line with the center service line
    objp[14] = [18,0,-21] # 14.  Intersection of the lower service line with the center service line
    objp[15] = [0,0,0] # 15.  Intersection of the left side line with the net line (this will be considered (0,0) )
    objp[16] = [36,0,0] # 16.  Intersection of the right side line with the net line

    return objp

作为其他参考,这里是我的相机的内在矩阵和失真参数(使用 OpenCV 获得并经过验证):

intrinsic_mtx = np.array([
    [1882.77177, 0.0, 973.572122],
    [0.0, 1880.83035, 537.299982],
    [0.0, 0.0, 1.0]
])

distortion = np.array([0.232714433, -1.35119878, -0.00188551612, 0.00166434182, 2.50351701])

这是我用来将每个 3D 点投影到 2D 并使用 Matplotlib 绘制点/线的代码。

def ProjectPoints(intrinsic_mtx, distortion, R, T, objp)
    x_points = []
    y_points = []

    # Loop through each of the 3D points and project them to 2D.
    for index in objp: 
        2d_point = cv2.projectPoints(
                        np.array(objp[index], dtype=np.float64),
                        cv2.Rodrigues(R)[0],
                        T,
                        intrinsic_mtx, 
                        distortion
                     )[0][0][0]

        print(2d_point)
        x_points.append(2d_point[0])
        y_points.append(2d_point[1])

    # Graph the court boundary.
    lines = [(1,2), # A line exists between point 1 and 2...
            (2,3), # A line exists between point 2 and 3...
            (3,4), # A line exists between point 3 and 4...
            (4,1)] # A line exists between point 4 and 1...

    x_lines = list()
    y_lines = list()
    for pair in lines:
        for i in range(2):
            x_lines.append(x_points[pair[i]-1])
            y_lines.append(y_points[pair[i]-1])
        # Append None to separate the lines.
        x_lines.append(None)
        y_lines.append(None)

    fig, ax = plt.subplots()
    ax.scatter(x_points, y_points)
    ax.axis('equal')
    ax.plot(x_lines, y_lines, c = 'r')
    plt.show()

问题

当我对这些点进行投影并绘制图表时,我希望得到一个看起来像网球场的东西,但我只得到了一团点!

为了排除故障,我决定使用球场的四个角(即 DefineCourtPoints 中的前四个点)仅绘制球场的外边缘。我希望看到一个矩形或平行四边形,因为它们是矩形的有效投影。但是,我得到如下内容,这实际上没有任何意义,因为它已经越界了:

投影输出......不是我所期待的

上面的结果是使用R = [0, 0, 0] 和获得的T = [0, -10, 0]

以下是上述结果的四个点的坐标,表明我并没有通过以错误的顺序绘制线条来导致奇怪的形状:

# Intersection of the upper base line with the left side line
[973.572122 , 1019.56417431]

# Intersection of the lower base line with the left side 
line
[973.572122 , 55.03578969]

# Intersection of the lower base line with the right side 
line
[-764.37105031, 55.03578969]

# Intersection of the upper base line with the right side line
[2711.51529431 , 1019.56417431]

问题

为什么对于像矩形/网球场边界这样简单的 3D 对象,我会得到如此奇怪的投影?

有人得到和我一样的结果吗?

谢谢!

自己试试

import numpy as np
import cv2
import matplotlib.pyplot as plt

def DefineCourtPoints(): # Just the corners of the court.
    objp = {}
    objp[1] = [0,0,39] # 1.  Intersection of the upper base line with the left side line
    objp[2] = [0,0,-39] # 2.  Intersection of the lower base line with the left side line
    objp[3] = [36,0,-39] # 3.  Intersection of the lower base line with the right side line
    objp[4] = [36,0,39] # 4.  Intersection of the upper base line with the right side line  

objp = DefineCourtPoints()
intrinsic_mtx = np.array([
    [1882.77177, 0.0, 973.572122],
    [0.0, 1880.83035, 537.299982],
    [0.0, 0.0, 1.0]
])

distortion = np.array([0.232714433, -1.35119878, -0.00188551612, 0.00166434182, 2.50351701])
R = np.array([0,0,0])
T = np.array([0,-10,0])
ProjectPoints(intrinsic_mtx, distortion, R, T, objp)
4

0 回答 0