☰
激光雷达与相机联合标定:手动选点、数据采集与时间同步
2026/10/7 9:16:52 网站建设 项目流程

上周一个做园区配送小车的老哥给我发了张截图:16线激光雷达的点云投到相机画面上,近处路沿贴得严丝合缝,越往远处越离谱,二十米外的楼角整整歪出去半个车身。他一口咬定是相机内参没标好,准备重新拿棋盘格折腾一遍。我看了眼那几张叠加图就说,先别急,这大概率不是内参的事——"近处准、远处飞"这个特征,八成是标定选点时所有点对都挤在同一个高度区间里,俯仰和翻滚两个角压根没被约束住。他照着重选了一组高低错落的点,重新解算,十分钟搞定,误差从肉眼可见的几十像素压到三像素以内。

类似的事我见过太多次了。激光和相机的联合标定听起来是个高深的数学活,实际上大部分翻车都发生在"选点"和"数据采集"这两个看起来最没技术含量的环节。而手动标定恰恰是在这些环节里最可控的一条路:你亲手决定哪个角、哪根杆、哪个点参与计算,错了能立刻定位到具体是哪一对点出了问题。下面这套流程,是我自己反复用过、也给同事交接过好几轮的方法,从上位机的环境准备一路讲到参数落盘,中间会穿插大量只有真踩过才知道的细节。

1. 手动标定还没被淘汰:它到底解决什么问题

现在自动标定工具确实越做越省事,无靶标、基于边缘互信息、基于深度连续性的方法一抓一大把,很多还带一键优化。但我在实际项目里发现,自动方法有个共同前提:它假设场景里有足够多、足够规整的几何结构,比如笔直的建筑立面、清晰的道路标线、成片的立柱。园区、厂区、高速这类结构化环境没问题,可一旦场景换成树丛、堆放杂乱的货物、临时搭建的棚子,自动方法的优化就容易跑偏,甚至收敛到一个看起来误差很小但物理上完全错误的结果。

1.1 三种必须手动介入的现实场景

第一种是传感器安装位置特殊。我遇到过把激光雷达装在车顶、相机装在车头保险杠的情况,两者基线接近两米,还有明显的俯视和侧倾。这种大外参自动标定很难收敛,因为视角差异太大,同一个物体在两路数据里的形态完全不同,互信息这类相似度度量会失效。

第二种是验证阶段需要独立证据。自动标定的输出是一个数字,你凭什么信它?手动标定天然带一组人工确认过的对应点,你可以拿它们算重投影残差,作为独立的第三方证据。我现在的习惯就是:自动标定先跑一遍拿初值,再手动挑十来个点验算,误差对得上才敢上车。

第三种是现场急救。设备在客户那边跑着,突然发现标定漂了,手边没有标定板、没有标定场地、甚至没有合适的软件,这时候能救场的只有手动标定——有一段历史数据包,有一张能看清的图像,就能干活。

1.2 手动、自动、半自动:一条务实的选型线

我不建议把这三者对立起来,它们更像是流水线上的不同工位。我自己的选型逻辑是这样的:

方法类型适用阶段典型耗时精度量级主要风险
纯自动(无靶标)批量产线、定期复检几分钟中等,依赖场景结构场景退化时静默失败
自动 + 靶标出厂标定、精度要求高十几分钟高需要靶标和场地
半自动(自动初值 + 手动微调)现场部署、返修半小时左右高,且可解释依赖操作者经验
纯手动选点应急、特殊安装、验证二十分钟到一小时取决于选点质量人为疏漏

我个人的主力方案是半自动:先用一次快速自动标定拿到初值,然后把初值丢进可视化界面,手动点几对点做残差检查,最后用手动微调把手感不对的自由度掰回来。纯手动从头做的情况,主要是没有自动工具可用,或者要对自动结果做独立复核。

1.3 别混为一谈:激光-相机标定和手眼标定、双目标定根本不是一回事

