点云配准

把一片点云对齐到另一片上,输出 4×4 变换矩阵。算法用 KISS-Matcher 的流程(FPFH + 图剪枝)和 TEASER++ 的鲁棒求解(GNC-TLS + COTE),不需要初始位姿,也不需要装任何东西。

源点云(待配准)

要被移动的那一片。输出的矩阵作用在它身上。

还没加载

目标点云(参考)

保持不动的参考系。

还没加载

怎么用

  1. 源点云放进左边(会被移动),目标点云放进右边(参考系保持不动)。
  2. 体素边长会自动填好;两片点云重叠区域大、有几何纹理就不用改。
  3. 点「开始配准」,等结果出来看一眼重合度和 RMSE。
  4. 要的话下载对齐后的点云,或者把 4×4 矩阵粘到「点云坐标系转换」里继续处理。

算法:KISS-Matcher 的流程 + TEASER++ 的求解器

配准这件事的难点不在「解方程」,而在「对应点里有大量是错的」。逐点最近邻匹配在实测数据里错配率常常过半,直接用最小二乘求解会被离群点带飞到完全错误的位置。所以整条链路的关键是先把错的对应点筛掉,再在剩下的点上求位姿。

  • 体素降采样:按体素边长把点云抽稀成关键点,同时把噪声上界定下来(KISS-Matcher 里所有阈值都是体素的倍数)。
  • FPFH 33 维描述子:每个关键点用一个局部几何直方图表示,转过来、挪过去,描述子的值不变 —— 这正是它能跨视角匹配的原因。
  • 互检匹配 + 比值检验:源到目标、目标到源两个方向都成立才留下,两个最近邻太接近时丢掉。走廊、栅栏这类重复结构里,这一步能砍掉大部分错配。
  • 图剪枝(ROBIN 的 max-core):把「距离关系互相一致」的对应点连成图,取最大 k-核。真的对应点彼此之间的距离差只在噪声量级,错误对应几乎不可能同时满足,于是在图上落到低核层被剪掉。
  • GNC-TLS 求旋转:在相邻对应点构成的差分(TIM)上做逐步收紧的截断最小二乘,唯一解由 SVD 给出,权重在内外点之间自动拉开。
  • COTE 求平移:三个轴各自做一维「区间覆盖最多」的投票,某个轴的离群值不会污染另外两个轴。
  • ICP 精修:鲁棒解已经很接近了,再用最近邻 ICP 把残差压到体素量级以下。

这套流程来自 MIT-SPARK 的 KISS-Matcher(参数命名也沿用它:法向半径 3×体素、FPFH 半径 5×体素、剪枝噪声界 1×体素、求解噪声界 0.75×体素)和 TEASER++ 的 GNC-TLS / COTE 求解器。这个页面用 TypeScript 重写了同样的算法并在浏览器里运行 —— 好处是不用下载 WASM、打开就能用;代价是百万点级别的规模还不是它的强项。

参数怎么调

参数什么时候改
体素边长唯一必须理解的旋钮。太小 → 关键点多、慢,且描述子被噪声主导;太大 → 几何细节被抹平,匹配失去区分度。点数多到算不动时,页面会自动加大它并告诉你最终值。
关键点上限控制计算量。2000~3000 是浏览器里的舒适区。
对应点上限图剪枝是 O(n²),这个值越大越准但越慢。
比值检验重复结构多(长走廊、栅栏、货架)时保持开启;场景特征很独特、对应点太少时可以关掉试试。
ICP 精修默认开启。如果你的点云本身噪声很大,ICP 可能把结果往噪声上拉,这时可以关掉对比一下。

结果怎么看

  • 重合度:对齐后源点云里有多少比例的点在目标点云的 1.5 倍体素内。低于 60% 基本可以认为没配上。
  • RMSE:这些点的平均最近邻距离。两片点云的体素格本来就错开,所以 RMSE 的下限就是体素量级,不必追求 0。
  • 内点数:鲁棒求解器最后认可了多少对对应点。它和「剪枝后」的比值反映了数据有多干净。
  • 旋转 / 平移:分解出来的直观量。旋转接近 0、平移接近 0 说明两片点云本来就在同一个坐标系里。

常见情况

现象通常是这个原因
重合度很低、矩阵看着完全不对两片点云没有足够重叠,或者尺度差太多(毫米 vs 米)
对应点很少(< 50)体素太大把细节抹平了,或者场景本身太光滑
结果是个 180° 翻转场景有旋转对称性(正方形房间、圆柱体);用裁剪工具先去掉对称部分
每次跑结果都在跳内点太少,说明数据本身不支持全局配准;先做粗对齐或者换用带初始位姿的方法
页面卡了十几秒关键点在 3000 以上,主线程满负荷;减少关键点上限或者加大体素

为什么坚持本地计算:标定和配准用的点云经常带客户现场坐标、未公开的场地数据。这个工具没有后端,文件不会离开你的浏览器。代价是计算能力受限于你的机器 —— 也正因如此,参数默认值都往「能在几秒内跑完」的方向调。