3、相机标定:内参、外参、畸变模型(径向与切向)、标定板设计与OpenCV标定流程

相机标定是双目立体视觉系统中决定深度估计精度的基石环节。无论是工业检测、机器人导航还是三维重建,如果相机内参、外参和畸变系数存在偏差,后续的极线校正、立体匹配和三角测量都会产生系统性误差。本章将系统讲解针孔模型下的内参与外参物理意义、径向与切向畸变的数学表达、标定板的设计规范,以及基于OpenCV的完整标定流程与实战排障方法。

相机标定核心链路与畸变模型 世界坐标系 (Xw, Yw, Zw) 外参 R,t 相机坐标系 (Xc, Yc, Zc) 内参 K 图像坐标系 (u, v) 像素 畸变模型 校正后理想像素 (u', v') 畸变模型 径向畸变: k1, k2, k3 切向畸变: p1, p2 桶形/枕形 + 透镜装配误差 标定板设计要点 • 棋盘格 10x7 或 12x9 • 方格尺寸 20-30mm • 平面度 < 0.1mm,哑光打印 1. 采集 15-25 张图像 不同角度/距离/光照 2. findChessboardCorners 亚像素角点提取 3. calibrateCamera 重投影误差 < 0.1px 输出 K, D, R, t

上图展示了从世界坐标系到像素坐标系的完整映射链路。外参将世界点变换到相机坐标系,内参将相机坐标投影到像素平面,而畸变模型则描述了实际镜头与理想针孔之间的偏差。理解这条链路是标定工作的前提。

3.1 核心原理:针孔模型与内外参的物理意义

理想情况下,相机成像遵循针孔模型。设世界坐标系中一点 Pw = (Xw, Yw, Zw),经过外参矩阵 [R|t] 变换到相机坐标系 Pc = (Xc, Yc, Zc),再通过内参矩阵 K 投影到像素平面 (u, v)。整个过程可表示为:

Zc * [u, v, 1]^T = K * [R|t] * [Xw, Yw, Zw, 1]^T

内参矩阵 K 包含焦距 fx、fy(单位像素),主点坐标 cx、cy,以及倾斜因子 s(通常为0)。焦距的物理意义是镜头光心到成像平面的距离,而主点则是光轴与成像平面的交点。对于双目系统,左右相机的内参通常不同,需要分别标定。

外参矩阵描述相机在世界坐标系中的位姿。旋转矩阵 R 由三个欧拉角(或四元数)构成,平移向量 t 表示相机光心在世界坐标系中的位置。在双目系统中,左右相机之间的相对外参(Rstereo, tstereo)是立体校正和深度计算的关键参数。

关键理解:内参是相机自身的固有属性,不随相机移动而改变;外参则描述了相机在空间中的位置和朝向。标定的本质就是通过已知空间点(标定板角点)和对应像素坐标,反向求解这些参数的最优估计。

3.2 畸变模型:径向与切向的数学表达

实际镜头并非完美针孔,存在两类主要畸变:

  • 径向畸变:由透镜形状引起,光线在远离中心处弯曲更严重。表现为桶形畸变(负值)或枕形畸变(正值)。用 k1、k2、k3 三个系数描述,其中 k3 通常用于鱼眼镜头,普通镜头可设为0。
  • 切向畸变:由透镜与成像平面不平行引起,源于装配误差。用 p1、p2 两个系数描述。

畸变校正的数学模型如下(以归一化坐标 xdist, ydist 表示):