这个词经常被人搅在一起。双目相机标定解的是两个相机之间的相对位姿,输入是两幅图像上同一特征点的像素坐标,输出是相机间的旋转平移,同时还顺手把各自的内参和畸变一起标了。手眼标定(比如机械臂加相机)解的是相机坐标系和机械臂末端或基座坐标系的关系,它的核心难点在于机械臂要带动相机做多组不同位姿的运动,用多组"Ax=XB"形式的方程去解,纯靠单次静态观测是解不出来的。而激光-相机标定,在这篇文章的语境里,是求激光雷达坐标系到相机坐标系的一个固定刚体变换,输入是同一物理点在两个坐标系下的坐标——点云里的三维坐标和图像里的二维像素坐标——输出是六自由度的外参。

分清这一点非常重要,因为它直接决定了你需要什么数据。激光-相机标定不需要机器人做运动,不需要多组位姿,只要一次静态观测、一组对应点就够了。反过来,如果你拿着一套手眼标定的流程去标激光和相机,会发现根本没法构造方程。

2. 动手前先定死坐标系与数据采集方案

标定翻车最隐蔽的原因,往往不是算法错了,而是两个人在说不同的事。你说"外参"指的是激光到相机,你的同事理解成相机到激光;你说"y轴向上",结果点云里是z轴向上。参数写进文件的时候没人发现,跑起来车就往沟里开。所以我把坐标约定放在最前面讲。

2.1 六个自由度的现实含义与正负号约定

外参就是六个数字:三个旋转、三个平移。旋转可以用旋转矩阵、四元数、欧拉角表示,平移就是一个三维向量。我强烈建议内部统一用旋转矩阵加平移向量,理由是矩阵乘法不会出现欧拉角那种"转序不同结果不同"的陷阱。只有在跟人交流或者写配置文件的时候,才临时转成欧拉角或四元数,并且一定要在注释里写清转序。

平移向量的物理含义是:相机坐标系原点在激光雷达坐标系下的坐标表达(如果你存的是激光到相机的话,方向正好相反)。我自己习惯这样记:定义变换 T 把激光系下的点映射到相机系,即 p_cam = R × p_lidar + t。那么 t 就是激光原点在相机系里的位置,它的逆变换对应的才是相机光心的位置。

注意:写 yaml 的时候,同一份文件里出现"lidar_to_camera"和"camera_to_lidar"两个方向是极其常见的错误来源。我的做法是文件里只留一个方向,另一个方向由程序在读取时求逆得到,杜绝两头都能写的情况。

旋转矩阵的合法性也要顺手检查:行列式应该是 1,而且 R × Rᵀ 应该接近单位阵。我见过因为手抖写错一个元素,导致点云整体被镜像的场景——图像上看着还挺像那么回事,但左右是反的,这种错误肉眼看叠加图很难发现。

2.2 采集一段"能标"的数据:场景、距离、静止与运动

数据采集这一步决定了标定的上限。我挑场景的标准有三条:有明确的直角结构、有不同高度的物体、有一定的纵深跨度。理想场地是停车场出入口或者厂区转角:有墙面(提供竖直平面)、有地面(提供水平面)、有立柱或电箱(提供竖直边缘和不同高度)、有二十米以上的视野纵深。

对应点的分布范围,我一般控制在五米到三十米之间。太近的点受激光光斑尺寸和相机近场畸变影响大,太远的点受激光角分辨率限制——十六线雷达在三十米外相邻线束的垂直间距能到半米以上,你根本没法从点云里准确判断某个角点的三维位置。中间这个区间的点,三维坐标和像素坐标都相对可靠。

静止还是运动,这也是个取舍。静止采集最省事,不用做去畸变,时间戳对齐的压力也小。但如果标定的最终用途是运动中的感知,我会额外采一段运动中低速行驶的数据做复验,因为这时候才能暴露出那些只在动态下才显现的问题。低速是指十公里每小时以内,超过这个速度,机械旋转式雷达的点云会被明显拉扯变形。

采数据的时候,记得把相机的自动曝光、自动白平衡、自动增益全关掉。自动曝光在画面里进出一辆车就会改变亮度,虽然不影响几何,但你手动点像素的时候对边缘的判读会受影响。而且关掉自动之后,图像亮度是固定的,后面用同一套参数复验时对比起来更干净。

2.3 时间同步:从硬触发到软对齐的实际取舍

时间不同步的直接表现是:静止时标得挺准,车一动就整体漂移,而且漂移方向和运动方向相关。原因很简单,激光点和图像帧根本不是同一时刻的。

