相机标定如何提高焦距精度?

问题描述 投票:0回答:1

问题

我正在校准一些相机,并且焦距有轻微(5%左右)的误差,以及还可以但不是很大的重投影误差(〜0.7px)。对于我的应用程序,我需要精度尽可能接近完美,所以这个误差太大了。

我从校准中得到的焦距是

2530 px
。我正在使用这款相机。根据
(4056, 3040)
的分辨率、
1.55 um
的像素大小和
75 degrees
的 H-FoV,我可以计算出我的预期焦距为
4.096558636989045 mm
2642.9410561219647 px

焦距实验

为了验证这个预期焦距是否正确,我设置了一个实验来测量焦距。相机聚焦后,我在垂直于相机的方向放置了一块查尔科板,并测量了深度。然后,我测量了图像中电路板的一部分,根据我的电路板尺寸,我当然知道它有多大(以毫米为单位)。使用针孔相机模型,我最终陷入了原始

2643 px
数字的实验误差范围内。所以,我确信这是正确的答案。

我尝试过的事情

以下是我尝试改善焦距结果的方法。

  1. 使用多种软件。我尝试过相机制造商的软件 (DepthAI)、我自己的 OpenCV 实现以及 MATLAB 相机校准器应用程序。这三个都给了我相同的结果。
  2. 采用优质板材。我尝试过使用 calib.io 的两块不同的板,以及我自己打印的一块。同样,每个结果都相似。
  3. 我的照明良好,无眩光,角落清晰。
  4. 我的镜头在应用程序的工作距离处对焦良好,并且我大致在这个工作距离处拍摄图像。
  5. 我有很多有角度的图像,因为透视缩短对于焦距很重要。
  6. 我使用过少则 10-15 张,多则 100 张图像。

下面是我的数据分布示例,以了解我正在使用的姿势。 Images

问题

这是我的一些问题。

  1. 捕获数据以确保焦距准确的最佳方法是什么?
  2. 我的流程中是否有任何问题引起任何标记或问题?
  3. 我的相机结构(即:廉价的 M12 镜头)可以在这里做出贡献吗?
  4. 对于使用针孔相机进行基于 OpenCV 的校准,我所追求的精度是否合理?
  5. 还有什么办法可以进一步减少重投影误差?

最小示例

这是一个使用 OpenCV 的最小示例。

from pathlib import Path

import cv2
import numpy as np

# Load images.
calib_images_path = Path("calibration_images")
image_files = list(calib_images_path.glob("*.png"))
images = [cv2.imread(str(image_file)) for image_file in image_files]

# Define the ChArUco board parameters.
charuco_size = (17, 24)
square_length = 30  # mm
marker_length = 22  # mm
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_5X5_1000)
charuco_board = cv2.aruco.CharucoBoard(
    size=charuco_size,
    squareLength=square_length,
    markerLength=marker_length,
    dictionary=aruco_dict,
)

# Detect ChArUco corners.
all_charuco_corners = []
all_charuco_ids = []
for image_file in image_files:
    # Grayscale image.
    image = cv2.imread(str(image_file))
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Marker detection.
    corners, ids, rejected = cv2.aruco.detectMarkers(gray, aruco_dict)

    # Interpolation and refinement.
    if ids is not None and len(ids) > 0:
        cv2.aruco.refineDetectedMarkers(gray, charuco_board, corners, ids, rejected)

        retval, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(
            markerCorners=corners, markerIds=ids, image=gray, board=charuco_board
        )

        if retval > 0:
            all_charuco_corners.append(charuco_corners)
            all_charuco_ids.append(charuco_ids)

# Initial camera matrix and distortion coefficients.
expected_focal_length_px = 2642.9410561219647
image_size = gray.shape[::-1]
initial_camera_matrix = np.array(
    [
        [expected_focal_length_px, 0, image_size[0] / 2],
        [0, expected_focal_length_px, image_size[1] / 2],
        [0, 0, 1],
    ]
)
initial_dist_coeffs = np.zeros((5, 1))

# Camera calibration.
image_size = gray.shape[::-1]
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.aruco.calibrateCameraCharuco(
    charucoCorners=all_charuco_corners,
    charucoIds=all_charuco_ids,
    board=charuco_board,
    imageSize=image_size,
    cameraMatrix=initial_camera_matrix,
    distCoeffs=initial_dist_coeffs,
)
opencv computer-vision camera camera-calibration matlab-cvst
1个回答
0
投票

这里有几个因素在起作用。

  • 镜头的焦距规格始终只是“近似值”。特别是在 M12 镜头的情况下,当镜头旋入和旋出其螺纹支架时,焦距通常会随焦点发生轻微变化。
  • 我也不期望像素尺寸规格的精确度超过 5%,尤其是在不受控制的温度环境下。
  • 焦距通常与畸变参数相关。 IE。焦距可能小于标称焦距,并且估计失真以补偿该焦距。

Calib.io 有校准器程序,它可以让您调查此类参数相关性是否存在,并让您获得最适合的线性相机模型,估计与您通过实验获得的“有效焦距”相当的“有效焦距”。 此外,校准器还可以让您分析剩余的 rpe 是由于未建模的镜头行为(不良)还是仅由于无偏图像噪声(无害)造成的。

© www.soinside.com 2019 - 2024. All rights reserved.