评估相机校准产生的 In/Extrinsic 参数的正确性
Evaluate the correctness of In/Extrinsic Params resulting from camera calibration
我用 OpenCV
进行相机校准并设法获取了所有相机参数,但现在我不确定我是否正确完成了所有操作。
这是我使用的图像
我在图像上使用了 6 个点(4 个球场角落和两个在网接触球场线的中间)
imgPts = [[577, 303], [1333, 303], [495, 517], [1422, 517], [366, 857], [1562, 857]]
假设左上角是原点我构建了以米为单位的相应世界坐标(23.77m x 10.97m):
objPts = [[0, 0, 0], [10.97, 0, 0], [0, 11.8, 0], [10.97, 11.8, 0], [0, 23.77, 0], [10.97, 23.77, 0]]
以下是我获取 camera_matrix、旋转平移向量的代码:
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]]
如何检查这些 values/matrix/vectors 是否正确?
我用你的数字得到了奇怪的结果。坐标似乎与您分享的图片中的任何可识别内容都不匹配。
我根据您分享的 1366x768 图片进行了自己的测量。结果看起来很合理。
但是,由于略有不同imgPts
,我得到了截然不同的结果。这意味着您需要进行更多测量才能确保准确性。
图片来自阿瑟·阿什球场的一场比赛,球场的半径约为 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
我用 OpenCV
进行相机校准并设法获取了所有相机参数,但现在我不确定我是否正确完成了所有操作。
这是我使用的图像
imgPts = [[577, 303], [1333, 303], [495, 517], [1422, 517], [366, 857], [1562, 857]]
假设左上角是原点我构建了以米为单位的相应世界坐标(23.77m x 10.97m):objPts = [[0, 0, 0], [10.97, 0, 0], [0, 11.8, 0], [10.97, 11.8, 0], [0, 23.77, 0], [10.97, 23.77, 0]]
以下是我获取 camera_matrix、旋转平移向量的代码:
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]]
如何检查这些 values/matrix/vectors 是否正确?
我用你的数字得到了奇怪的结果。坐标似乎与您分享的图片中的任何可识别内容都不匹配。
我根据您分享的 1366x768 图片进行了自己的测量。结果看起来很合理。
但是,由于略有不同imgPts
,我得到了截然不同的结果。这意味着您需要进行更多测量才能确保准确性。
图片来自阿瑟·阿什球场的一场比赛,球场的半径约为 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