简介:面向机器人视觉与三维感知学习者的6D位姿估计综述资料,围绕从物体定位、姿态估计到并行夹爪抓取估计的主线,整理相关文献的思维导图,适合希望快速建立方法脉络、对比技术路线的研究者与工程人员。资源包仅含1个PDF文件,大小约434KB,将RGB-D、点云和RGB图像三类路径集中呈现:RGB-D部分涉及DenseFusion、MaskedFusion与PoseCNN,点云部分覆盖PointNet系列、Frustum-PointNet和VoxelNet,RGB部分串起PnP、模板匹配、PoseNet、PVNet与Pix2Pose等代表性工作。内容着重说明各方法的网络结构、融合策略、迭代优化思路、适用条件与局限,读者可据此梳理6D位姿估计的发展脉络,并对照机器人抓取、自动驾驶等应用选择合适方案。已有3718人学习,可作为综述与选题调研的参考。
1. 先说结论:没有全能网络,选 6D 位姿估计方案要从传感器倒推
我把 RGB-D、纯点云、纯 RGB 三条技术线的十来个代表工作挨个拆过一遍,越拆越确认一件事:6D 位姿估计里根本不存在「哪个网络最强」这种问法,只有「你的相机给什么输入、你的物体有没有纹理、你能容忍多少毫秒延迟」这三个约束。有人看到 RGB-D 方案在公开评测集上的漂亮数字,直接搬到自家单目产线上,跑起来精度崩得一塌糊涂——不是网络不行,是输入通道对不上,融合层拿不到它期待的几何分支。
这篇把这几份综述里拆出来的判断依据、横向对比表和几次真实的取舍写清楚:什么场景该用逐像素稠密融合,什么场景老老实实退回点云配准,什么场景干脆别碰深度学习。做机器人抓取选型的、刚进这个方向想少走弯路的,照着结论和后面几张表就能落地。
2. 三条路线怎么分:从输入传感器倒推算法边界
教科书喜欢按「传统方法 / 深度学习方法」切,我拆文献时更愿意按输入模态切,因为模态决定信息上限,而信息上限决定后面所有工程取舍。RGB 图有纹理没几何,深度图有几何没纹理,两者拼起来才谈得上互补;纯点云看起来信息最全,实际上丢掉了表面纹理,一遇到几何细节匮乏的物体就抓瞎。这个顺序想不明白,后面看再多的网络结构图都是白看。
2.1 先定输入再谈网络:RGB-D、纯点云、纯 RGB 的分水岭
我一般会拿三个问题过一遍候选方案,任何一个答不上来就先别急着看精度指标。第一,深度图和彩色图是否已经做过后对齐和相机内参标定?RGB-D 融合类方法默认两路输入在同一像素坐标系下,像素级拼接才有意义,对齐误差超过一两个像素,稠密融合基本就退化成噪声叠加。第二,物体的几何细节够不够丰富?如果目标是规整的工业零件、几何特征明显,纯点云加 3D 描述符配准的性价比往往高于跑一个大网络。第三,训练预算有多少?带 mask 分支、带迭代精修的方案精度好看,代价是训练时长成倍上涨,这个账后面第 4 章细算。
三条路线的边界大致是这样:RGB-D 路线吃的是「颜色嵌入 + 几何嵌入」的互补红利,对遮挡和弱纹理都有一定容忍度,但强依赖传感器质量和对齐精度;纯点云路线不依赖纹理,适合 3D 传感器直出的场景,可它天生缺表面信息,遇到「同形状不同颜色」的物体无法区分,而且点云数据量大、冗余度高、非结构化强,特征提取难、计算量大,对场景遮挡和空间形变敏感;纯 RGB 路线成本最低,单目相机就能跑,但弱纹理物体和严重遮挡是它的死穴。
| 输入模态 | 能拿到的信息 | 天然短板 | 典型适用场景 |
|---|---|---|---|
| RGB-D | 纹理 + 几何 + 尺度 | 依赖标定对齐,深度图噪声 | 桌面级抓取、近距离操作 |
| 纯点云 | 几何 + 尺度 | 无纹理,数据冗余,遮挡敏感 | 3D 传感器直出、大场景检测 |
| 纯 RGB | 纹理 + 语义 | 无绝对尺度,弱纹理失效 | 单目相机、成本敏感产线 |
这张表看着简单,实际选型时能省掉一大半无效比对。我见过不止一个团队拿纯 RGB 方案去啃无纹理金属件,调了两周把问题归到「网络不够深」,其实是模态本身就缺信息,换多大 backbone 都没用。
2.2 RGB-D 融合派:DenseFusion 的逐像素融合与 MaskedFusion 的 mask 增强
DenseFusion 是我认为在 RGB-D 这条线上把「融合」这件事做得最干净的一个。它的做法是两条分支并行:RGB 图走颜色分支求出颜色嵌入图,深度图转成点云后走几何分支求出几何嵌入,然后把两种嵌入按像素对应关系拼起来,得到逐像素的稠密融合特征。关键在于「逐像素」三个字——每一个像素位置的融合特征都独立预测一组 6D 位姿和一个置信度分数,最后一堆预测靠置信度加权投票出最终结果。
这个设计的好处很实在:当物体被部分遮挡时,被遮挡区域的像素预测置信度自然低,没被遮挡的像素照样能投出正确位姿,不需要额外写遮挡处理逻辑。它的 refinement 模块是一个迭代过程:拿上一帧算出来的位姿,对当前帧输入的点云做位移和旋转变换,再送进点云特征提取网络求嵌入,输出的是位姿残差而不是完整位姿。这里有个实践中的硬约束——refinement 必须在主网络收敛之后再单独训练,主网还在乱跳的时候同步训精修,残差估计器学到的是噪声,整条链路会越修越歪。这条我踩过,后面避坑章细说。
MaskedFusion 是在 DenseFusion 骨架上改数据融合部分的方案。它不再只喂 RGB 和 Depth,而是把输入拆成裁剪后的 RGB 图、裁剪后的深度图、裁剪后的 mask 图三路一起送进网络。多出来的 mask 通道带的是物体的形状语义信息,等于在颜色和几何之外又加了一路先验。代价很明确:训练时间变长;收益也很明确:准确度更高,而且推理时间不增加——因为多出来的计算只发生在训练阶段的融合分支里,推理时的前向路径没变长。这个「训练侧加料、推理侧不加价」的特性,在工业落地里价值很高,我在第 4 章会专门算这笔账。
2.3 纯点云派:从 PointNet 的无序性处理到 VoxelNet 的体素化代价
纯点云这条路线的起点是点云数据的三个天然缺陷:无序性、旋转敏感性、数据不均匀。PointNet 的处理方式很直接,用最大池化把无序点集压成一个全局特征,从机制上消掉了排列顺序的影响;再用一个微型变换网络学习旋转矩阵,把输入点云摆正,保证旋转不变性;最后用一组稀疏关键点代表整个输入,对小扰动和缺省值比较鲁棒。这套思路在分类、部分分割、语义分割上一起打通,是后面几乎所有点云网络的祖宗。
PointNet++ 补的是「局部特征」这一课。它在不同尺度上逐层提取局部特征,通过采样层挑代表点、组合层划邻域、特征提取层求局部描述,多尺度多分辨率的组合方式有效缓解了点云分布不均匀的问题。到了 Frustum-PointNet,思路变成先用 2D 检测算法在图像上框出目标,把对应视锥内的点云取出来,再做 3D 实例分割和边界框回归。缺陷也很清楚:它由 2D 检测、3D 分割、回归三个网络串起来,不是端到端可训的,而且 3D 分割和边界框回归只用了点云特征,白白扔掉了 2D 检测那一路的图像特征。
VoxelNet 走的是另一条路:把三维点云划分成固定数量的体素,随机采样并归一化后,对每个非空体素做特征提取,再用 3D 卷积进一步抽象,最后接区域候选网络做 3D 检测和位置回归,在公开自动驾驶基准上拿到过领先结果。但体素化的代价是显存的平方级增长,体素分辨率调细一点,显存就顶不住;调粗一点,小物体直接消失。更要命的是,一般的位姿估计任务还要求同时估计物体的几何信息和表面信息,只用点云信息根本解决不了这个问题——这就是为什么纯点云路线在抓取场景里往往只能当配准器用,当不了完整方案。
3. 六个代表网络逐项对比:融合时机、骨干网、精修方式
把三个模态路线铺开之后,真正决定成败的是三个工程维度:融合发生在哪一层、骨干网选谁、精修模块怎么接。这三件事直接对应训练难度、精度上限和推理延迟,比看论文里的 mAP 数字有用得多。下面按这三个维度把六个代表网络摆一起比。
3.1 融合时机决定信息利用率:早融合、晚融合与逐像素稠密融合
融合时机是我评判一个 RGB-D 方案的第一眼标准。早融合是把 RGB 和深度直接堆成多通道输入塞进网络,实现最简单,但两种模态的统计分布差异极大,网络前几层基本在忙着做归一化;晚融合是两条分支各自出结果再拼,实现干净但丢掉了跨模态的像素级关联;逐像素稠密融合是两条分支各自提完嵌入后按像素位置拼接,兼顾了分支独立性和跨模态关联,代价是特征图对齐要求严格。
| 网络 | 输入 | 融合位置 | 输出形式 | 后处理 |
|---|---|---|---|---|
| DenseFusion | RGB + Depth | 嵌入层后逐像素拼接 | 每像素一组位姿 + 置信度 | 置信度加权投票 + 迭代精修 |
| MaskedFusion | RGB + Depth + Mask | 三路嵌入后融合 | 每像素一组位姿 + 置信度 | 同上,mask 增强 |
| PoseCNN | RGB(+Depth 精修) | 无融合,纯 RGB 预测 | 语义分割 + 3D 位置 + 3D 旋转 | ICP 用深度图精修 |
| PointNet++ | 纯点云 | 不涉及 | 逐点/全局特征 | 下游任务头 |
| VoxelNet | 纯点云 | 不涉及 | 体素特征 + 3D 框 | 区域候选网络回归 |
| SSD-6D | 纯 RGB | 不涉及 | 多尺度特征图回归 | 视觉点 + 平面旋转映射 |
从表里能看出一个规律:真正做融合的方案(前两个)都把融合放在特征层而不是输入层,而且都保留了「逐像素预测 + 投票」这套结构。原因不复杂——单点预测在遮挡下太脆弱,多点投票才能把鲁棒性做出来。反过来,PoseCNN 干脆放弃融合,用纯 RGB 出初值,再拿深度图做 ICP 精修,把融合推迟到几何层。这两种思路没有优劣,取决于你的深度图质量:深度图噪声大,晚融合的 ICP 更稳;深度图干净,早一点的稠密融合能榨出更多精度。
3.2 骨干网与任务头:VGG16、点云特征提取器、InceptionV4 各自的取舍
PoseCNN 的结构值得单独说,它把位姿估计拆成三个任务:语义分割、3D 位置、3D 旋转,骨干网用的是 VGG16。这三个任务头分别解决「物体在哪几个像素上」「物体中心在图像上的位置和到相机的距离」「物体的旋转四元数」。语义分割给出像素级 mask,3D 位置通过定位中心点加回归距离得到平移量,3D 旋转直接回归四元数表示。它引入的 ShapeMatch-Loss 是专门为对称物体设计的——对称物体旋转 90 度看起来一模一样,用普通的位置误差损失会让网络在几个等价解之间反复横跳,ShapeMatch-Loss 在对称变换集合里取最小误差,从损失函数层面把这个歧义消掉。网络预测完之后再调 ICP,用深度图做精修,对遮挡物体的鲁棒性明显提升。
SSD-6D 走的是单阶段多尺度路线,用 InceptionV4 的分支把输入映射成六个不同尺度的特征图,每个尺度上用大小为 4+C+V+R 的卷积核去卷积。这个核尺寸拆开看很直白:4 是 2D 边界框的四个参数,C 是类别数,V 是预先定义的视觉点数量,R 是平面内旋转角的离散划分数。一次卷积同时出类别、框、视觉点和面内旋转,再通过视觉点与 3D 模型的映射关系反解 6D 位姿,速度上有优势。
关键点检测这条线是把任务解耦成两阶段:先检测 2D 图像上的关键点坐标,再用 PnP 求位姿。有一类做法是先分割出物体区域再从区域内检关键点;有受 2D 人体姿态估计启发的做法,输出像素级热力图来对抗遮挡;也有直接用单阶段检测器同时出检测框和位姿的。更细的一支是向量场投票:让物体可见部分的每个像素预测一个指向关键点的方向向量,再用随机采样一致性对关键点投票,最后和 3D 模型匹配求位姿。还有把 3D 模型坐标点编码成 RGB 值的做法——模型上每个 3D 点对应一个固定颜色,网络去预测遮挡区域的彩色图,从而建立 2D-3D 对应关系,再配一个生成模型补全被遮挡部分。分割驱动的做法则让每个可见部分都产生一个局部预测位姿,用多个局部预测替代单一全局预测,鲁棒性更好。
这条线的通病是:处理低纹理物体或低分辨率图片时性能下降明显,而且两阶段结构没法做端到端优化。这一点在选型时要提前想清楚,如果你的场景纹理丰富、分辨率够高,关键点路线性价比极高;如果是无纹理的金属件,趁早换路线。
3.3 精修模块值不值:ICP 与位姿残差估计的两条路
精修这件事有两条典型路径。一条是几何精修,网络出初值后拿深度图转点云,和物体模型点云做迭代最近点配准,把位姿往真实值上拉;另一条是学习式精修,把上一轮位姿作用到点云上,再送网络回归残差,迭代若干轮。前者不需要训练,泛化性好,但依赖初值质量;后者精度更高,但需要单独训练,且必须在主网收敛之后。
下面这段是几何精修的骨架,用 Open3D 实现,我把它当成所有 RGB-D 方案的兜底后处理:
import numpy as np import open3d as o3d def refine_pose_icp(scene_points, model_points, init_pose, max_dist=0.01, max_iters=50): """ scene_points: (N,3) 场景点云,已按分割 mask 裁剪,只保留目标物体 model_points: (M,3) 物体 CAD 模型均匀采样点云(一般取 2000~5000 点) init_pose: (4,4) 网络输出的初始位姿,作为 ICP 初值 max_dist: 对应点最大距离阈值,按物体直径的 1%~2% 取 max_iters: 最大迭代次数,50 次在桌面级物体上基本收敛 """ src = o3d.geometry.PointCloud() src.points = o3d.utility.Vector3dVector(np.asarray(scene_points)) dst = o3d.geometry.PointCloud() dst.points = o3d.utility.Vector3dVector(np.asarray(model_points)) # ICP 是局部最优算法,必须用网络位姿做初值,否则配准结果基本必崩 trans_init = np.asarray(init_pose, dtype=np.float64) reg = o3d.pipelines.registration.registration_icp( src, dst, max_dist, trans_init, o3d.pipelines.registration.TransformationEstimationPointToPoint(), o3d.pipelines.registration.ICPConvergenceCriteria( max_iteration=max_iters) ) # fitness 是重叠区域内点占比,低于 0.3 直接判该帧失败,不要硬用 return reg.transformation, reg.fitness, reg.inlier_rmse这段代码里有三个参数决定成败。max_dist是最关键的,设大了会把背景点、相邻物体的点一起吸进对应关系里,位姿被拽偏;设小了初值稍有偏差就找不到对应点,配准原地不动。我的经验值是物体直径的百分之一到百分之二,先用卷尺量一下目标物尺寸再定。max_iters不用调太大,桌面级物体五十次足够收敛,调大只是浪费时间。真正要盯的是返回的fitness,它是重叠区域内点占源点云的比例,低于 0.3 说明这一帧要么分割错了、要么初值偏到姥姥家了,这时候把结果丢给下游比强行用更安全。
学习式精修的收益在遮挡场景下更明显,因为它吃的不是几何对应关系而是特征,被遮挡部分的特征缺失可以由上下文补一部分。但它有个前提:主网络必须先收敛。主网还在震荡的时候同步训精修,残差估计器学到的是主网噪声的分布,最后表现就是「精修越修越歪」,这个坑我在第 5 章展开。
4. 精度、训练时长与推理延迟:三个指标怎么一起算
选型时最容易被忽略的是训练成本和推理延迟的不对称性。论文里报的是推理精度和推理速度,可落地时真正卡住项目的是训练周期——一个方案精度高两个点,但要训练三倍时间,在需要快速迭代验证的场景里照样出局。这一章把三个指标放一起算账。
4.1 训练侧加料、推理侧不加价:MaskedFusion 的账怎么算
MaskedFusion 相对 DenseFusion 的改动集中在数据融合部分:多喂一路裁剪后的 mask 图。多一路输入意味着融合分支的通道数变多、前向计算量变大,所以训练时间变长;但它的推理路径没有增加额外的迭代,所以预测时间基本不变。
这笔账要这么算:假设 DenseFusion 单轮训练 8 小时、需要 30 轮收敛,MaskedFusion 单轮假设 11 小时、同样 30 轮,多出来 90 小时。换回来的是准确度提升——具体提升多少取决于你的数据集里遮挡样本的比例,遮挡越严重、mask 先验越值钱。如果你的场景里目标物体常年被机械臂、料框遮挡一半以上,这 90 小时换的精度值得;如果你的场景是干净台面上的单目标抓取,遮挡本来就少,mask 通道带来的边际收益很低,不如把这部分预算花在数据采集上。
提示:MaskedFusion 的 mask 输入必须是训练时也能拿到的。如果你的产线在推理阶段拿不到可靠的分割结果,训练时的 mask 就只能靠人工标注或合成数据,这里存在训练-推理分布不一致的风险,务必在验证集上单独核一遍。
4.2 对称物体与弱纹理:ShapeMatch-Loss 与关键点投票两条解法
对称物体是 6D 位姿估计里最经典的坑。一个圆柱形零件绕轴转任意角度看起来都一样,用常规的位置误差损失,网络会在这无穷多个等价解之间来回跳,loss 曲线看着收敛了,实际预测的旋转角每次都不一样。
PoseCNN 给的解法是在损失函数层面处理:ShapeMatch-Loss 不直接比较预测旋转和标注旋转的差异,而是在物体的对称变换集合里找一个使损失最小的等价解再计算。这样网络只要落在任何一个等价解上都不受惩罚,训练就稳了。这条思路的好处是不改网络结构,只改损失;代价是你必须提前知道物体的对称性,并把它写成对称变换集合,物体种类多了之后维护成本不低。
关键点路线是另一条解法:不直接回归位姿,而是回归关键点坐标,再用 PnP 求解。对称物体的关键点如果定义在对称轴上,投票时会自动聚到同一处,天然绕开了歧义。这条路的代表做法包括预测 3D 包围盒八个顶点在 2D 图像上的投影、构建局部 3D 控制点再预测其 2D 投影、以及前面说的方向向量投票加随机采样一致性。
| 方案 | 对称物体处理方式 | 需要额外先验 | 端到端可训 |
|---|---|---|---|
| 直接回归 + ShapeMatch-Loss | 损失函数内消歧 | 需要对称变换集合 | 是 |
| 关键点 + PnP | 关键点定义天然消歧 | 需要 3D 关键点标注 | 否(两阶段) |
| 逐像素投票 + 置信度 | 多预测投票平均 | 不需要 | 是 |
我一般会优先选第三种,因为它不需要你提前枚举对称性,也不需要关键点标注,多预测投票本身就是一种消歧机制。前提是你的分割质量要够,投票的输入是逐像素特征,分割错了投出来的位姿全是废票。
4.3 直接回归与间接投票:搜索空间、实时性与失败模式
从整篇综述的梳理框架看,方法可以按两层维度切开。第一层是输入模态:2D 图像输入、3D 点云输入、RGB-D 输入。第二层是求解范式:基于对应点的方法、基于模板的方法、基于投票的方法。
基于对应点的方法主要吃特征点——传统侧有 SIFT、FAST、SURF、ORB 这些 2D 特征,3D 侧有 Spin Images、3D shape context、FPFH、CVFH、SHOT 这些点云描述子,深度学习侧有基于学习的 3D 描述符。它的逻辑是找输入数据和已有完整模型之间的对应关系:输入是 2D 图就找 2D 像素到 3D 模型点的对应,用 PnP 算位姿;输入是点云就找输入点到模型点的对应,用最小二乘解位姿。两类输入最后都可以用局部配准做优化。这条路的失败模式很统一:弱纹理或遮挡严重时,对应点找不出来,后面全崩。
基于模板的方法吃的是整体,把问题看成从带标签的训练图像里找和当前输入最像的一张,直接输出它对应的位姿标签。它适合低纹理物体,因为不依赖局部特征;但场景混叠或者物体表面发生形变时,模板匹配就失效了。
基于投票的方法介于两者之间,每个像素或每个 3D 点都贡献一票,投票目标是预定义的关键点或直接是位姿,投完之后再做选择和优化。直接回归位姿和投票出位姿的区别在于搜索空间:直接回归是在连续空间里一步到位,搜索空间大、定位难、实时性差;投票是把大搜索空间拆成大量小预测再聚合,单点可以错,聚合起来就稳。
我踩过最贵的一次坑,是拿一个直接回归的方案去做实时抓取,帧率怎么调都上不去,最后发现瓶颈不在网络前向,而在后处理——回归出来的位姿需要做一致性校验才能用,这个校验的开销比网络本身还大。换成投票结构之后,置信度本身就是现成的筛选依据,后处理几乎归零。
5. 选型避坑:五条踩过的坑,从训练顺序到评测指标
这一章不讲方法,只讲翻车现场。下面五条都是我或者身边同行真真切切踩过的,每一条按「现象 → 原因 → 解决」写,看到眼熟的直接跳过前面的论证,照解决方案改就行。
5.1 精修模块先训:位姿越修越歪
现象:主网络和精修模块一起训,训练 loss 看着在降,验证集上的位姿误差却在某个 epoch 之后开始回升,最后精修输出的位姿比不做精修还差。
原因:DenseFusion 那类迭代精修模块的输入是「上一轮预测位姿作用后的点云」,它学的是残差。主网络还没收敛时,每一轮喂进去的位姿都是随机抖动的,残差估计器学到的是噪声的分布,不是真实残差的分布。等主网收敛了,残差估计器已经固化在错误的分布上,再训也很难拉回来。
解决:严格分两阶段。主网络单独训到收敛(验证集指标连续若干轮不再提升),冻结主网权重,再单独打开精修模块训练。现在我的训练脚本里这一步是硬编码的顺序,不给任何人「一起训快一点」的机会。
5.2 置信度当准确率用:筛选阈值一设就崩
现象:DenseFusion 这类逐像素投票的方案,每帧会输出一堆位姿预测和一个置信度分数。有人直接把置信度当准确率用,设个 0.7 的阈值过滤,结果阈值一设,可用帧数掉到个位数。
原因:置信度分数是网络自监督学出来的相对排序量,不是校准过的概率。它只能用来在同一帧内部的多个预测之间排序,跨帧、跨物体比较没有意义。这个分数对训练数据分布极其敏感,换个相机、换个光照,整体分布就平移。
解决:把置信度当排序依据而不是绝对阈值。做法是每帧取置信度最高的那一批预测做加权平均,而不是先卡阈值再平均。如果一定要设阈值,就在目标场景的验证集上重新标定,别用论文里的数值。
5.3 只报 ADD 不报 ADD-S:对称物体上分数虚高
现象:自测报告上平均精度漂亮,实际部署时对称零件频繁抓空,日志里看位姿误差大得离谱。
原因:ADD 指标是计算两个位姿下模型点的平均欧氏距离,对非对称物体没问题,但对对称物体,模型绕对称轴转 180 度和原姿态在几何上等价,ADD 却会给出巨大误差;反过来如果网络恰好学到了「另一侧」的等价姿态,某些角度下 ADD 又意外地小。只统计一个指标,会把对称物体的评估彻底搞乱。
import numpy as np def add_metric(pose_gt, pose_pred, model_pts): """ADD:逐点求两个位姿变换后模型点的平均欧氏距离,用于非对称物体""" a = (pose_gt[:3, :3] @ model_pts.T + pose_gt[:3, 3:4]).T b = (pose_pred[:3, :3] @ model_pts.T + pose_pred[:3, 3:4]).T return float(np.mean(np.linalg.norm(a - b, axis=1))) def add_s_metric(pose_gt, pose_pred, model_pts): """ADD-S:每个点取模型上最近点的距离,专治对称物体 model_pts 采样 500 点左右即可,全量算会爆内存(复杂度 O(N^2))""" a = (pose_gt[:3, :3] @ model_pts.T + pose_gt[:3, 3:4]).T b = (pose_pred[:3, :3] @ model_pts.T + pose_pred[:3, 3:4]).T d = np.linalg.norm(a[:, None, :] - b[None, :, :], axis=2) return float(np.mean(np.min(d, axis=1)))这两个函数要一起用:非对称物体看 ADD,对称物体看 ADD-S,报告里两个都给。model_pts一定要用均匀采样的模型点,不能用关键点,采样密度不够会让 ADD-S 系统性偏小。
解决:评估脚本里强制两条都跑,并且按物体是否对称分组统计。发现某个物体 ADD 和 ADD-S 差得特别多,先别怀疑网络,检查这个物体是不是对称件。
5.4 点云预处理不一致:换台相机结果全变
现象:实验室标定好的方案搬到产线,同一批零件,精度掉了一大截,重新训一轮模型也救不回来。
原因:点云预处理链路里藏了一堆隐式假设——深度图截断范围、无效深度值的填充方式、点云下采样体素尺寸、坐标系原点定义、单位是米还是毫米。这些在实验室都靠默认值跑通,换台相机、换个量程,某个默认值就越界了,点云整体尺度或分布变了,网络输入分布跟着变。
解决:把所有预处理参数显式写进配置文件,包括深度截断的上下限、无效值处理策略、下采样体素边长、单位换算系数。上线前跑一遍「同物体不同相机」的对比测试,把两个相机的预处理输出点云可视化叠一起看,能对上的再往下走。
5.5 点云配准当万能药:初值一偏全盘皆输
现象:想着「网络出的初值不准没关系,后面 ICP 能救」,结果遮挡严重或者分割出错的帧上,ICP 把位姿拉到一个完全错误的位置,而且fitness还挺高。
原因:ICP 是局部最优算法,它只保证在初值附近找到最近的局部极小。初值偏到另一个物体上,ICP 会认认真真地把两个错误的东西对齐,然后告诉你「配准成功」。fitness高只说明重叠区域大,不说明配对了。
解决:在 ICP 前面加一道初值体检——把网络位姿作用到模型点云上,和场景点云做一次粗重叠率计算,重叠率低于阈值直接判失败,不进 ICP。另外 ICP 之后要复算一次 ADD 或重投影误差做二次确认,两个指标都过才算这一帧有效。这套「初值体检 + 精修 + 后验确认」的三段式,从那以后我在每个项目里都强制走一遍。
6. 落到项目上:一张决策表加一个我现在固定跑的四步流程
拆完这么多方案,落到实际选型,我最后收敛成一张决策表。用的时候从最左边一列往下问,命中哪一行就不用再纠结了。
| 你的约束条件 | 首选路线 | 备选 | 不建议 |
|---|---|---|---|
| 有对齐好的 RGB-D,遮挡多 | 逐像素稠密融合 + mask 分支 | DenseFusion 原版 | 纯 RGB 关键点 |
| 有对齐好的 RGB-D,遮挡少 | DenseFusion 原版 | PoseCNN + ICP | 三路 mask 融合(收益低) |
| 只有深度/3D 传感器 | 点云描述符配准 + ICP | 体素化检测 | 任何 RGB 方法 |
| 只有单目相机,纹理丰富 | 关键点 + PnP | 单阶段多尺度回归 | 点云方法 |
| 只有单目相机,弱纹理 | 模板匹配兜底 | 合成数据 + 弱监督 | 特征点匹配 |
| 对称零件 | 逐像素投票 | ShapeMatch-Loss | 纯 ADD 评估的方案 |
| 训练预算紧、要快迭代 | DenseFusion 原版 | 关键点两阶段 | 三路融合 + 迭代精修 |
表里最后一行是我最想强调的。很多团队一开始就被精度数字带着走,直接上结构最复杂的方案,结果训练一轮要十几个小时,调参调到怀疑人生,两周下来连 baseline 都没跑通。先用最简单的版本跑通端到端链路,把数据预处理、评估脚本、失败帧回放这三件事做扎实,再往上叠模块,这个顺序反过来做,血泪经验。
流程上我现在固定跑四步。第一步,先把数据按「对称 / 非对称」「遮挡 / 无遮挡」交叉分成四组,分组看指标,不要只看总数;总数好看但某一组稀烂是常态。第二步,跑一个最简 baseline——DenseFusion 原版或者一个关键点 + PnP 的轻量实现,拿到端到端的完整链路,包括预处理、推理、ICP 后处理、评估。第三步,在 baseline 上只加一个变量,要么是 mask 分支,要么是精修模块,要么是对称损失,加一个测一个,绝不两个一起上,否则出了效果说不清是谁的功劳。第四步,把失败帧全部导出来可视化——点云叠合图、位姿误差分布、置信度直方图,三张图一起看。翻车的案子九成能在这一步找到原因,要么是分割错了,要么是初值偏了,要么是评估指标选错了。
有个细节值得单独拎出来说:失败帧的可视化一定要做点云叠合,不要只画 2D 框。6D 位姿的错误在 2D 图上看经常「看起来还行」,旋转轴偏了十几度,投影到图像上只是轮廓稍微错一点,但抓取时夹爪就是夹不住。我现在的习惯是每批实验结束强制导出二十张失败帧的叠合图,扫一眼就能看出是平移错还是旋转错——平移错通常是分割或深度问题,旋转错多半是对称性或关键点定义的问题。
再补一个评估上的小技巧。算 ADD 和 ADD-S 的时候,如果你的模型点云是从 CAD 直接采样的,注意采样密度要足够均匀,用体素栅格下采样比随机采样稳,随机采样会导致某些面片点特别少,ADD-S 的最近点距离被系统性高估。这个偏差在小物体上不明显,物体尺寸一上去就能差出好几毫米,足以让一个本来及格的方案被判为不及格,反过来也一样。
回过头看,我从一开始盯着「哪个网络精度最高」,到后来变成先问「输入是什么模态、物体有没有纹理、训练预算多少」,中间隔了好几个项目的返工。从那以后我每次拿到一份新的位姿估计方案,都强制先跑一遍上面那四步流程,尤其是第一步的分组和第四步的失败帧可视化,跳过任何一步都会在后面某个深夜还回来。希望帮到你。
本文还有配套的精品资源,点击获取