硬件同步是最干净的方案:用同一路触发信号同时驱动相机曝光和雷达旋转起始,两路数据带着同源的时间基准。但这需要硬件支持,很多改装车上没有。没有硬件同步时,退而求其次的做法是软件同步加静止采集——采集时车停稳,触发相机抓一帧,记录下这一帧的时间戳,然后在点云里找时间戳最接近的那一帧,中间的时间差控制在十毫秒以内。车停着的时候,十毫秒的时间差不会带来任何几何误差。

如果必须用运动中的数据,那就得做时间对齐:把点云按每一条线束的相对时间戳做运动补偿,用轮速计或惯性单元的信息把每个点外推到统一时刻。这块工作量和风险都不小,我一般建议能静止采集就静止采集,把复杂度留到后期。

3. 从选点到求解:一套可复现的手动标定流程

前面铺垫完了,这里是正文重点。整套流程可以概括成:**在点云里点N个点,在图像里点N个对应点,把两组坐标丢给求解器,看残差,不满意就回去重选。**听起来简单,但每一步都有讲究。

3.1 环境准备与工具盘点

我常用的组合是 Ubuntu + ROS 环境下的可视化工具,加上一个 OpenCV 求解脚本。ROS 这边的好处是点云和图像能同时在一个界面里看,选点直观;不足是数据要走话题传输,偶尔会丢帧,所以采集阶段我习惯先用数据包把原始数据录下来,标定的时候离线回放,可重复性好,出问题也能回退。

需要的组件大致是:点云可视化工具(用来显示点云并读取鼠标点击位置的三维坐标)、图像查看工具(用来读取像素坐标)、OpenCV(解算和验证)、一个小脚本负责把两组坐标合并、求解、输出残差和投影叠加图。相机内参和畸变系数必须在标定之前拿到——这一步用棋盘格或者标定板单独做,属于另一个话题,但它质量直接决定外参的上限,后面会展开说。

3.2 在点云里选点的四条硬规矩

这是整个流程里最吃经验的部分。我总结成四条:

第一条,点不能共面。如果所有点都落在地面上,或者都落在一面墙上,那么沿垂直于该平面的方向上的旋转是无法被唯一确定的。经典的PnP问题在共面条件下会出现解的歧义,表现就是标定出来的俯仰角或翻滚角偶尔会跳到一个明显不对的值,重选几个高度不同的点,问题立刻消失。

第二条,优先选"角"而不是"边",优先选"竖直缘"而不是"水平缘"。竖直的柱角、电箱的棱、建筑转角,在点云里是两条线的交点,位置唯一;而水平的地面边缘在点云里就是一条带,你很难判断该选哪个点。同样,竖直边缘在图像上的像素位置比水平边缘更容易判断准,因为竖直边缘的检测对图像的横向分辨率更敏感。

第三条,避免高反光和透明物体。反光膜、水面、玻璃幕墙会让激光出现多路径回波或者直接丢点,点云上会出现一片奇怪的散点。这类地方的坐标压根不可信,选了就是往数据里掺噪声。

第四条,避开动态物体和纹理物体。行人、车辆、树叶、草地,这些要么位置会变,要么边缘模糊到无法定位。我见过有人在点云里选了棵树的树干,图像上选了个大概位置,结果那棵树被风吹得晃,标定结果自然不准。

一个实用的做法是:**先在点云里选点,记下坐标,再把点云叠加到图像上(用上一次标定的旧参数也行,有个大概位置就够),从叠加图里去找那个点对应的图像位置。**这比反过来在图像里找点云位置要容易得多,因为点云里选中的点可以在图像上打出一个候选标记,你只需要在附近做微小修正。

3.3 图像端像素坐标的取法与偏差控制

像素坐标怎么取,直接影响精度。我的一般做法是:把图像放大到四倍以上,用像素级查看器把边缘放大到能看清灰度过渡,然后取过渡带的中点。不要取最亮的一侧,也不要取最暗的一侧,取中间。这是抵消镜头模糊和边缘扩散最简单有效的办法。

取点的数量,我建议至少十二对,最好十五到二十对。理论上四对不共线的点就能解,实

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询