バックグラウンド
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()
問題
ポイントを射影してグラフ化すると、テニスコートのようなものが得られると思いますが、ポイントの塊しか得られません!
トラブルシューティングを行うために、コートの 4 つのコーナー (DefineCourtPoints の最初の 4 つのポイント) を使用して、コートの外側の端だけをグラフ化することにしました。これらは長方形の有効な投影であるため、長方形または平行四辺形が表示されると予想していました。ただし、次のようなものが得られますが、これは線を越えているため、実際には意味がありません。
上記の結果はR = [0, 0, 0]
、 とT = [0, -10, 0]
上記の結果の 4 つの点の座標を次に示します。これは、何らかの方法で線を間違った順序でグラフ化したために奇妙な形状が発生したのではないことを示しています。
# 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)