【问题标题】:Evaluate the correctness of In/Extrinsic Params resulting from camera calibration评估相机校准产生的 In/Extrinsic Params 的正确性
【发布时间】:2021-10-03 01:55:04
【问题描述】:

我正在使用OpenCV 进行相机校准并设法获取所有相机参数,但现在我不确定我是否正确执行了所有操作。
这是我使用的图像 我在图像上使用了 6 个点(4 个球场角,两个在网与球场线接触的中间)
imgPts = [[577, 303], [1333, 303], [495, 517], [1422, 517], [366, 857], [1562, 857]]
假设左上角是原点,我构建了以米为单位的相应世界坐标( 23.77mx 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]]

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

【问题讨论】:

    标签: python opencv camera-calibration


    【解决方案1】:

    我得到了奇怪的结果。坐标似乎与您分享的图片中可识别的任何内容都不匹配。

    我根据您分享的 1366x768 图片进行了自己的测量。结果看起来非常合理。

    然而,由于imgPts略有不同,我得到的结果大不相同。这意味着您需要进行更多的测量才能获得准确度。

    图片来自在 Arthur Ashe 体育场举行的一场比赛,该体育场的半径约为 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

    【讨论】:

    • 非常感谢您的回答!你是对的,我附上了错误的截图,已编辑!而且你的结果肯定比我的更合理,但这是一种非常具体的检查正确性的方法吗?
    • 不知道。我在这些问题上的数学是生疏的。您可能必须浏览“多视图几何”一书才能了解数学。这个算法需要更多的数据才能得到好的结果。我相信总共四点对是最小值。将所有内容移动到一个函数中,然后在循环中将正常/高斯分布的噪声添加到点(sigma = 一个像素左右),然后观察结果的作用。
    • 如果我的两条水平线都完全水平(即每两个点的 y 坐标相同),我会得到疯狂的结果。这很好地证明了该算法需要该维度中的实际数据。
    • 我认为有轻微的镜头畸变。这是“噪音”的一个具体来源……您肯定需要更多数据。相机不动,场也不动,所以这是个问题。为了验证结果,您还可以projectPoints 模型并重新摆回图片上,并考虑这看起来是否合理。但是,许多解决方案看起来都是合理的
    • 我认为initCameraMatrix2D 是完全错误的工具。数据也太少了。
    猜你喜欢
    • 2017-09-01
    • 2018-07-15
    • 2015-09-16
    • 2015-06-18
    • 1970-01-01
    • 2023-03-08
    • 2015-11-16
    • 1970-01-01
    • 2015-03-17
    相关资源
    最近更新 更多