r^2 = x^2 + y^2
x_dist = x * (1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p1*x*y + p2*(r^2 + 2*x^2)
y_dist = y * (1 + k1*r^2 + k2*r^4 + k3*r^6) + p1*(r^2 + 2*y^2) + 2*p2*x*y

OpenCV 的 calibrateCamera 函数默认优化 5 个畸变系数(k1, k2, p1, p2, k3)。对于双目系统,建议先单独标定每个相机,再使用 stereoCalibrate 优化双目标定参数。

畸变类型系数典型表现校正方法
径向畸变k1, k2, k3直线变曲线,边缘明显多项式拟合
切向畸变p1, p2图像倾斜,中心偏移透视校正

3.3 标定板设计与采集规范

标定板的质量直接影响标定精度。推荐使用高精度棋盘格或圆点阵列板,设计要点如下:

  1. 棋盘格尺寸:建议 10x7 或 12x9 内角点,方格边长 20-30mm。过小的棋盘格会导致角点提取不稳定,过大则难以在视野中完整呈现。
  2. 平面度:标定板必须平整,平面度误差应小于 0.1mm。建议使用玻璃基板或铝基板,避免使用纸板(易弯曲)。
  3. 表面处理:哑光打印,避免反光。黑白格对比度要高,边缘清晰。
  4. 采集数量与角度:至少采集 15-25 张图像,覆盖不同角度(倾斜 20°-30°)、不同距离(近、中、远)和不同位置(画面四角与中心)。
常见误区:不要只采集正对相机的图像,这样无法解算出畸变系数。必须包含倾斜视角的图像,才能充分激励径向和切向畸变参数。

3.4 OpenCV 标定流程与实战案例

以下是一个完整的 OpenCV 标定流程,以 Python 为例:

import cv2
import numpy as np
import glob

# 1. 准备标定板角点坐标(世界坐标系)
CHECKERBOARD = (10, 7)  # 内角点数
square_size = 25.0  # 方格边长 mm
objp = np.zeros((CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
objp *= square_size

objpoints = []  # 世界坐标
imgpoints = []  # 像素坐标

# 2. 遍历图像提取角点
images = glob.glob('calib_images/*.jpg')
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, None)
    if ret:
        objpoints.append(objp)
        corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1),
                                    (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
        imgpoints.append(corners2)
        cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)
        cv2.imshow('Corners', img)
        cv2.waitKey(100)

cv2.destroyAllWindows()

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

# 4. 评估重投影误差
total_error = 0
for i in range(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
    total_error += error
print(f"平均重投影误差: {total_error/len(objpoints):.4f} px")

# 5. 保存参数
np.savez('camera_params.npz', mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)

案例:工业双目系统标定实战

某汽车零部件检测项目需要测量螺栓孔间距,精度要求 ±0.05mm,工作距离 300mm。使用两台 500 万像素工业相机(像元 2.2μm,焦距 12mm),基线距离 120mm。

初始现象:直接使用出厂内参进行立体匹配,深度误差达到 ±2mm,远超标要求。

分析过程:检查发现出厂内参未考虑镜头畸变,且相机在运输过程中可能发生微小位移。决定重新标定。

操作步骤:

  1. 设计 12x9 棋盘格,方格边长 20mm,玻璃基板,平面度 0.05mm。
  2. 左右相机各采集 20 张图像,覆盖视野四角、中心及倾斜 25° 视角。
  3. 分别标定左右相机,重投影误差均小于 0.08px。
  4. 使用 stereoCalibrate 计算双目标定参数,得到 Rstereo 和 tstereo。
  5. 进行立体校正,验证极线误差小于 0.5px。

结果对比:重新标定后,深度误差降至 ±0.08mm,满足检测要求。同时发现切向畸变系数 p1=0.0023,说明镜头装配存在轻微倾斜,若不校正将导致边缘区域测量偏差。

风险与代价:标定过程耗时约 1 小时,但换来了 25 倍的精度提升。后续每季度需复标一次,防止温度变化或振动导致参数漂移。

经验总结:标定不是一次性工作。在双目系统中,建议每次开机后先做一次快速校验(拍摄一张标定板图像,计算重投影误差),若误差超过 0.15px 则触发重新标定。

3.5 常见误区与排障指南

误区现象解决方案
标定板不平整重投影误差大,边缘角点偏差明显更换玻璃基板,使用水平仪验证
图像数量不足参数过拟合,新视角误差大增加至 20 张以上,覆盖更多角度
忽略切向畸变图像中心区域校正良好,边缘倾斜启用 p1, p2 参数
标定板反光角点提取失败或偏移使用哑光板,调整光源角度
分辨率变化标定参数失效标定时的分辨率必须与使用时一致

排障时,首先检查重投影误差是否小于 0.1px。若误差偏大,逐张查看角点提取结果,剔除模糊或遮挡严重的图像。同时注意,标定板在图像中的尺寸应占画面的 20%-80%,过小或过大都会影响角点提取精度。

最后,标定参数的验证不能只看重投影误差,还应通过立体校正后的极线约束来验证。极线误差(左右图像对应点的垂直坐标差)应小于 1px,这是双目系统标定质量的最终检验标准。