简介:《6D位姿估计 综述文献总结》以思维导图形式梳理视觉机器人抓取中从目标定位、位姿估计到抓取估计的知识框架,适合机器人视觉、三维感知方向的学习者与研究人员快速建立方法脉络。内容围绕RGB-D、点云和RGB图像三条技术路线展开,串联DenseFusion、MaskedFusion、PoseCNN、PointNet/PointNet++、Frustum-PointNet、VoxelNet,以及PnP、模板匹配和关键点检测等代表性工作,并点出各自优势、局限与适用场景。压缩包内为1个PDF文件,约434KB,轻量便于查阅和标注。已有3713人学习下载,可作为综述阅读笔记、组会汇报提纲或课题调研入口,帮助读者对比数据融合、refinement、语义分割与2D-3D对应等关键环节,快速定位后续精读文献。
1. 三条路线本质上回答的是同一个问题:你给网络多少“物体已知信息”
很多人第一次接触 6D 位姿估计,会把注意力全放在网络结构上。但复现几篇综述里提到的代表方法就会发现,误差的来源很少是“层数不够”,而是输入模态和输出定义:同一条 RGB-D 流水线,换成纯 RGB 输入,旋转误差会先塌下去;换成纯点云输入,平移反而更稳。6D 位姿估计本质上是在估计物体坐标系到相机坐标系的刚体变换,3 个平移自由度加 3 个旋转自由度,9 个参数被压缩成 6 个,多出来的约束来自正交性,这也是为什么四元数、旋转矩阵、轴角三种表示在损失函数里表现完全不同。
真正值得关心的问题是:同一组 RGB-D 图像,为什么 DenseFusion 要拆成两路编码再拼回去、MaskedFusion 要多加一路 mask、PoseCNN 要在网络之后补一个 ICP。答案都指向同一件事:网络擅长从数据中学习语义,不擅长从几何中学习精确的数值,所以每多一路显式的几何或语义先验,就少一分对网络“猜”的依赖。
2. RGB-D 融合:DenseFusion 为什么要把颜色和几何拆成两路再拼回去
RGB-D 输入最朴素的用法是把深度图当第四个通道,和 RGB 叠成一个四通道张量喂进卷积网络。这种做法在分类任务上勉强能用,在位姿任务上基本不可用,原因是深度图的数值语义和颜色完全不同:颜色在物体表面是连续的,深度在物体边缘是断崖式的,同一个 3×3 卷积核在这两个域上提取的东西根本对不上。DenseFusion 的核心设计是把这两类信息拆成两个独立编码器,各自在自己的域里提取特征,再在特征空间里做逐像素拼接。
2.1 两路编码:color embedding 与 geometry embedding 各自解决什么问题
颜色分支负责纹理和语义。一台相机拍到的物体,只要表面有纹理,RGB 分支就能把“这是杯口、那是把手”这类语义信息编码进特征里,这类特征对区分同类不同实例很有用。几何分支负责形状,深度图经由相机内参反投影成点云之后,送入一个 PointNet 类的编码器,输出的特征描述的是该像素对应空间点周围的局部几何结构,比如这里是平面、那里是圆柱面。
两个分支输出的特征图在空间上是对齐的,因为点云是按像素索引反投影得到的,每个像素对应一个 3D 点。对齐之后逐像素 concat,就得到了一个既含颜色又含几何的融合特征。常见的实现思路是:颜色分支用 ResNet 类骨干在降采样后上采样回原分辨率,几何分支用轻量 PointNet 对每个像素邻域内的点做局部聚合,两路输出保持同一空间尺寸再拼接。
注意:几何分支的输入不是原始的 depth 图,而是由 depth 和相机内参反投影出来的点云。直接拿 depth 图卷,等于丢掉了相机内外参,不同相机拍出来的同一场景会得到不同特征。
这一步的设计取舍很明显:拆成两路意味着参数量和显存开销都上去了,但换来的是每一路都能用最适合自己模态的算子。卷积处理规则网格,PointNet 处理无序点集,这是两个不同的归纳偏置,硬塞进同一个卷积核里只会互相干扰。
2.2 逐像素位姿投票:为什么每个像素都输出一个位姿
融合特征之后,DenseFusion 没有用一个全局池化把特征压成一个向量再回归位姿,而是让每个像素都独立预测一组位姿参数加一个置信度。这个设计初看很浪费,一个物体几千个像素,等于预测了几千个位姿。但它的好处在遮挡场景下极其明显:被遮挡的像素特征本身就是脏的,它预测出来的位姿置信度会低;而可见部分的像素特征干净,置信度高。最后按置信度选或者加权,相当于网络自己学会了“哪些像素的话可信”。
下面这段示意代码展示了单像素位姿预测的张量流,重点看输出维度的构成:
# 单像素位姿预测的关键张量流(示意) rgb_feat = rgb_backbone(rgb) # (B, C_c, H, W) 颜色嵌入 pts = depth_to_pointcloud(depth, K) # (B, 3, H, W) 由内参反投影 geo_feat = pointnet_encoder(pts, radius=0.01) # (B, C_g, H, W) 几何嵌入 fused = torch.cat([rgb_feat, geo_feat], 1) # (B, C_c + C_g, H, W) 逐像素拼接 head_out = pose_head(fused, hidden=128) # (B, 8, H, W) quat = head_out[:, 0:4] # 旋转,四元数表示 trans = head_out[:, 4:7] # 平移,单位米 conf = head_out[:, 7] # 该像素位姿的置信度参数说明:K是相机内参矩阵,决定像素和 3D 点的对应关系;radius是 PointNet 聚合邻域半径,与物体尺度强相关,单位是米;输出维度 8 来自 4(四元数)+ 3(平移)+ 1(置信度)。四元数在送入损失函数前必须归一化,否则旋转矩阵不正交,反算出来的位姿会出现缩放。
置信度这一路的用处不止选优。训练时它会作为自监督信号参与损失,让网络对干净像素的预测更自信、对脏像素的预测主动压低权重。这个思路在后续很多融合类方法里被反复借用,本质上是一种可学习的注意力,只不过注意力的载体是位姿置信度而不是特征通道。
2.3 refinement 迭代:残差估计器为什么要等主网络收敛后再训
DenseFusion 的 refinement 模块是一个迭代过程:用上一轮估计出的位姿,把当前帧的点云变换到物体坐标系,再送入 PointNet 提取残差特征,输出一个位姿残差去修正上一轮的估计。这个结构在概念上很像视觉里程计里的位姿图优化,只不过这里的“上一帧”不是时间上的前一帧,而是上一次迭代。
关键细节在于训练顺序。残差估计器的输入依赖主网络输出的位姿,如果主网络还没收敛,输入的位姿本身就在剧烈抖动,残差估计器学到的就是一个噪声目标,训出来的东西没有意义。所以实践中必须先把主网络训到收敛,冻结或者小学习率微调主干,再单独训残差模块。这个顺序一旦搞反,损失曲线会呈现典型的两段式震荡:先降后升,再缓慢下降,看起来像过拟合,实际是残差模块在跟主网络互相拖后腿。
迭代次数也不是越多越好。每一轮迭代都会把点云按当前位姿变换一次,变换引入的插值误差会累积;通常两到三轮之后收益就趋于饱和,再迭代反而在对称物体上容易滑向等价位姿。这个现象在后面的避坑章节还会展开。
3. MaskedFusion 与 PoseCNN:多一路 mask 输入,和多一步 ICP 精修
如果说 DenseFusion 解决的是“两种模态怎么融合”,那 MaskedFusion 和 PoseCNN 解决的就是“融合之前能不能先给网络一点结构提示”。两者的思路方向相反:一个往前置环节加信息,一个往后置环节加约束。
3.1 MaskedFusion:把 RGB-D 拆成三路输入,慢在训练快在推理
MaskedFusion 在 DenseFusion 的基础上动的是数据入口。它不再把整张 RGB-D 图直接喂进去,而是先裁出物体区域,分成三路输入:裁剪后的 RGB、裁剪后的深度、以及对应的 mask。多出来的这一路 mask 提供的是形状先验,它告诉网络哪些像素属于这个物体、物体的轮廓长什么样,这对弱纹理物体尤其关键——颜色分支在纯色表面上提不出有区分度的特征,但 mask 的边界形状是确定的信息。
代价落在训练侧。三路输入意味着三个编码分支,前向和反向的开销都上去了,收敛需要的迭代数也更多,因为 mask 分支的梯度要穿过更多层才能影响到融合特征。但推理侧的时间并没有明显增加,原因是 mask 在部署时可以由图中的检测或分割阶段一次性给出,不需要在网络内部再算一遍。这个“训练慢、推理不慢”的不对称性,是很多融合类方法的共同特征,评估这类方法时如果只看推理耗时,会低估它们的训练成本。
三路特征融合的位置也有讲究。RGB 和 depth 的融合发生在特征空间,mask 的融合可以发生在更早的阶段,比如用 mask 对颜色特征做逐像素加权,把背景像素的响应压下去。这样做的效果相当于给网络加了一个软性的空间注意力,而且是物理意义明确的注意力,不是学出来的黑匣子。
3.2 PoseCNN:VGG16 三任务头 + ShapeMatch-Loss 怎么处理对称物体
PoseCNN 走的是另一条路:用 RGB 单模态,骨干是 VGG16,输出接三个任务头,分别做语义分割、3D 位置回归、3D 旋转回归。语义分割头给出每个像素的物体标签,3D 位置头不直接回归平移向量,而是回归每个像素指向物体中心的单位向量加上到中心的距离,再通过投票求中心,这套做法和后来关键点投票的思路是同源的。旋转头回归四元数。
真正让它区别于同期工作的是损失函数的设计。对称物体是位姿估计的老大难:一个圆柱体绕自身轴旋转 180 度,外观完全一样,但四元数差了十万八千里,如果直接对四元数做 L2 损失,网络会被这些等价位姿来回拉扯,训到最后哪个方向都估不准。ShapeMatch-Loss 的做法是绕开参数空间,直接在形状空间里比:
def shape_match_loss(R_pred, t_pred, R_gt, t_gt, model_pts): """model_pts: (N, 3) 物体坐标系下的模型点云""" p_pred = model_pts @ R_pred.transpose(-1, -2) + t_pred # (N, 3) p_gt = model_pts @ R_gt.transpose(-1, -2) + t_gt # (N, 3) # 双向最近邻:每个预测点找最近的 gt 点,反之亦然 d_pred2gt = torch.cdist(p_pred, p_gt).min(dim=1).values # (N,) d_gt2pred = torch.cdist(p_gt, p_pred).min(dim=1).values # (N,) return d_pred2gt.mean() + d_gt2pred.mean()参数说明:model_pts是物体的 CAD 模型采样点,数量通常取几千,太少会让最近邻距离失真;双向最近邻是为了避免单向匹配时预测点云整体塌缩到一个点上。这个损失函数的意义在于:两个位姿只要把模型点云变换到同一个空间位置,损失就是零,不管它们的四元数表示差多少。等价位姿被天然地视为正确,网络不用再为对称性纠结。
提示:ShapeMatch-Loss 的计算量随模型点数线性增长,训练时通常采样 1000 到 2000 个点即可,评测时再换用完整点云计算 ADD 指标。
3.3 ICP 精修:为什么网络输出之后还要再跑一次几何配准
PoseCNN 在网络输出之后还接了一步 ICP,用深度图对预测位姿做精修。这一步在深度学习流水线里看起来有点“返祖”,但它解决的是网络解决不了的问题:网络回归的平移和旋转是在整张图上全局池化出来的,精度受限于特征图分辨率,而 ICP 是在原始点云上做局部优化,精度可以到亚像素级。
ICP 起作用的前提是有一个足够好的初值。如果网络输出的位姿偏差超过物体尺度的一半,ICP 会收敛到错误的局部极小值,这时候精修不但没帮助,还会把原本勉强正确的位姿拉得更偏。所以 ICP 的迭代次数一般控制在几十次以内,并且要设一个距离阈值,把离群点排除在最近点匹配之外。遮挡场景下这个阈值尤其重要,被遮挡部分的点云本来就缺失,强行匹配只会把位姿往遮挡物那边拽。
这一步的设计取舍也很清楚:ICP 是纯几何方法,不依赖训练数据,泛化性好;但它对初值敏感,且每次精修都要跑迭代,实时性上是额外开销。PoseCNN 之所以敢加这一步,是因为它的网络输出已经足够接近真值,ICP 只是锦上添花。
4. 纯点云与纯 RGB:PointNet 系列的无序性解法,和关键点投票的两阶段解耦
前面几节讨论的都是 RGB-D 融合。但实际部署里,深度相机不一定有,有时候只有一张 RGB 图,有时候只有一帧点云。这两条单模态路线各自演化出了一套独立的方法论,理解了它们,才能明白为什么综述里要把 6D 位姿估计分成“直接法”和“间接法”两大支。
4.1 PointNet 到 PointNet++:max pooling 与 T-Net 换来了什么
点云和图像最大的区别是它没有网格结构,点的顺序换一下,语义完全不变。卷积网络处理不了这种无序性,因为卷积核的权重是和空间位置绑定的。PointNet 的解法是用一个对称函数把无序点集映射成一个固定长度的向量,具体做法是对每个点单独提特征,然后对所有点的特征做 max pooling。max 是置换不变的,输入点的顺序怎么变,输出都一样。
这个设计的理论依据是:任意定义在点集上的连续集合函数,都可以被“逐点变换 + 对称聚合”的结构任意逼近。换句话说,max pooling 不是在偷懒,它是在一个足够表达能力的函数空间里做聚合。PointNet 还引入了 T-Net,一个小网络预测一个变换矩阵,作用在输入点云或中间特征上,让网络对旋转和扰动更鲁棒。T-Net 的输出矩阵在训练时会趋近于正交,否则特征会被拉伸变形。
PointNet 的短板在于它把每个点独立处理,局部结构信息丢失严重。PointNet++ 用 set abstraction 层补上了这块:先在最远点采样选出一组中心点,再以每个中心点为球心划分邻域,邻域内的点用 mini-PointNet 提局部特征,逐层向上抽象。最远点采样保证采样点在空间上均匀分布,解决了点云密度不均的问题——激光雷达近处点密、远处点疏,如果按固定半径分组,近处组内点太多、远处组内点太少,特征尺度完全不一致。
4.2 VoxelNet 的体素化代价:为什么点云冗余度是硬伤
VoxelNet 走的是另一条路:把点云划分成规则的三维体素,每个体素内随机采样固定数量的点,提特征后做 3D 卷积,最后接 RPN 做检测和位姿回归。这条路子在自动驾驶基准上曾经拿到过领先效果,因为体素化之后点云变成了规则张量,可以直接复用成熟的 3D 卷积结构。
代价也很直接。体素分辨率提高一倍,体素总数变成八倍,而真实场景里绝大多数体素是空的,计算资源大量浪费在空体素上。稀疏卷积就是为了解决这个问题才出现的,它只对非空体素做卷积,但实现复杂度比密集卷积高一个量级。另一方面,体素化本身就是一种量化,一个体素内的所有点被压成一个特征,亚体素级别的几何细节被抹掉了,这对小物体的位姿估计是致命的。
点云路线的共性问题还在于信息缺失。点云只有几何,没有纹理,两个形状相同但材质不同的物体在点云上无法区分。而在工业抓取这类场景里,位姿估计往往还要求同时估计物体的几何参数和表面属性,纯点云方案在这类任务上先天不足。
4.3 关键点路线:PVNet 的方向向量投票与 RANSAC
PVNet 代表的是另一类思路:不直接从图像回归位姿,而是先找关键点,再用 PnP 解位姿。它的做法是让每个像素预测一个指向物体关键点的单位方向向量,然后对这些向量做投票,找出关键点在图像上的位置。
这个设计的精妙之处在于它对遮挡的鲁棒性。传统关键点检测要求关键点本身可见,一旦被挡住就彻底失效;而方向向量投票不要求关键点可见,只要物体还有一部分像素可见,这些像素的方向向量延长线就会在关键点附近交汇,交点就是关键点的位置。相当于用大量局部证据去推断一个不可见的全局量。
投票过程用 RANSAC 实现,下面这段代码展示了核心逻辑:
def vote_keypoint(vectors, origins, n_iter=500, thresh=0.02): """vectors: (N,2) 单位方向向量; origins: (N,2) 像素坐标""" best_inliers, best_pt = -1, None n = len(vectors) for _ in range(n_iter): i, j = np.random.choice(n, 2, replace=False) A = np.stack([vectors[i], -vectors[j]], axis=1) # 两条射线的方向 if abs(np.linalg.det(A)) < 1e-6: # 近似平行,跳过 continue t, s = np.linalg.solve(A, origins[j] - origins[i]) if t <= 0 or s <= 0: # 交点落在射线反向 continue pt = origins[i] + t * vectors[i] # 内点判定:像素射线到候选点的垂直距离 d = origins - pt perp = np.abs(d[:, 0] * vectors[:, 1] - d[:, 1] * vectors[:, 0]) inliers = int((perp < thresh).sum()) if inliers > best_inliers: best_inliers, best_pt = inliers, pt return best_pt, best_inliers参数说明:thresh是内点距离阈值,单位是像素,取值和关键点的定位精度相关,太小会导致内点不足、太大则投票结果发散;n_iter是采样次数,理论上需要满足1-(1-p)^2 > 0.99才能保证至少采到一组全内点,p是内点比例,遮挡严重时p可能低到 0.1,此时需要上千次采样。这段代码只处理单个关键点,实际实现里要对每个关键点分别投票。
得到 2D 关键点之后,用 PnP 结合已知的 3D 模型关键点解位姿。这条路线的问题是两阶段不能联合优化:关键点检测的误差会直接传导到位姿上,而且 PnP 对关键点的空间分布敏感,所有关键点挤在一小片区域时,解出来的旋转会非常不稳定。
4.4 直接回归 vs 间接投票:搜索空间与实时性的拉扯
直接法把图像或点云映射到位姿参数,一次前向出结果,端到端可训练,但搜索空间大,网络要在一个高维连续空间里回归,收敛慢且容易陷入局部最优。间接法把任务拆成检测和求解两步,每一步的搜索空间都小得多,鲁棒性更好,但两阶段之间的误差无法反向传播,且推理链路更长。
这个取舍在综述里被反复提及,但没有统一的答案。物体纹理丰富、遮挡少的时候,直接法精度更高也更简洁;物体弱纹理、遮挡严重的时候,间接法的投票机制优势明显。实际工程里常见的做法是两种都实现,根据场景切换,而不是指望一个网络通吃。
5. 避坑与排查:综述里不会写、但复现时一定撞上的五个问题
综述文章倾向于把方法讲成一个自洽的整体,但真正动手复现时,大部分时间会消耗在一些文献里不会提的细节上。下面这五条都是实践中反复撞上的,每一条都按现象、原因、解决的顺序写。
5.1 对称物体的位姿“翻转”
现象:训练损失正常收敛,评测时某些物体的旋转误差突然跳到 180 度附近,同一批数据里其他物体正常。原因:对称物体的等价位姿在参数空间里距离很远,但如果用四元数或旋转矩阵做直接监督,网络每轮看到的方向都不一样,学到最后输出的是一个折中的错误方向。解决:改用形状空间的距离度量,比如把模型点云按预测位姿和真值位姿各变换一次再求最近点距离;或者在数据加载阶段对对称物体做位姿规范化,只保留一个标准表示。这个坑几乎每个做位姿的人都会踩一次,属于典型的血泪经验。
5.2 单位与坐标系:米和毫米、相机系和物体系
现象:训练时损失下降得很漂亮,部署到真实设备上平移误差大到离谱,物体位置整体偏移一个固定量级。原因:深度图的单位是毫米,模型点云的单位是米,反投影时没做换算;或者训练时的位姿定义是物体到相机,推理时误用成相机到物体,求逆之后误差被放大。解决:在数据加载层统一单位,所有几何计算只在米制下进行;位姿的方向约定写进代码注释并做单元测试,用一组已知的 R、t 正向变换再反向验证。
5.3 点云缺失与遮挡导致的置信度失真
现象:遮挡严重的样本上,网络输出的置信度依然很高,最终选出来的位姿反而比低置信度的候选更差。原因:置信度是在训练集分布上学出来的,如果训练集里遮挡样本少,网络没学会在缺数据时降低置信度;另一层原因是逐像素预测的置信度只在像素级别有意义,聚合成物体级时用了简单平均,被大量背景像素稀释。解决:训练集里显式构造遮挡样本;聚合时用 top-k 而不是全平均,或者对置信度做温度缩放后再比较。
5.4 refinement 迭代不收敛
现象:残差模块加上去之后,验证集误差先降后升,迭代两轮以上时位姿开始在两个值之间来回跳。原因:残差估计器的训练数据和主网络当前输出分布不匹配,主网络在训练过程中还在变化,残差模块学到的是过时的误差分布;另一种情况是迭代过程中的点云变换引入了插值误差,误差被逐轮放大。解决:主网络收敛后再训残差模块,训练时对输入位姿加噪声做数据增强,让残差模块见到各种偏差;迭代次数限制在两到三轮,每轮后检查位姿变化量,超过阈值就提前停止。
5.5 评测指标 ADD 与 ADD-S 用错
现象:同一个模型在两份代码里跑出来的 ADD 指标差好几个点,但推理结果肉眼看上去一样。原因:ADD 计算的是模型点云在两个位姿下的平均距离,ADD-S 计算的是最近点距离,前者对非对称物体严格,后者对对称物体友好;如果对对称物体用了 ADD,指标会被等价位姿拉低,反之对非对称物体用 ADD-S 会虚高。解决:按物体类别分别选择指标,对称物体用 ADD-S,非对称用 ADD,报告时两者都给,并且注明哪些物体被归为对称。这个坑不会让模型变差,但会让论文里的数字失去可比性。
6. 设计取舍:为什么“一个网络通吃所有物体”在 6D 位姿上不成立
把三条路线放在一起看,会发现它们的取舍维度其实只有四个:输入模态、输出表示、是否端到端、以及推理链路长度。下面这张表是我自己在选型时会画的对照,列的是各路线在这四个维度上的典型特征,不是某一篇论文的具体数字。
| 路线 | 输入 | 输出形式 | 端到端 | 主要短板 |
|---|---|---|---|---|
| RGB-D 融合 | 彩色 + 深度 | 逐像素位姿 + 置信度 | 是 | 依赖深度质量,融合结构复杂 |
| 纯 RGB 直接回归 | 单张彩色 | 全局位姿参数 | 是 | 弱纹理失效,旋转精度受限 |
| 纯 RGB 关键点投票 | 单张彩色 | 2D 关键点 + PnP | 否 | 两阶段误差不可联合优化 |
| 纯点云 | 单帧点云 | 位姿 + 残差 | 是 | 无纹理信息,对密度敏感 |
从这张表能看出一条隐含的规律:端到端的方法在数据充足、模态完整时精度上限更高,但鲁棒性依赖训练分布;非端到端的方法在分布外样本上更稳,但精度天花板受限于中间表示。这不是技术不够先进,而是问题本身的约束:位姿是一个六自由度的连续量,任何把它拆成离散中间量的做法都会损失信息,任何直接回归它的做法都会放大分布偏移。
验证一个方法是否真的适合你的场景,我一般按三步走。第一步做模态消融,把 RGB 和深度分别置零或加噪,看误差怎么变,误差对哪个模态敏感就说明这个模态在你的场景里不可靠。第二步做遮挡分级评测,按物体可见面积比例分桶统计误差,很多方法在 80% 可见度以上表现接近,在 50% 以下迅速分化,这个分桶曲线比单一平均值有信息量得多。第三步做位姿误差分解,把旋转误差和平移误差分开看,旋转误差大通常是关键点或对称性问题,平移误差大通常是深度尺度或相机内参问题,两者的排查方向完全不同。
还有一个常被忽略的取舍是标注成本。RGB-D 融合和纯点云方法都需要位姿真值,而位姿真值要么靠动捕设备采,要么靠人工对齐 CAD 模型,成本很高;纯 RGB 的关键点路线只需要 2D 标注,数据获取容易得多,这也是它在工业界落地更早的原因之一。精度和标注成本之间的平衡,往往比网络结构的选择更能决定一个项目能不能做成。
我自己的习惯是,每接手一个新的位姿任务,先不急着搭网络,而是拿十几帧数据手动算一遍从像素到 3D 点的反投影,确认单位、内参、坐标系方向这三件事没有搞反。这个习惯是被坑出来的:有一次整套流水线跑通、损失曲线完美,最后发现深度图的 scale 因子少乘了 1000,所有平移预测都差了三个数量级,而损失函数因为一直在优化相对误差,完全没有报警。从那以后我每次接入新的数据源,都强制走一遍这个手动验算,哪怕看起来很多余。希望帮到你。
本文还有配套的精品资源,点击获取