- 人工智能
- 计算机视觉
- 深度学习
【免费下载链接】ViTPose
The official repo for [NeurIPS'22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [TPAMI'23] "ViTPose++: Vision Transformer for Generic Body Pose Estimation"
导读
DARK(Distribution-Aware coordinate Representation of Keypoints)是 CVPR 2020 提出的一种模型无关的姿态估计后处理/前处理增强方法,其核心发现是:热图(heatmap)从预测到最终关节坐标的解码过程对精度影响远超预期。本文以 ViTPose 仓库中的算法文档 docs/en/papers/algorithms/dark.md 为主体,结合仓库中TopDownGenerateTarget的无偏编码实现、keypoints_from_heatmaps的分布感知解码实现以及 ResNet/HRNet 的 dark 系列训练配置,完整拆解 DARK 的数学原理、代码调用链与实际配置方法,帮助你在自己的姿态估计模型上直接落地这套“即插即用”的精度提升方案。
一、DARK 方法概述:从论文摘要看核心主张
在人体姿态估计领域,热图长期是关节坐标表示的事实标准(de facto standard),但很少有工作深入剖析热图本身的设计。DARK 论文(Zhang et al.,Distribution-aware coordinate representation for human pose estimation, CVPR 2020)首次指出两个此前被忽视的环节:
- 解码环节至关重要:将预测热图解码回原始图像空间中的最终关节坐标这一过程,对最终性能的影响“惊人地显著”(surprisingly significant)。标准坐标解码方法(取最大值并做固定偏移)存在系统性偏差。
- 编码环节可以更准:将真实坐标转换为热图(ground-truth coordinates → heatmaps)的过程也可以改进,通过生成无偏/更精确的热图来消除量化误差。
论文将这两部分统一为一个完整方法——分布感知的关键点坐标表示(DARK)。作为模型无关的即插即用模块(model-agnostic plug-in),DARK 能为现有姿态估计模型带来显著性能提升,论文报告其在 MPII 与 COCO 两个常见基准上取得当时的最佳结果,并斩获 ICCV 2019 COCO Keypoints Challenge 第二名(以上结论均出自论文摘要原文)。
在 ViTPose 仓库中,DARK 并非一个独立模型,而是以训练管线配置 + 评测后处理函数的形式存在:编码端由数据管线TopDownGenerateTarget的unbiased_encoding开关控制,解码端由keypoints_from_heatmaps的post_process='unbiased'分支驱动。
二、编码端:如何生成无偏的热图标签
2.1 标准编码的问题:量化取整引入偏差
在 mmpose/datasets/pipelines/top_down_transform.py 中,TopDownGenerateTarget支持三种编码方案(encoding参数:MSRA、Megvii、UDP),并通过布尔开关unbiased_encoding决定是否采用 DARK 的无偏编码。默认配置为encoding='MSRA'、unbiased_encoding=False。
标准的 MSRA 编码流程(unbiased_encoding=False分支)为:
feat_stride = image_size / [W, H] mu_x = int(joints_3d[joint_id][0] / feat_stride[0] + 0.5) mu_y = int(joints_3d[joint_id][1] / feat_stride[1] + 0.5)这里将连续的真实坐标映射到热图网格时使用了int(... + 0.5)的四舍五入取整,高斯分布的中心被强制对齐到整数像素,从而引入最多 ±0.5 像素的量化误差。这个误差在把热图解码回原图时会以特征步长(feat_stride)倍数放大。
2.2 DARK 无偏编码:保留亚像素位置
当unbiased_encoding=True时(对应源码 L325-L348),代码不再取整,而是直接在浮点中心上放置高斯分布:
feat_stride = image_size / [W, H] mu_x = joints_3d[joint_id][0] / feat_stride[0] mu_y = joints_3d[joint_id][1] / feat_stride[1] ... target[joint_id] = np.exp(-((x - mu_x)**2 + (y - mu_y)**2) / (2 * sigma**2))此时mu_x、mu_y是亚像素精度的浮点数,每个热图像素的值按照其与真实中心的连续距离计算,高斯分布的中心得以“落”在真实位置,从而消除取整带来的系统偏差。这就是论文中“生成无偏/精确热图”(unbiased/accurate heatmaps)的仓库实现。
值得注意的实现细节:无偏编码分支用全图逐点计算高斯(x = np.arange(0, W, 1)),而标准分支只在一个2*tmp_size+1的局部窗口内生成高斯并切片写入(L362-L379)。无偏分支同样遵循 3-sigma 规则(tmp_size = sigma * 3)做边界检查,越界关节会被置为不可见。
2.3 在训练配置中的开启方式
在仓库的 dark 系列配置中,训练管线里即开启了无偏编码。以 res50_coco_256x192_dark.py 为例:
dict(type='TopDownGenerateTarget', sigma=2, unbiased_encoding=True),其中sigma=2控制训练热图中高斯分布的尺度,它与解码端的调制核(modulate_kernel)存在严格的对应关系(见下文)。
三、解码端:分布感知的坐标解码
3.1 解码入口与调用链
推理时,TopDown检测器在 top_down.py 中调用keypoint_head.decode(),该方法定义于 topdown_heatmap_base_head.py,最终进入评测核心函数keypoints_from_heatmaps(定义于 mmpose/core/evaluation/top_down_eval.py):
preds, maxvals = keypoints_from_heatmaps( output, c, s, unbiased=self.test_cfg.get('unbiased_decoding', False), post_process=self.test_cfg.get('post_process', 'default'), kernel=self.test_cfg.get('modulate_kernel', 11), ... )关键参数均来自test_cfg:post_process='unbiased'触发 DARK 解码;modulate_kernel控制高斯调制核大小(默认 11)。需要注意的是,源码中还保留了一个已废弃的unbiased布尔参数,若设置unbiased=True会发出弃用警告并自动归一化为post_process='unbiased'(L555-L560),因此新配置一律直接使用post_process='unbiased'。
3.2 标准解码 vs DARK 解码
keypoints_from_heatmaps中非 UDP 分支的解码逻辑(L589-L612)清晰地对比了三种后处理:
post_process='default'(标准方法):先取热图最大值_get_max_preds,然后根据最大值两侧邻居的差分符号施加固定的±0.25 像素偏移。这个经验性偏移是启发式的,当真实分布不对称时会产生系统性偏差——这正是 DARK 论文批评的对象。post_process='unbiased'(DARK):同样先取最大值定位初值,但随后对热图执行高斯调制 + 对数变换 +泰勒展开亚像素修正(_taylor)。post_process='megvii':仅对热图做高斯模糊(_gaussian_blur),并施加 +0.5 偏移与特殊分数归一化(maxvals = maxvals / 255.0 + 0.5)。
DARK 解码的核心流程(L591-L597):
if post_process == 'unbiased': # alleviate biased coordinate # apply Gaussian distribution modulation. heatmaps = np.log(np.maximum(_gaussian_blur(heatmaps, kernel), 1e-10)) for n in range(N): for k in range(K): preds[n][k] = _taylor(heatmaps[n][k], preds[n][k])三步依次是:
- 高斯分布调制:用
_gaussian_blur(L399-L438)对预测热图做核大小为modulate_kernel的高斯模糊,同时归一化回原始峰值(heatmaps[i, j] *= origin_max / np.max(...)),使热图分布更接近训练时的高斯形态; - 对数变换:
np.log将热图从响应值域转换为对数域,便于后续泰勒展开直接拟合对数高斯(即二次型)曲面; - 泰勒展开修正:
_taylor(L298-L332)在初值点计算一阶导数(梯度)与二阶导数(海森矩阵),按牛顿法一步求亚像素偏移:
dx = 0.5 * (heatmap[py][px + 1] - heatmap[py][px - 1]) dy = 0.5 * (heatmap[py + 1][px] - heatmap[py - 1][px]) dxx = 0.25 * (heatmap[py][px + 2] - 2 * heatmap[py][px] + heatmap[py][px - 2]) dxy = 0.25 * (heatmap[py + 1][px + 1] - heatmap[py - 1][px + 1] - heatmap[py + 1][px - 1] + heatmap[py - 1][px - 1]) dyy = 0.25 * (heatmap[py + 2][px] - 2 * heatmap[py][px] + heatmap[py - 2][px]) derivative = np.array([[dx], [dy]]) hessian = np.array([[dxx, dxy], [dxy, dyy]]) if dxx * dyy - dxy**2 != 0: hessianinv = np.linalg.inv(hessian) offset = -hessianinv @ derivative coord += offset其数学本质:假设预测响应在对数域近似为高斯(二次型),则最优亚像素位置即梯度为零的点,coord_new = coord - H⁻¹·∇f。注意_taylor要求初值位于热图内(1 < px < W-2 and 1 < py < H-2),靠近边界时直接返回原始坐标。
3.3 调制核与训练 sigma 的配套原则
_gaussian_blur与keypoints_from_heatmaps的文档字符串均明确给出对应关系:核大小必须与训练热图的 sigma 匹配——K=17对应sigma=3,K=11对应sigma=2。因此 dark 配置中训练侧TopDownGenerateTarget(sigma=2, unbiased_encoding=True)与推理侧modulate_kernel=11成对出现,切勿随意改动其中一侧。
3.4 与 UDP 的关系:post_dark_udp
仓库还提供了post_dark_udp(L335-L396),它是 DARK 解码在 UDP(The Devil is in the Details, CVPR 2020)数据流程下的向量化实现:对热图先做高斯模糊,再np.clip(0.001, 50)后取对数,随后通过预填充(np.pad(..., mode='edge'))与平铺索引一次性完成全 batch 的导数/海森矩阵计算,最后用np.linalg.inv(hessian + eps * eye(2))求逆并做np.einsum修正。它在keypoints_from_heatmaps的use_udp=True分支中被调用(L567-L570),同时在 bottom-up 范式的人群分组后处理(mmpose/core/post_processing/group.py)中也被复用,是 DARK 思想在仓库内二次扩散的体现。
四、ViTPose 仓库中的 DARK 配置实践
4.1 完整的 dark 配置范式
将编码端与解码端合起来,一个标准的 dark 训练配置(以 hrnet_w32_coco_256x192_dark.py 为例)包含三个关键位置:
# 训练侧:无偏编码,sigma=2 dict(type='TopDownGenerateTarget', sigma=2, unbiased_encoding=True), # 推理侧:DARK 解码,调制核与 sigma 配套 test_cfg=dict( flip_test=True, post_process='unbiased', shift_heatmap=True, modulate_kernel=11)配套的还有data_cfg中的输入输出尺寸(image_size=[192, 256]、heatmap_size=[48, 64],即 4 倍下采样)以及标准优化配置(Adam、lr=5e-4、step 学习率策略、210 epochs)。对比同尺寸的普通配置可以发现,dark 版本与 baseline 的唯一区别正是上述编码开关与后处理模式,充分体现了 DARK “模型无关插件”的定位。
4.2 仓库提供的 dark 模型家族
ViTPose 仓库在 COCO 与 MPII 上提供了完整的 dark 配置与权重发布记录:
- COCO(ResNet 骨干):resnet_dark_coco.md 收录 ResNet-50/101/152 在 256x192 与 384x288 两种分辨率下的 6 个 dark 模型,例如
res50_coco_256x192_dark(AP 0.724)与res152_coco_384x288_dark(AP 0.757); - COCO(HRNet 骨干):hrnet_dark_coco.md 收录 HRNet-W32/W48 的 4 个 dark 模型,最佳为
hrnet_w48_coco_384x288_dark(AP 0.772,AP75 0.836); - MPII(HRNet 骨干):hrnet_dark_mpii.md 收录 2 个 dark 模型,
hrnet_w48_mpii_256x256_dark达到 PCKh@0.5 = 0.905、Mean@0.1 = 0.360。
各配置对应的.py文件与预训练权重下载记录统一维护在同目录的.yml文件(如 hrnet_dark_coco.yml)中,模型名规范为topdown_heatmap_<backbone>_coco_<input_size>_dark。这些指标仅作为仓库内配置复现结果供参考,实际以自行训练/评测为准。
4.3 在 ViT 骨干上复用的思路
从源码结构看,DARK 完全作用于数据标签生成与热图后处理两层,与骨干网络解耦:TopDownGenerateTarget属于数据管线,keypoints_from_heatmaps属于头部解码,二者均不感知 backbone 类型。因此对于 ViTPose 的 Vision Transformer 骨干(如 mmpose/models/backbones/vit.py),只需沿用相同的unbiased_encoding=True与post_process='unbiased'组合即可获得同等收益,无需修改网络结构——这正是 DARK 作为“即插即用”插件的设计意图。
五、测试验证:从单元测试看 DARK 的行为约束
仓库在 tests/test_evaluation/test_top_down_eval.py 中为 DARK 解码提供了直接的单测覆盖,可据此验证实现行为:
preds, maxvals = keypoints_from_heatmaps( heatmaps, center, scale, post_process='unbiased') assert_array_almost_equal(preds, np.array([[[126, 126]]]), decimal=4)测试构造一个64x64全 1、峰值(2.0)位于(31, 31)的对称热图,post_process='unbiased'解码后仍应得到对称结果(126, 126)——对于对称分布,泰勒修正偏移为零,验证了 DARK 在无偏输入下不会引入额外偏差。同时测试还断言post_process='unbiased'时kernel=0会触发断言错误(AssertionError),印证了 DARK 解码必须携带合法的调制核大小这一约束(源码 L531-L532)。
六、总结与使用建议
DARK 之所以能成为姿态估计工具箱中的常青技巧,在于它用极小代价(两个开关、一个后处理函数)修正了热图流程两端最容易被忽视的系统偏差:
| 环节 | 标准做法 | DARK 做法 | 仓库实现位置 |
|---|---|---|---|
| 编码 | 坐标取整到整数像素放置高斯 | 浮点中心放置高斯(无偏编码) | top_down_transform.py L325-L348 |
| 解码 | 最大值 + 固定 ±0.25 偏移 | 高斯调制 + 对数域泰勒展开求亚像素偏移 | top_down_eval.py L589-L597、L298-L332 |
| 配置 | —— | unbiased_encoding=True+post_process='unbiased'+modulate_kernel=11 | hrnet_w32_coco_256x192_dark.py |
在实际项目中启用 DARK 时,请务必遵守三条配套原则:训练 sigma 与调制核必须匹配(sigma=2 ↔ kernel=11,sigma=3 ↔ kernel=17);编码与解码必须同时开启(仅开一端会因训练/推理分布不一致而效果打折);注意输入分辨率与热图下采样倍率,它们共同决定亚像素修正折算回原图后的实际位移量。参考仓库中的 resnet_dark_coco.yml 等元数据文件,可以快速复现并在此基础上做增量实验。
- 人工智能
- 计算机视觉
- 深度学习
【免费下载链接】ViTPose
The official repo for [NeurIPS'22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [TPAMI'23] "ViTPose++: Vision Transformer for Generic Body Pose Estimation"
相关推荐
DarkPose(DARK)分布感知坐标表示在 MMPose 中的原理、源码实现与训练配置实战
DarkPose(DARK)分布感知坐标表示在 MMPose 中的原理、源码实现与训练配置实战 本篇技术指南围绕 CVPR 2020 论文《Distributi
计算机视觉人工智能深度学习ResNet + DarkPose 在 COCO 人体姿态估计中的应用:ViTPose 仓库 topdown_heatmap 配置解析与无偏热图解码原理
ResNet + DarkPose 在 COCO 人体姿态估计中的应用:ViTPose 仓库 topdown_heatmap 配置解析与无偏热图解码原理 本文以
人工智能计算机视觉深度学习ViTPose 仓库中的 ViPNAS 姿态估计模型:COCO 顶级热图配置、网络结构搜索与源码解析
ViTPose 仓库中的 ViPNAS 姿态估计模型:COCO 顶级热图配置、网络结构搜索与源码解析 导读 ViPNAS(CVPR'2021)是一套面向高效人体
人工智能计算机视觉深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考