4. RGB相机标定实战
RGB相机标定是RGBD传感器融合、三维重建、视觉SLAM和测量系统中最基础也最关键的一步。标定的本质是求解相机从三维世界坐标到二维像素坐标的投影关系,即内参矩阵(焦距、主点、倾斜因子)和畸变系数(径向畸变与切向畸变)。本章将围绕“图像采集—角点检测—参数求解—重投影误差评估—结果输出”的完整链路展开,分别给出OpenCV(Python/C++)与MATLAB两种实现路径,并结合实际案例说明标定板设计、图像数量选择、误差阈值判定等工程要点。
4.1 标定原理与数学模型
RGB相机标定基于针孔成像模型,世界坐标系下的三维点 \(P_w = [X, Y, Z]^T\) 通过刚体变换(外参:旋转矩阵 \(R\) 和平移向量 \(t\))转换到相机坐标系,再经透视投影归一化到图像平面,最后通过内参矩阵映射到像素坐标系。完整投影公式为:
s * [u, v, 1]^T = K * [R | t] * [X, Y, Z, 1]^T
其中 \(K = \begin{bmatrix} f_x & \gamma & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix}\),\(f_x, f_y\) 为归一化焦距(单位像素),\((c_x, c_y)\) 为主点坐标,\(\gamma\) 为倾斜因子(通常近似为0)。实际镜头存在非线性畸变,主要包括径向畸变(桶形/枕形)和切向畸变(镜头与传感器不平行导致)。OpenCV采用Brown-Conrady模型,畸变系数向量为 \([k_1, k_2, p_1, p_2, k_3]\),其中 \(k_1, k_2, k_3\) 为径向畸变系数,\(p_1, p_2\) 为切向畸变系数。标定过程即通过多组已知三维角点坐标与其对应的二维像素坐标,联合优化内参、外参和畸变系数,使重投影误差最小化。
4.2 标定板设计与图像采集规范
标定板是标定精度的物理基础。工程中常用棋盘格(Checkerboard)和圆点阵列(Circle Grid)两种。棋盘格角点检测鲁棒性高,但需要保证图案不反光、边缘清晰;圆点阵列对运动模糊更敏感,但亚像素定位精度更高。推荐使用A3或A4尺寸的陶瓷或玻璃基板,方格边长10~30mm,精度要求±0.01mm。图像采集需遵循以下规范:
| 采集要求 | 推荐值 | 原因说明 |
|---|---|---|
| 图像数量 | 15~25组 | 过少导致欠约束,过多增加计算量且可能引入低质量图像 |
| 姿态变化 | 俯仰/偏航/滚转各变化20°~70° | 保证内外参可观测性,避免退化配置 |
| 标定板占视场 | ≥60% | 角点分布充分覆盖图像边缘,提高畸变估计精度 |
| 光照条件 | 均匀、无高光、无阴影 | 避免角点检测偏移或误检 |
| 对焦状态 | 清晰对焦,无运动模糊 | 模糊图像导致角点定位误差增大 |
| 标定板平面度 | 平整无弯曲 | 平面度误差直接引入系统偏差 |
采集时建议固定相机光圈和焦距,标定过程中不得改变镜头参数。手持标定板缓慢移动,每变换一个姿态拍摄一张,避免连续视频帧抽取(帧间姿态变化太小)。
4.3 OpenCV标定实战流程(Python)
OpenCV提供完整的标定函数链,核心步骤分为四步:角点检测、亚像素细化、参数求解、误差评估。以下给出可直接运行的Python代码框架:
import cv2
import numpy as np
import glob
# 1. 准备棋盘格角点世界坐标(假设方格边长25mm)
CHECKERBOARD = (9, 6) # 内角点数
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 = [] # 像素坐标
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)
# 亚像素精细化
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners2)
cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)
cv2.imshow('Corners', img)
cv2.waitKey(50)
cv2.destroyAllWindows()
# 2. 标定求解
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
objpoints, imgpoints, gray.shape[::-1], None, None)
# 3. 重投影误差评估
total_error = 0
for i in range(len(objpoints)):
imgpoints_proj, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i], imgpoints_proj, cv2.NORM_L2) / len(imgpoints_proj)
total_error += error
rms_error = total_error / len(objpoints)
print(f"RMS重投影误差: {rms_error:.4f} px")
print(f"内参矩阵:\n{mtx}")
print(f"畸变系数: {dist.ravel()}")
代码中calibrateCamera返回的mtx为3×3内参矩阵,dist为5维畸变向量。重投影误差计算方式为:将世界角点通过标定结果投影回像素平面,计算与检测角点的欧氏距离,取所有角点的平均。工程上RMS误差小于0.1像素为优秀,小于0.3像素可接受,超过0.5像素需检查图像质量或标定板精度。
4.4 MATLAB Camera Calibrator 可视化标定
MATLAB提供交互式App——Camera Calibrator,适合快速验证和教学演示。操作流程为:在App中导入标定板图像→设置棋盘格尺寸→自动检测角点→剔除异常图像→标定求解→查看误差分析。MATLAB的优势在于可视化诊断:可查看每张图像的角点检测覆盖图、重投影误差直方图、相机与标定板相对位姿三维视图。关键参数输出包括:
- IntrinsicMatrix:转置后的内参矩阵(MATLAB约定为\(K^T\))
- RadialDistortion:\([k_1, k_2, k_3]\)
- TangentialDistortion:\([p_1, p_2]\)
- MeanReprojectionError:平均重投影误差(像素)
MATLAB还支持“Export”功能生成包含标定参数的MAT文件或C代码,便于后续集成。对于批量图像处理,也可使用estimateCameraParameters函数以脚本方式运行,与App结果一致。
4.5 案例拆解:工业质检相机标定与误差优化
背景与约束:某3C产线需要测量手机中框平面度,使用500万像素工业相机(2448×2048)搭配8mm镜头,工作距离300mm,视场约200mm×170mm。要求测量重复性±0.02mm,因此标定重投影误差必须控制在0.05像素以内。
初始现象:首次标定使用12张棋盘格图像,RMS误差为0.18像素,测量系统重复性仅±0.05mm,不满足要求。分析发现:图像中棋盘格仅占视场的40%,且所有图像标定板均位于画面中心区域,边缘畸变未被充分激励。
优化措施:
- 重新设计标定板:采用A3尺寸,方格边长20mm,内角点15×11,确保标定板覆盖视场80%以上。
- 增加图像数量至20张,并强制标定板出现在画面四角和边缘位置,俯仰角变化范围扩大至15°~65°。
- 使用LED漫射光源消除反光,并固定光圈F8保证景深。
- 在OpenCV中启用
CALIB_ZERO_TANGENT_DIST标志先估计径向畸变,再放开切向畸变联合优化。
结果对比:优化后RMS误差降至0.042像素,测量重复性提升至±0.015mm。进一步分析发现,第17张图像因轻微运动模糊导致角点检测偏差,剔除后RMS降至0.038像素。最终内参输出为:\(f_x=3452.8, f_y=3450.3, c_x=1223.5, c_y=1024.1\),畸变系数\(k_1=-0.112, k_2=0.085, p_1=0.0003, p_2=-0.0002, k_3=-0.021\)。
4.6 常见误区与复盘总结
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 图像数量不足10张 | 内参过拟合,外参不稳定 | 至少15张,姿态多样化 |
| 标定板始终在画面中央 | 边缘畸变估计不准 | 让标定板出现在画面各个区域 |
| 忽略亚像素细化 | 角点精度仅±0.5像素 | 必须使用cornerSubPix或MATLAB自动细化 |
| 标定后改变光圈/焦距 | 内参失效 | 标定与使用保持相同镜头设置 |
| 只关注RMS不检查单张误差 | 个别异常图像拉高整体误差 | 逐张查看误差分布,剔除离群图像 |
| 忽略标定板平面度 | 系统误差无法通过算法消除 | 使用刚性基板,定期校验 |
复盘要点:RGB相机标定是“数据质量决定结果上限”的典型任务。无论使用OpenCV还是MATLAB,核心都在于获取高质量的角点对应关系。建议建立标定图像质量检查清单:每张图像检查角点检测是否完整、是否有高光/阴影、标定板是否清晰对焦。标定完成后,应保存内参和畸变系数为JSON或YAML文件,并在后续RGBD融合中直接加载,避免重复标定。对于温度变化大的环境,需定期重新标定,因为镜头热胀冷缩会改变焦距和主点位置。