单目相机标定是计算机视觉中最基础却最关键的环节。简单来说,标定就是通过一系列已知空间坐标的物体(通常是棋盘格),计算出相机的内部参数(焦距、主点坐标、畸变系数等)和外部参数(相机在世界坐标系中的位置和方向)。
棋盘格作为最常用的标定板,其选择有讲究:
实际经验:我曾用普通打印纸制作的棋盘格,在空调房和室外温差大的环境下,标定结果差异达到15%。后来改用铝板蚀刻的标定板,稳定性大幅提升。
原始代码中几个关键点需要特别注意:
python复制# 角点精细化参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
这个停止条件决定了角点搜索的精度:
MAX_ITER=30表示最多迭代30次EPS=0.001表示当位置变化小于0.001像素时停止角点检测的完整流程应该是:
findChessboardCorners找到粗略角点位置cornerSubPix进行亚像素级精细化标定完成后,必须进行严格的验证:
python复制# 计算重投影误差
mean_error = 0
for i in range(len(obj_points)):
img_points2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(img_points[i], img_points2, cv2.NORM_L2)/len(img_points2)
mean_error += error
print("平均重投影误差: {}".format(mean_error/len(obj_points)))
重投影误差的判断标准:
0.5像素:需要重新标定
常见问题排查:
双目标定不仅需要分别标定两个相机,还需要精确计算两个相机之间的相对位置关系(旋转矩阵R和平移向量T)。
python复制ret, _, _, _, _, R, T, E, F = cv2.stereoCalibrate(
obj_points, img_points_l, img_points_r,
mtx_l, dist_l, mtx_r, dist_r,
image_size, criteria=criteria, flags=cv2.CALIB_FIX_INTRINSIC)
关键输出参数:
特别注意:T向量的第一个分量(通常是水平方向)决定了双目系统的基线长度,直接影响深度测量范围。
标定后必须进行极线校验:
python复制# 立体校正
R1, R2, P1, P2, Q, _, _ = cv2.stereoRectify(
mtx_l, dist_l, mtx_r, dist_r,
image_size, R, T)
# 计算极线
lines_r = cv2.computeCorrespondEpilines(img_points_l, 1, F)
验证标准:
常见问题解决方案:
视觉-惯性系统(VINS)的核心挑战在于解决传感器间的时空对齐问题。
时间不同步会直接导致运动估计偏差,处理方法:
硬件同步:使用PPS信号或硬件触发确保时间戳对齐
软件估计:将时间偏移作为标定参数优化
python复制# 时间偏移估计模型
def imu_to_camera_time(imu_time):
return imu_time + time_delay
运动激励:采集数据时需要充分的旋转和平移运动,特别是高频运动有助于时间偏移估计
手眼标定解决的是相机与IMU之间的外参标定问题,主要分两种情形:
使用Kalibr工具箱时的注意事项:
典型问题排查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 轨迹发散 | 时间不同步 | 重新估计时间偏移 |
| 尺度漂移 | IMU偏置不稳定 | 延长预热时间 |
| 旋转偏差 | 外参旋转不准 | 增加旋转运动数据 |
| 位置跳变 | 特征跟踪丢失 | 检查图像曝光和模糊 |
环境控制:
运动模式:
数据量:
硬件问题:
数据问题:
算法问题:
多阶段标定:
在线标定:
标定自动化:
在实际项目中,我发现最容易被忽视的是环境因素。曾经有一个室内定位项目,标定时空调开启,而实际使用时关闭空调,温度变化导致IMU偏置变化,最终定位误差增加了3倍。后来我们建立了环境-参数对照表,在不同温度下进行标定,使用时根据实时温度选择最接近的参数集,效果显著提升。