背景
我已经定义了一个带有 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)