传感器标定基础:内参标定、外参标定、标定工具与流程、常见问题排查
各位同学,欢迎来到《感知联调实战避坑指南》的第一章。
说实话,标定这件事,在很多人眼里就是个「配准」的活儿。但我在项目里摔过跟头之后才明白——标定没做好,后面所有感知算法都是空中楼阁。你想想看,相机看到的目标在像素坐标,激光雷达扫到的点在雷达坐标系,这两者如果对不上号,融合出来的结果就是「四不像」。
今天我们就来把标定的底子打扎实。我会从内参、外参、工具流程、再到常见坑点,一条一条捋清楚。
1. 内参标定:相机与激光雷达各自「认清自己」
内参标定,说白了就是让传感器知道「我是谁,我长什么样」。每个传感器出厂时都有理论参数,但实际安装、温度变化、震动都会让参数跑偏。所以我们必须重新标定。
1.1 相机内参标定
相机内参包括:焦距(fx, fy)、主点(cx, cy)、畸变系数(k1, k2, p1, p2, k3)。
我习惯用棋盘格标定板。为什么?因为角点检测稳定,算法成熟。OpenCV 的 cv2.calibrateCamera() 就能搞定。
核心步骤:
- 拍摄 15-20 张不同角度的棋盘格图像
- 检测亚像素级角点
- 调用标定函数,得到内参矩阵和畸变系数
- 用重投影误差评估标定质量(一般 < 0.1 像素算合格)
import cv2
import numpy as np
# 棋盘格尺寸(内角点)
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)
objpoints = [] # 世界坐标系中的点
imgpoints = [] # 图像坐标系中的点
for fname in image_files:
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)
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print("内参矩阵:\n", mtx)
print("畸变系数:\n", dist)
我的小技巧: 拍摄时让棋盘格占图像面积的 1/3 到 1/2,并且覆盖图像四个角落。我曾经偷懒只拍了中心区域,结果标出来的畸变参数在边缘完全不准,后来吃了大亏。
1.2 激光雷达内参标定
激光雷达的内参相对简单,主要是:
- 激光发射器与接收器的相对位置
- 每个激光束的俯仰角、水平角偏移
- 距离测量偏移量
大部分激光雷达出厂时已经标定好了。但如果你用的是多线雷达(比如 64 线、128 线),或者自己组装的雷达,那就得重新标。
我记得有一次,项目里用的雷达因为运输震动,导致某几根激光束的角度偏了 0.1 度。结果点云投影到图像上,远处目标总是错位。排查了两天才找到原因——就是内参出了问题。
注意: 激光雷达内参标定通常需要专用靶标(如平面板、角反射器)。不要用普通墙面,因为反射强度不稳定,容易引入误差。
2. 外参标定:让传感器「对齐」到同一个坐标系
外参标定,就是求传感器之间的旋转矩阵 R 和平移向量 t。说白了,就是让相机和激光雷达「看」到同一个世界。
2.1 相机-激光雷达联合标定
这是感知系统中最常见的标定任务。我们需要找到 3D 点云到 2D 图像的投影关系。
常用的方法有两种:
| 方法 | 原理 | 精度 | 适用场景 |
|---|---|---|---|
| 靶标法 | 使用棋盘格或特制标定板,同时被相机和雷达观测 | 高(< 0.5°) | 实验室、量产线 |
| 自然特征法 | 利用场景中的角点、边缘等特征自动匹配 | 中等(1°-2°) | 现场标定、OTA 更新 |
我个人更推荐靶标法,尤其是用那种带反光标记的标定板。激光雷达打在反光标记上,回波强度会特别高,很容易和相机图像中的角点对应起来。
# 伪代码:外参标定流程
1. 采集 N 组数据(每组包含一张图像 + 一帧点云)
2. 在图像中检测标定板角点(像素坐标)
3. 在点云中提取标定板平面,计算角点的 3D 坐标
4. 使用 PnP 算法求解 R, t
5. 用重投影误差评估(一般 < 2 像素算合格)
避坑指南: 我曾经在标定时只用了 5 组数据,结果外参在某个方向上特别敏感。后来我改成至少采集 15 组不同角度、不同距离的数据,标定结果才稳定下来。记住:数据多样性比数据量更重要。
2.2 多传感器联合标定
如果你的系统里有多个相机、多个激光雷达,甚至还有毫米波雷达,那就需要做联合标定。这时候通常采用「链式标定」或「全局优化」两种策略。
- 链式标定: 先标定主传感器(如主相机)到车体的外参,再标定其他传感器到主传感器的外参。简单,但误差会累积。
- 全局优化: 把所有传感器的外参放在一起,用图优化(如 g2o、Ceres)同时求解。精度高,但计算量大。
嗯,这里要注意:链式标定适合传感器数量少(2-3 个)的场景。如果超过 4 个,我建议直接上全局优化,否则累积误差会让你怀疑人生。
3. 标定工具与流程
工欲善其事,必先利其器。我常用的标定工具有这些:
| 工具 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| OpenCV | 相机内参、单目外参 | 免费、文档全 | 不支持激光雷达 |
| Autoware Calibration Toolkit | 相机-激光雷达联合标定 | 开源、有 GUI | 依赖 ROS |
| Apollo 标定工具 | 多传感器联合标定 | 支持全局优化 | 配置复杂 |
| MATLAB Lidar Camera Calibrator | 快速原型验证 | 交互式、可视化好 | 需要 License |
标定流程我一般分三步走:
- 准备阶段: 制作标定板、搭建采集环境(光照均匀、无遮挡)
- 采集阶段: 多角度、多距离采集数据,保证覆盖整个视场
- 优化阶段: 用重投影误差、点云投影一致性等指标反复调优
我的习惯: 每次标定完,我都会做一次「验证标定」——用标定好的参数投影一帧点云到图像上,肉眼看看边缘是否对齐。如果对齐得不好,就重新采集数据再标。别嫌麻烦,这一步能省掉后面很多排查时间。
4. 常见标定问题排查
标定过程中,你大概率会遇到下面这些问题。我一个个说。
4.1 重投影误差很大
原因可能是:
- 标定板不平整(换用亚克力板或铝板)
- 图像模糊(检查快门速度,避免运动模糊)
- 角点检测不准(改用亚像素检测)
4.2 点云投影到图像上整体偏移
这通常是外参的平移向量不准。我遇到过的情况是:标定板距离太近(< 1m),导致平移量估计偏差大。建议标定距离覆盖 2m-10m。
4.3 远处目标投影偏差大
大概率是激光雷达内参(角度偏移)没标好。或者相机畸变参数在边缘区域不准。解决办法:重新标定相机内参,或者用更多边缘数据优化。
4.4 标定结果时好时坏
嗯,这个问题最让人头疼。我排查过几次,发现原因往往是:
- 数据采集时传感器有微小震动(用三脚架固定)
- 标定板反光不均匀(换用哑光材质)
- 算法初始化不好(换个初始值试试)
重要提醒: 标定不是一劳永逸的。车辆行驶一段时间后,螺丝松动、温度变化都会导致外参漂移。我建议每 3 个月或每 1 万公里做一次标定校验。如果发现感知结果异常,优先检查标定参数。
知识体系总览
最后,我用一张图把本章的核心逻辑串起来。你一看就明白标定在整个感知系统中的位置了。
好了,这一章的内容就到这里。标定是感知系统的「地基」,地基不稳,上层建筑再漂亮也没用。下一章我们会深入聊聊相机和激光雷达的联合标定实操,到时候我会带上具体的代码和踩坑记录。
可可精品资料库