0%

Opencv内参标定

相机内参标定(Camera Intrinsic Calibration)的目的是确定相机的内部参数,包括焦距、主点坐标和畸变系数等。这些参数描述了相机如何将三维世界中的点投影到二维图像平面上。以下是相机内参标定的原理和步骤。


1. 相机模型

相机的成像过程可以用针孔相机模型描述。相机内参包括以下参数:

  1. 焦距(fx,fy)(f_x, f_y):相机在 xxyy 方向上的焦距(以像素为单位)。
  2. 主点cx,cyc_x, c_y):图像平面的主点坐标(通常是图像中心)。
  3. 畸变系数:描述镜头畸变的参数,包括径向畸变和切向畸变。

相机内参矩阵 KK 可以表示为:

K=[fx0cx0fycy001]K = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix}


2. 畸变模型

镜头畸变主要包括:

  1. 径向畸变:由镜头形状引起,通常用多项式模型描述:

    xcorrected=x(1+k1r2+k2r4+k3r6)x_{\text{corrected}} = x (1 + k_1 r^2 + k_2 r^4 + k_3 r^6)

    ycorrected=y(1+k1r2+k2r4+k3r6)y_{\text{corrected}} = y (1 + k_1 r^2 + k_2 r^4 + k_3 r^6)

    其中 r2=x2+y2r^2 = x^2 + y^2k1,k2,k3k_1, k_2, k_3 是径向畸变系数。

  2. 切向畸变:由镜头安装误差引起,通常用以下模型描述:

    xcorrected=x+[2p1xy+p2(r2+2x2)]x_{\text{corrected}} = x + [2 p_1 xy + p_2 (r^2 + 2 x^2)]

    ycorrected=y+[p1(r2+2y2)+2p2xy]y_{\text{corrected}} = y + [p_1 (r^2 + 2 y^2) + 2 p_2 xy]

    其中 p1,p2p_1, p_2 是切向畸变系数。


3. 标定原理

相机内参标定通常使用已知几何形状的标定板(如棋盘格或圆点阵列)。标定过程包括以下步骤:

  1. 采集图像:从不同角度拍摄标定板的图像。
  2. 检测特征点:在图像中检测标定板的特征点(如棋盘格的角点)。
  3. 建立对应关系:将图像中的特征点与标定板的已知 3D 坐标对应起来。
  4. 优化求解:通过最小化重投影误差,求解相机内参和畸变系数。

4. 重投影误差

重投影误差是标定的关键指标,表示标定板的 3D 点投影到图像平面后与实际检测到的 2D 点之间的距离。标定的目标是最小化重投影误差:

误差=i=1npip^i2\text{误差} = \sum_{i=1}^{n} \| \mathbf{p}_i - \hat{\mathbf{p}}_i \|^2

其中:

  • pi\mathbf{p}_i 是实际检测到的 2D 点。
  • p^i\hat{\mathbf{p}}_i 是通过相机模型投影得到的 2D 点。

5. 标定步骤

以下是相机内参标定的具体步骤:

  1. 准备标定板:使用棋盘格或圆点阵列作为标定板。
  2. 采集图像:从不同角度拍摄标定板的图像(通常需要 10-20 张)。
  3. 检测特征点:使用 OpenCV 或其他工具检测标定板的特征点。
  4. 建立 3D-2D 对应关系:将标定板的 3D 坐标与图像中的 2D 点对应起来。
  5. 调用标定函数:使用 OpenCV 的 calibrateCamera 函数求解相机内参和畸变系数。
  6. 评估标定结果:检查重投影误差,确保标定精度。

6. 示例代码(OpenCV)

以下是使用 OpenCV 进行相机内参标定的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import numpy as np
import cv2

# 1. 准备标定板的 3D 坐标
square_size = 1.0 # 棋盘格方块的尺寸(单位:任意)
pattern_size = (9, 6) # 棋盘格内角点数量
objp = np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
objp *= square_size

# 2. 存储 3D 点和 2D 点
objpoints = [] # 3D 点
imgpoints = [] # 2D 点

# 3. 读取标定图像
images = ["calib1.jpg", "calib2.jpg", "calib3.jpg"] # 标定图像路径

for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 检测棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)

if ret:
objpoints.append(objp)
imgpoints.append(corners)

# 可视化角点
cv2.drawChessboardCorners(img, pattern_size, corners, ret)
cv2.imshow("Corners", img)
cv2.waitKey(500)

cv2.destroyAllWindows()

# 4. 标定相机
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

# 5. 输出结果
print("相机内参矩阵 K:\n", K)
print("畸变系数 dist:\n", dist)
print("重投影误差:", ret)

7. 输出结果

  • 相机内参矩阵 KK:包含焦距和主点坐标。
  • 畸变系数 distdist:包含径向和切向畸变系数。
  • 重投影误差:表示标定的精度,误差越小越好。

8. 注意事项

  • 标定板的质量:标定板的角点检测必须准确。
  • 图像数量:通常需要 10-20 张图像以确保标定精度。
  • 图像角度:标定图像应覆盖不同的角度和位置,以提高标定鲁棒性。

通过上述方法,可以完成相机内参标定,并获得相机的内部参数和畸变系数。

Powered By Valine
v1.5.2