评估摄像机校准产生的内部/外部参数的正确性

2024-04-20 09:30:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用OpenCV进行相机校准,并设法获得所有相机参数,但现在我不确定是否所有操作都正确。
这是我使用的图像enter image description here 我在图像上使用了6个点(4个球场角落和两个在中间的网接触球场线)
imgPts = [[577, 303], [1333, 303], [495, 517], [1422, 517], [366, 857], [1562, 857]]
假设左上角是原点,我构建了相应的世界坐标,单位为米(23.77m x 10.97m):
{}
以下是我获取相机矩阵、旋转平移向量的代码:

objPts = np.array(objPts)
objPts = objPts.astype('float32')

imgPts = np.array(imgPts)
imgPts = imgPts.astype('float32')

w = frame.shape[1]
h = frame.shape[0]

size = (w,h)

camera_matrix = cv2.initCameraMatrix2D([objPts],[imgPts], size)
rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera([objPts], [imgPts], size, None, None)

print(rms)

2.2659039195846487

print(camera_matrix)

[[7.29904054e+04 0.00000000e+00 7.70590422e+02]
 [0.00000000e+00 3.27820311e+03 1.05708724e+02]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]

print(dist_coefs)

[[-4.60113019e+00  1.52353355e+03 -1.11809613e+00  7.20674734e-02
  -2.28959021e+04]]

print(rvecs[0])

[[ 0.48261931]
 [-4.87671221]
 [ 0.28501516]]

print(tvecs[0])

[[ -0.69935398]
 [ 15.30349325]
 [189.46509398]]

如何检查这些值/矩阵/向量是否正确


Tags: 图像sizenp矩阵array向量framematrix
1条回答
网友
1楼 · 发布于 2024-04-20 09:30:33

我从你的数字中得到奇怪的结果。坐标似乎与您共享的图片中可识别的任何东西都不匹配

我根据你分享的1366x768张照片自己做了测量。结果看起来很有道理

然而,随着稍微不同^{,我得到了截然不同的结果。这意味着您需要更多的测量来获得准确度

这张照片来自阿瑟·阿什体育场的一场比赛,该体育场的半径约为70米。在距离中心约30米的地方,有一条环形通道,这架相机可能就在那里

#!/usr/bin/env python3

import os
import sys
import numpy as np
import cv2 as cv

np.set_printoptions(suppress=True)

# https://en.wikipedia.org/wiki/Tennis_court#Dimensions
court_width = 10.97 # meters
court_length = 23.77 # meters

objPts = np.float32([
    [-0.5, +0.5, 0], # far left
    [+0.5, +0.5, 0], # far right
    # center of court is 0,0,0
    [+0.5, -0.5, 0], # near right
    [-0.5, -0.5, 0], # near left
]) * np.float32([court_width, court_length, 0])

# points centered on the outside lines
# imgPts = np.float32([
#   [ 346,  245], # far left
#   [ 988,  244], # far right
#   [1188,  607], # near right
#   [ 142,  611], # near left
# ])
# points on the outsides of the outside lines (one variant)
# imgPts = np.float32([
#   [ 345,  244], # far left
#   [ 989,  243], # far right
#   [1192,  609], # near right
#   [ 139,  612], # near left
# ])
# points on the outsides of the outside lines (other variant)
imgPts = np.float32([
    [ 344,  244], # far left
    [ 989,  243], # far right
    [1192,  609], # near right
    [ 138,  613], # near left
])

#im = cv.imread("vxUZD.jpg")
#height, width = im.shape[:2]
width, height = 1366, 768

print(f"image size:\n\t{width} x {height}")

C = cv.initCameraMatrix2D([objPts], [imgPts], (width, height))
print("camera matrix:")
print(C)
fx = C[0,0]

# fx * tan(hfov/2) == width/2
hfov = np.arctan(width/2 / fx) * 2
print(f"horizontal FoV:\n\t{hfov / np.pi * 180:.2f} °")

# x? mm focal length -> 36 mm horizontal (24 vertical)?
fd = 36 / (np.tan(hfov/2) * 2)
print(f"focal length (35mm equivalent):\n\t{fd:.2f} mm")

(rv, rvec, tvec) = cv.solvePnP(objPts, imgPts, C, distCoeffs=None)
print("tvec [m]:")
print(tvec)

结果:

image size:
        1366 x 768
camera matrix:
[[1850.17197043    0.          682.5       ]
 [   0.         1850.17197043  383.5       ]
 [   0.            0.            1.        ]]
horizontal FoV:
        40.52 °
focal length (35mm equivalent):
        48.76 mm
tvec [m]:
[[-0.2618669 ]
 [-0.45430541]
 [30.2741125 ]]

下面是一个更加充实的脚本,它使用calibrateCamera并确定了各种参数。这似乎会带来更稳定的结果

https://gist.github.com/crackwitz/0d1e401b597b435bcc5e65349cbca870

相关问题 更多 >