系列文章目录
参考博客
参考博客
参考博客
文章目录
- 系列文章目录
- 前言
- 一、OpenPose
- 模型架构
- VGG-19骨干网络
- 多阶段双分支结构
- PAF-Part Affinity Field
- 骨架后处理
- 二、YOLO26-Pose
- 模型架构
- 关键点回归分支
- 三、RTMO
- 模型架构
- CSPDarknet
- Hybrid Encoder
- RTMOHead
- 四、ViTPose
- 模型架构
- Patch Embedding
- Transformer Block
- Decoder
- 多数据集Decoder
- 总结
前言
人体姿态估计最核心的两个子问题:
关键点定位:找到图像中所有人体关节点的准确位置
关键点归属:判断哪个关节点属于哪个人
根据这两个问题的解决顺序、耦合程度不同,人体姿态估计模型主要根据 Top-Down 、 Bottom-Up 、 Single-Stage 三种范式划分。
Top-Down(自上而下)
先解决归属再解决定位,先用目标检测框出所有人,逐个裁剪人形框,根据人形框单独估计每个框内的关键点,好比如先点名叫一个同学上来答题,答对就记这个人的分。
但是依赖检测框质量,框漏了或框偏了,对应的人就完全估计失败。并且人数越多计算量线性增长。适用于人数少/中、对精度要求极高的场景。
Bottom-Up(自下而上)
先解决定位再解决归属,先检测全图所有人体关键点,用分组算法把属于同一个人的关键点拼起来,好比如先收全班的卷子堆在一起,再对着花名册把卷子分到每个人名下。
但是这种分组算法的设计在遮挡、密集场景下很难判断哪些点属于同一个人,精度上限低。适用于密集人群场景,避免逐人裁剪的计算开销。
Single-Stage(单阶段)
归属和定位同时解决,端到端网络直接输出带所属人ID的关键点,没有显式的先检测或先检点,再分组的后处理步骤,好比如收卷的时候直接让同学在卷子上写好名字,不用二次分卷。
但是网络需要同时学习找人、找关键点、关联归属三个任务,训练难度高。适用于实时视频、移动端、边缘设备。
Top-Down现在也在做单阶段化,比如把检测头和姿态头合并,减少两阶段的误差传递。
Single-Stage随着Transformer(如DETR系列)的引入,精度正在快速追赶Top-Down,未来很可能成为兼顾精度和速度的主流路线。
Bottom-Up因为分组的上限问题,现在更多作为密集场景的专用方案,或者作为Single-Stage的分组模块存在。
一、OpenPose
模型架构
VGG模型具体架构参考博客
VGG-19骨干网络
简单直接而有效的流式主干网络,主要使用3×3卷积+relu激活+maxpool下采样等算子。
多阶段双分支结构
OpenPose使用多个Stage的原因是一次性精准预测「所有关键点位置」+「所有关键点的连接关系」难度极高,而多Stage的迭代式精修,本质是给网络多次「纠错、补信息、消歧义」的机会,同时解决深层网络的训练稳定性问题。
可以理解为通过类残差的方法加深模型学习深度,在获取更丰富的特征同时避免出现梯度问题。
每个Stage都划分为两个并行分支,两个分支的结构除了最后一部分,其他都基本一致,每个stage内部使用多个7×7大卷积核,以获得更大的感受野,捕捉关键点之间的远距离依赖。
Part Affinity Fields L分支是用于学习肢体特征,在最后输出的是38通道的特征矩阵,对应19种肢体,也就是两辆关键点之间的肢体联系。
Part Confidence Maps S分支是用于学习关键点特征,在最后输出的是19通道的特征矩阵,对应18个特征点和一个背景的置信度。
除了第一个stage是使用两个主干的原始输出,之后的stage使用的是一个跨阶段主干的原始输出和上一阶段stage输出。
也就是说当前stage能看到原始特征+上一阶段stage的特征+上一阶段stage的PAF,然后在此基础上继续深度学习。这种迭代预测机制让网络能逐步纠正前一阶段的错误。
PAF-Part Affinity Field
PAF 就是给图像中每一根"骨头"画满小箭头,箭头的方向标明了这根骨头应该从哪个关节指向哪个关节。有了这些箭头,算法就能判断:两个被检出的关键点,到底是不是属于同一个人的同一根骨头。
PAF 是一个2D 向量场,对于图像中的每一个像素位置,都存储了一个二维向量 (x, y) 。而OpenPose 定义了人体 19 种肢体连接,所以需要预测 19 个这样的向量场,每个场负责一种连接类型 。每个向量场用2个通道表示(x ,y),所以对应了L分支的38通道。
通过PAF最终得到位置编码、方向编码和密集像素预测,相比早期方法只预测肢体的"中点"是否存在,PAF保留了肢体的完整空间支持和方向信息,对遮挡和人群拥挤更鲁棒。
骨架后处理
通过S分支获取关键点热图,对每张关键点热图做NMS非极大值抑制,找出所有局部峰值,作为该关键点的候选位置。
使用PAF和L分支计算肢体关联得分,结合关键点相连线段,如果与PAF方向越一致,这两个关键点越可能属于同一个人的这条肢体。
使用贪心二分匹配组人,对每种肢体类型独立做二分图匹配,然后把所有肢体通过共享的关节点合并起来。
使用亚像素级修正,为提高精度,对最终确定的关键点坐标做二次插值,把定位误差从像素级降到亚像素级。
二、YOLO26-Pose
YOLO26是Ultralytics推出的统一多任务视觉模型家族,其中YOLO26目标检测负责识别图像中物体的位置和类别,输出轴对齐的边界框+置信度+类别。YOLO26-Pose负责在人体检测的基础上额外预测每个人的17个COCO关键点,每个关键点用(x, y, conf)三元组表示。
YOLO26-Pose模型对比YOLO26模型的区别就是在检测头之外,多了一个并行的关键点回归分支,两个分支共享 backbone 提取的特征,但通过任务特定的 1×1 卷积实现特征解耦。
模型架构
yolo模型具体架构参考博客
关键点回归分支
关键点回归分支的大致结构如下:
Neck 特征图 [B, 256, H, W] ↓ Conv2d(256 → 256, 3×3) + BN + SiLU ↓ Conv2d(256 → 256, 3×3) + BN + SiLU ↓ Conv2d(256 → 256, 3×3) + BN + SiLU ↓ Conv2d(256 → 17×3, 1×1)在对关键点回归分支进行前向传播和损失计算的时候会使用RLE损失函数,为了计算这个函数,需要跑一个额外的神经网络RealNVP。在推理的时候就不会涉及到RLE损失函数计算。
RLE(Residual Log-Likelihood Estimation,残差对数似然估计)是 2021 年 ICCV 论文《Human Pose Regression with Residual Log-Likelihood Estimation》提出的一种用概率建模来替代传统 L1/SmoothL1 回归损失的方法。YOLO26-Pose 引入它,核心目的是让模型自己从数据里学习"每个关键点的误差分布长什么样",而不是人为假设一个固定的高斯/拉普拉斯分布。
在RLE之前,关键点回归通常用SmoothL1或MSE Loss,使得每个关键点的预测误差服从固定方差的高斯或拉普拉斯分布。而RLE先用一个简单的高斯分布兜底,再用一个可学习的"流模型"去修正这个高斯分布没捕捉到的残差部分。
RLE 中的流模型是一个基于RealNVP的归一化流网络,它通过一系列可逆耦合层把标准高斯分布塑形成"关键点预测残差"的真实分布;在训练中它学习残差的对数似然来修正预设简单分布的偏差,从而让回归损失基于更真实的概率假设;而在推理时它完全不参与计算,零额外开销。
不同关键点后处理:
OpenPose需要复杂后处理,是因为它输出的是所有人的所有关节池,需要用PAF+图匹配把对应关节捞回到对应人体骨架中。
RTMO需要解码,是因为它用坐标分类换取精度,必须通过对热力图积分把 bin 概率分布还原成坐标。
YOLO26-Pose直接输出归一化坐标,是因为它在网络内部就把"人实例"和"该实例的关键点"绑定在了一起,输出即结果,后处理仅剩阈值过滤。
这三条路线没有绝对的优劣,而是精度-速度-工程简洁性三角下的不同权衡。
三、RTMO
模型架构
CSPDarknet
RTMO模型backbone主干沿用了YOLOv5和YOLOX的CSPDarknet模块,主要复用了YOLOX的backbone主干中的Focus层、CSPDarknet、SPPBottleneck、SiLU等,并没有为姿态估计任务重新设计主干,提供了s / m / l三个尺寸变种。
参考以下模型网络架构图片
Hybrid Encoder
Hybrid Encoder不是RTMO原创,而是 直接从RT-DETR搬过来并裁剪的 Neck 模块 。
主要采用两段式结构:AIFI + CCFF
AIFI — Attention-based Intra-scale Feature Interaction:
RTMO模型backbone主干最终输出S3、S4和S5三个特征矩阵,S3、S4 完全不参与Transformer处理,只对最深尺度的S5特征矩阵进行toker化,再输入Transformer Encoder层进行全局特征增强得到输出特征矩阵,这里用的是原生nn.TransformerEncoder,只有1层MHSA+FFN。
S5空间尺寸最小[B, 1024, 20, 20],所以转换token的时候只有20×20=400token,自注意力代价可控。无需patch embedding投影,只需要卷积压缩+展平空间维+转置把[B, C, H, W]的空间格式转成[B, N, C]的序列格式,得到符合Transformer Encoder层输入的特征序列矩阵[B, 256, 400]。
因为展平操作把2D空间结构打散了,必须加位置编码告诉Transformer每个token的原始坐标,所以使用2D正弦位置编码,捕捉全局语义上下文。
得到Transformer Encoder层的输出特征矩阵[B, 400, 256]后,反向处理还原回CNN原来的矩阵格式,通过转置+按展平空间维顺序反向还原得到特征矩阵F5[B, 256, 20, 20]。
CCFF — CNN-based Cross-scale Feature Fusion:
对得到的S3、S4和F5三个特征矩阵使用类FPN+PAN的卷积结构做多尺度融合:
Top-down(FPN 路径):F5 → 1×1conv → 上采样 → 与S4拼接 → CSPRepLayer融合 → 上采样 → 与S3拼接 → CSPRepLayer融合
Bottom-up(PAN 路径):多尺度融合特征 → 3×3conv下采样 → 与S4拼接 → CSPRepLayer融合 → 3×3conv下采样 → 与F5拼接 → CSPRepLayer融合
参考以下模型网络架构图片
RTMOHead
RTMOHead 是整个模型从特征图到人体框 + 17 关键点的最后一环,先对 CCFF 输出的 P4/P5 特征做统一提炼,之后分流为 4 个并行分支。
输入特征图 [B, 256, H, W] → 1×1conv → 3×3conv → RepConv 块 RepConv 块 ├─► Obj Branch: 1×1 conv → [B, 1, H, W] → score grid的人体置信度,是否包含人体 ├─► Box Branch: 1×1 conv → [B, 4, H, W] → bbox 相对grid中心的bbox偏移 ├─► Pose Branch: 1×1 conv → [B, 256, H, W] → pose 每个grid的姿态语义向量 └─► Vis Branch: 1×1 conv → [B, 17, H, W] → visibility 17 个关键点是否可见对当前 grid 预测出的 bbox 做 1.25× 外扩,,避免框偏了把关键点漏在外面,Pose Branch也只作用于该框内,框外的归属背景,以避免算力浪费。
然后对该框横着均匀切192个小格子,竖着均匀切256个小格子,总共192×256个格子,每个格子都有个固定的位置标签bin,所谓的bin就是把连续的坐标轴切成一段段,模型不去直接预测具体坐标,而是预测关键点在第几个bin区间里,把回归问题转化成分类问题。类似一把尺子,把它等分成若干段,每一段就是一个 bin。每个bin的空间大小随bbox的大小不同而不同。
Pose Branch 输出的 256 维特征向量本身不是坐标,需要先过一个 FC 层 + Reshape,拆成 17 个关键点的特征向量,然后通过相似度计算对比关键点特征向量与bin,把关键点特征和每个bin的位置编码做点积,点积越大说明该 bin 越可能是这个关键点的位置,再通过softmax转化成了17对1D热力图,最后解码计算得到对应的精确关键点坐标。
四、ViTPose
ViTPose走的是 top-down 范式,先用外部的人体检测器得到每张裁剪好的人像,再送进网络回归关键点热图。
模型架构
ViT模型具体架构参考博客
Patch Embedding
需要先使用外部的人体检测器获取并从原图裁剪人像区域,把该区域缩放填充到256192大小作为pose模型输入。然后把输入图像按照1616像素的图像块,沿着高度切256/16=16块,沿着宽度切192/16=12块,最终得到192个16*16像素大小的patch图像块。
每个 patch 会被展平成一个向量,经过一个线性层投影,再加上可学习的positional embedding,最终变成Transformer模块能处理的Token。
Transformer Block
Transformer Block采用的是层归一化前置结构Pre-LN。它由两个核心子层组成,分别是多头自注意力MHSA和前馈网络FFN,每个子层都配有残差连接。
Post-LN和Pre-LN都使用了层归一化Layer Normalization这个操作,它们的核心区别在于Layer Norm的调用位置。
Post-LN先算残差,再在残差后面做Layer Norm处理。这种做法导致在深层网络中,梯度在反向传播时需要通过Layer Norm层,容易导致梯度消失或爆炸,必须用非常精细的学习率Warm-up策略才能训得动。
Post-LN先做Layer Norm,经过多头自注意力MHSA处理再进行残差连接。因为残差连接是直接连接,没有经过Layer Norm的缩放,梯度可以沿着残差路径无损地直接回传到浅层。使得Pre-LN极其稳定,几乎不需要Warm-up也能轻松训练成百上千层的网络。
MHSA就是多头自注意力Multi-Head Self-Attention,是Transformer里最核心的组件。将原始的V、K、Q单独输入线性层处理投影到比较低的维度,然后做h次Scaled Dot-Product Attention并得到h个输出,合并输出最后做一次线性投影。
通过一个注意力机制的多次并行运行,将独立的注意力输出串联起来,线性地转化为预期维度。直观看来,多个注意头允许对序列的不同部分进行注意力运算,允许模型同时关注来自不同位置的不同表示子空间的信息。
MLP Block模块就是FFN处理,主要由两层MLP+GeLU组成,
Decoder
在 ViTPose 里,解码器Decoder的任务很简单,就是把Backbone输出的低分辨率且具有高维语义的Token序列,还原成高分辨率、通道数等于关键点个数的热力图。
例如Backbone输出的特征矩阵形状为[16,12,768]([H/16,W/16,C]),然后把输出的特征矩阵形状设定为[H/4, W/4, K],其中K为17,表示17个关键点,反卷积上采样设定为4,是ViTPose的Decoder从16倍下采样中获取的空间信息量,而4刚好在计算成本和定位精度之间达到了最优平衡,太大或太小都不利于精度和计算效率。
使用经典解码器Classic Decoder,通过可学习的转置卷积Deconv逐步上采样,并在每一步注入非线性变换,强行“修复”和“生成”空间细节。
如果说普通卷积是抽取最突出的信息,转置卷积则是还原补充信息。但是转置卷积不是简单的插值,而是一个带可学习参数的上采样。卷积核在生成更大特征图的过程中,会“脑补”出新的像素值,这相当于让网络自己学习“如何把模糊的语义特征画成清晰的热图”。
F_out [H/16,W/16,C] → Deconv(k=4, s=2) + BN + ReLU → Deconv(k=4, s=2) + BN + ReLU → predictor Conv1×1第一步:从[H/16,W/16,C]到[H/8,W/8,C],对全局语义进行还原。
第二步:从[H/8,W/8,C]到[H/4,W/4,C],进一步细化空间位置。
第三步:从[H/4,W/4,C]到[H/4,W/4,K],使用1×1卷积把Backbone输出的高维特征通道数C压缩映射到关键点个数K。
使用简单解码器Simple Decoder,通过简单直接的双线性插值上采样,Backbone 输出的特征已经足够好,几乎不需要非线性变换,不做任何需要迭代学习的特征变换,直接把现有的特征图拉大,让边缘平滑,但又没有新信息产生。
F_out [H/16,W/16,C] → Bilinear Upsample ×4 → ReLU → predictor Conv3×3第一步:从[H/16,W/16,C]到[H/4,W/4,C],无参数的几何放大,通过相邻像素的加权平均,一次性放大4倍。
第二步:从[H/4,W/4,C]到[H/4,W/4,K],使用3×3卷积对Backbone输出做轻微的局部特征平滑与融合,柔化热图的边缘,让关键点更清晰,同时将高维特征通道数C压缩映射到关键点个数K。
多数据集Decoder
预训练数据灵活:不绑定ImageNet,可在COCO/AIC等姿态数据上做MAE预训练。
注意力类型灵活:full/window/shift-window/pooling-window 可插拔。
微调策略灵活:实验发现冻结MHSA、只训FFN,性能与全参数微调相当。
多数据集联合训练:因为解码器极轻,共享一个backbone,为每个数据集配独立decoder,每次迭代从多个数据集随机采样。
模型泛化与精度提升:COCO+AIC+MPII等不同标注格式的数据集联合训练可以让模型更加泛化,使得精度有一定提升。
总结
大多数的人体姿态估计模型,例如OpenPose、YOLO26-Pose、RTMO、ViTPose等其实对于模型Backbone网络而言,与常见的模型Backbone网络没有太大区别,主要是Neck网络和Head网络可能会做特殊调整。
像Neck可能会直接沿用,也可能优化,也可能移除。
像Head就是模型之间差异最大的地方,有的选择做热力图回归,有的选择做向量场关联,有的选择做直接坐标回归。
不过也有像 HRNet 这样从底层设计就专为姿态估计(保持高分辨率)而生的主干,算是这个规律的一个例外。