- 人工智能
- 计算机视觉
- 深度学习
【免费下载链接】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"
全身姿态估计(whole-body pose estimation)的目标是在人体全身(包括面部、双手、双脚与躯干)上定位密集关键点。本文以 configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/README.md 为核心,系统讲解 top-down(自上而下)热图方法的两阶段流程、数据集组织、配置文件结构、训练测试命令与源码实现原理。读者读完本文后,将能够理解 top-down 全身姿态估计的完整技术链条,并可直接基于本仓库的配置在 COCO-WholeBody 与 Halpe 数据集上训练、评测与部署模型。
方法概览:Top-down 两阶段流程
与 bottom-up(自下而上)方法"先检测全部关键点、再按人体实例分组关联"的思路不同,top-down 方法把全身姿态估计拆解为两个独立阶段:
- 人体检测阶段:先用目标检测器在整幅图像中定位每一个人体,输出人体边界框(human bounding box);
- 单人多关键点估计阶段:基于每个人体边界框裁剪出单人区域,再由姿态估计网络回归该人的全身关键点。
这种"先检测、后估计"的解耦设计,让姿态估计网络只需面对单人输入,避免了多人场景下的关键点分组歧义,这也是 top-down 方法精度通常优于 bottom-up 方法的主要原因。原文明确强调了这一范式:"Top-down methods divide the task into two stages: human detection and whole-body pose estimation. They perform human detection first, followed by single-person whole-body pose estimation given human bounding boxes."
在实现层面,仓库中的TopDown检测器类正是这一范式的载体,见 mmpose/models/detectors/top_down.py 中的@POSENETS.register_module() class TopDown(BasePose)。其构造流程依次构建backbone(骨干网络)、可选neck与keypoint_head(关键点头),并通过init_weights加载预训练权重。
关键点热图表示:不回归坐标,回归似然分布
top-down 姿态估计网络并不直接输出关键点的 (x, y) 坐标,而是为每个关键点生成一张热图(heatmap)。热图上每个位置的取值代表"该位置是关键点"的似然(likelihood)大小,峰值位置即对应关键点的预测坐标。原文对此的表述是:"Instead of estimating keypoint coordinates directly, the pose estimator will produce heatmaps which represent the likelihood of being a keypoint."
热图表示之所以成为主流,是因为它对关键点位置提供了平滑的监督信号,比直接回归坐标更容易优化,且天然支持多峰值与不确定性表达。在仓库配置中,训练阶段通过TopDownGenerateTarget以高斯核(sigma=2)为每个标注关键点生成高斯热图目标;推理阶段则对预测热图取峰值并做坐标解码(见下文post_process配置)。
仓库配置中"为预测不同数量的关键点"体现在channel_cfg:
channel_cfg = dict( num_output_channels=133, # 输出热图通道数 = 关键点数量 dataset_joints=133, # 数据集标注关键点数量 dataset_channel=[list(range(133))], inference_channel=list(range(133)))COCO-WholeBody 使用 133 个关键点,Halpe 使用 136 个关键点,因此对应配置中的num_output_channels分别为 133 与 136。
数据集准备:COCO-WholeBody 与 Halpe
本目录下配置覆盖两个全身数据集,其标注定义分别位于 configs/base/datasets/coco_wholebody.py 与 configs/base/datasets/halpe.py。其中dataset_info完整定义了每个关键点的名称、编号、颜色、所属部位(upper/lower/空)以及左右互换关系(swap)——后者在随机翻转增强(TopDownRandomFlip)与推理时翻转测试(flip_test)中用于恢复关键点对应关系。
COCO-WholeBody(133 关键点)
COCO-WholeBody(ECCV 2020)在 COCO 17 个身体关键点基础上扩展了面部(68 点)、手部(42 点)与脚部(6 点),共133 个关键点。完整数据准备步骤见 docs/en/tasks/2d_wholebody_keypoint.md,要点如下:
- 图像使用 COCO 2017 Train/Val 集;
- 需要下载 COCO-WholeBody 的
coco_wholebody_train_v1.0.json与coco_wholebody_val_v1.0.json标注文件; - 评测还需要 COCO val2017 的人体检测结果文件
COCO_val2017_detections_AP_H_56_person.json; - 数据按如下结构组织(可软链接到
$MMPOSE/data):
data/coco ├── annotations │ ├── coco_wholebody_train_v1.0.json │ └── coco_wholebody_val_v1.0.json ├── person_detection_results │ └── COCO_val2017_detections_AP_H_56_person.json ├── train2017 └── val2017- 评估依赖 Extended COCO API,需执行
pip install xtcocotools。
对应的数据集类为TopDownCocoWholeBodyDataset,定义在 mmpose/datasets/datasets/top_down/topdown_coco_wholebody_dataset.py 中,继承自TopDownCocoDataset。
Halpe(136 关键点)
Halpe(CVPR 2020,PaStaNet 项目的一部分)标注136 个关键点,在 COCO-WholeBody 基础上增加了更多密集标注。其数据组织方式见 docs/en/tasks/2d_wholebody_keypoint.md:
data/halpe ├── annotations │ ├── halpe_train_v1.json │ └── halpe_val_v1.json ├── person_detection_results │ └── COCO_val2017_detections_AP_H_56_person.json ├── hico_20160224_det # 训练图像(来自 HICO-Det) └── val2017 # 验证图像(来自 COCO)对应的数据集类为TopDownHalpeDataset,定义在 mmpose/datasets/datasets/top_down/topdown_halpe_dataset.py 中,同样继承自TopDownCocoDataset。Halpe 的评估同样需要xtcocotools。
配置解析:以 ViTPose 全身模型为例
本仓库是 ViTPose(NeurIPS 2022 论文 "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation")的官方仓库,因此在全身姿态估计目录下提供了全套 ViTPose 配置,位于 configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/。以 ViTPose_base_wholebody_256x192.py 为例,完整解读如下。
基础配置与训练超参
_base_ = [ '../../../../_base_/default_runtime.py', '../../../../_base_/datasets/coco_wholebody.py' ] evaluation = dict(interval=10, metric='mAP', save_best='AP') optimizer = dict(type='Adam', lr=5e-4) optimizer_config = dict(grad_clip=None) # learning policy lr_config = dict( policy='step', warmup='linear', warmup_iters=500, warmup_ratio=0.001, step=[170, 200]) total_epochs = 210要点说明:
_base_引用了运行时常量 configs/base/default_runtime.py 与数据集定义,其中{{_base_.dataset_info}}用于把coco_wholebody.py中定义的关键点元信息注入数据集;evaluation每 10 个 epoch 评测一次,指标为mAP,并按AP保存最优模型;- 优化器采用 Adam,初始学习率
5e-4;学习率采用 step 策略,在 170 与 200 epoch 处衰减; - 线性 warmup 500 步、比例 0.001;总训练 210 epoch。
模型结构:ViT 骨干 + 热图头
model = dict( type='TopDown', pretrained=None, backbone=dict( type='ViT', img_size=(256, 192), patch_size=16, embed_dim=768, depth=12, num_heads=12, ratio=1, use_checkpoint=False, mlp_ratio=4, qkv_bias=True, drop_path_rate=0.3, ), keypoint_head=dict( type='TopdownHeatmapSimpleHead', in_channels=768, num_deconv_layers=2, num_deconv_filters=(256, 256), num_deconv_kernels=(4, 4), extra=dict(final_conv_kernel=1, ), out_channels=channel_cfg['num_output_channels'], loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), train_cfg=dict(), test_cfg=dict( flip_test=True, post_process='default', shift_heatmap=True, modulate_kernel=11))- 模型类型为
TopDown(对应 mmpose/models/detectors/top_down.py 中的TopDown类); - 骨干网络为 ViT(实现见 mmpose/models/backbones/vit.py),ViTPose 的四个规格对应不同超参:
| 规格 | embed_dim | depth | num_heads | 对应配置 |
|---|---|---|---|---|
| ViTPose-S | 384 | 12 | 12 | ViTPose_small_wholebody_256x192.py |
| ViTPose-B | 768 | 12 | 12 | ViTPose_base_wholebody_256x192.py |
| ViTPose-L | 1024 | 24 | 16 | ViTPose_large_wholebody_256x192.py |
| ViTPose-H | 1280 | 32 | 16 | ViTPose_huge_wholebody_256x192.py |
- 关键点头为
TopdownHeatmapSimpleHead(实现见 mmpose/models/heads/topdown_heatmap_simple_head.py)。ViT 配置中使用 2 层反卷积(deconv)将48×64的低分辨率热图上采样,最终输出 133 通道热图; - 损失函数为
JointsMSELoss(MSE 热图损失),并使用use_target_weight=True让可见性权重参与损失计算; test_cfg开启flip_test(翻转测试)、post_process='default'(默认坐标解码)、shift_heatmap=True(翻转热图平移校正)与modulate_kernel=11(用于 DARK 坐标解码)。
从源码看,TopdownHeatmapSimpleHead的inference_model方法(mmpose/models/heads/topdown_heatmap_simple_head.py)在flip_pairs不为空时会调用flip_back融合正反热图,并在shift_heatmap=True时执行"特征未对齐"的平移校正:
if flip_pairs is not None: output_heatmap = flip_back(...) # feature is not aligned, shift flipped heatmap for higher accuracy if self.test_cfg.get('shift_heatmap', False): output_heatmap[:, :, :, 1:] = output_heatmap[:, :, :, :-1]数据流水线:训练增强与推理裁剪
train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='TopDownRandomFlip', flip_prob=0.5), dict(type='TopDownHalfBodyTransform', num_joints_half_body=8, prob_half_body=0.3), dict(type='TopDownGetRandomScaleRotation', rot_factor=40, scale_factor=0.5), dict(type='TopDownAffine'), dict(type='ToTensor'), dict(type='NormalizeTensor', mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), dict(type='TopDownGenerateTarget', sigma=2), dict(type='Collect', keys=['img', 'target', 'target_weight'], meta_keys=[...]), ]- 训练阶段:随机水平翻转(50% 概率)→ 半身变换(以 30% 概率聚焦上半身/下半身关键点,需至少 8 个可见关键点)→ 随机缩放旋转(旋转 ±40°、缩放 0.5)→ 仿射变换 → 归一化(ImageNet 均值/标准差)→ 生成 sigma=2 的高斯热图目标;
- 验证/测试阶段(
val_pipeline/test_pipeline):仅保留仿射变换、归一化与收集,不做数据增强。
数据加载配置
data_cfg = dict( image_size=[192, 256], heatmap_size=[48, 64], num_output_channels=133, num_joints=133, ... use_gt_bbox=False, det_bbox_thr=0.0, bbox_file='data/coco/person_detection_results/' 'COCO_val2017_detections_AP_H_56_person.json', ) data = dict( samples_per_gpu=64, workers_per_gpu=2, val_dataloader=dict(samples_per_gpu=32), test_dataloader=dict(samples_per_gpu=32), train=dict(type='TopDownCocoWholeBodyDataset', ann_file='data/coco/annotations/coco_wholebody_train_v1.0.json', img_prefix='data/coco/train2017/', ...), val=dict(type='TopDownCocoWholeBodyDataset', ann_file='data/coco/annotations/coco_wholebody_val_v1.0.json', img_prefix='data/coco/val2017/', ...), test=dict(...))- 输入图像尺寸
[192, 256](W×H),对应热图尺寸[48, 64](下采样 4 倍); use_gt_bbox=False表示评测时使用外部人体检测框(即bbox_file中的检测结果),这是与检测器协同评测的标准做法。
其他骨干配置:HRNet、ResNet 与 ViPNAS
除了 ViTPose,本目录还提供了多套传统骨干配置,便于对比与选型:
- HRNet:以 hrnet_w32_coco_wholebody_256x192.py 为代表。与 ViT 不同,HRNet 的高分辨率表示无需反卷积,直接使用
num_deconv_layers=0、in_channels=32的TopdownHeatmapSimpleHead,由一个 1×1 卷积输出热图。HRNet 实现见 mmpose/models/backbones/hrnet.py; - ResNet(SimpleBaseline 范式):以 res50_coco_wholebody_256x192.py 为代表,使用 3 层反卷积上采样到热图分辨率,对应 "Simple Baselines for Human Pose Estimation"(ECCV 2018);
- ViPNAS(NAS 搜索的高效网络):以 vipnas_mbv3_coco_wholebody_256x192.py 与 vipnas_res50_coco_wholebody_256x192.py 为代表,适合对速度有要求的场景;
- DARK 变体:
*_dark.py配置启用 DARK(Distribution-Aware Coordinate Representation,CVPR 2020)坐标解码,配合post_process与modulate_kernel参数提升定位精度。
Halpe 数据集方面,仓库提供了 hrnet_w32_halpe_256x192.py 与 hrnet_w48_halpe_384x288_dark_plus.py。注意 Halpe 配置的num_output_channels=136,与 COCO-WholeBody 的 133 不同。
训练:单卡与多卡
单卡训练:
python tools/train.py configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_base_wholebody_256x192.py指定工作目录:
python tools/train.py ${CONFIG_FILE} --work-dir ${YOUR_WORK_DIR}多卡分布式训练:
./tools/dist_train.sh ${CONFIG_FILE} ${GPU_NUM} [optional arguments]例如 8 卡训练,并设置端口避免冲突:
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 ./tools/dist_train.sh configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_base_wholebody_256x192.py 8训练入口为 tools/train.py,分布式启动脚本为 tools/dist_train.sh。若需断点续训,可添加--resume_from work_dirs/.../latest.pth。
测试与评估
# 单卡测试 python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [--out ${RESULT_FILE}] \ [--eval ${EVAL_METRICS}] [--cfg-options ${CFG_OPTIONS}] # 多卡测试 ./tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} \ [--out ${RESULT_FILE}] [--eval ${EVAL_METRICS}]以 COCO-WholeBody 配置为例:
python tools/test.py \ configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/hrnet_w48_coco_wholebody_384x288_dark_plus.py \ ${CHECKPOINT_FILE} \ --eval mAP说明:
- 本目录配置的
evaluation.metric='mAP',因此--eval mAP即可得到全身各部位 AP/AR; - 可选参数
--out保存结果文件、--fuse-conv-bn融合卷积与 BN 以略微提升推理速度、--cfg-options用于命令行覆盖配置项; - 测试入口为 tools/test.py,分布式脚本为 tools/dist_test.sh。
运行 Demo:图片与视频
仓库提供了完整的全身姿态 Demo 脚本,详见 demo/docs/2d_wholebody_pose_demo.md。
使用 GT 人体框的图片 Demo
python demo/top_down_img_demo.py \ ${MMPOSE_CONFIG_FILE} ${MMPOSE_CHECKPOINT_FILE} \ --img-root ${IMG_ROOT} --json-file ${JSON_FILE} \ --out-img-root ${OUTPUT_DIR} \ [--show --device ${GPU_ID or CPU}] \ [--kpt-thr ${KPT_SCORE_THR}]仓库自带的测试数据示例(tests/data/coco/下提供了test_coco.json标注与示例图片):
python demo/top_down_img_demo.py \ configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/hrnet_w48_coco_wholebody_384x288_dark_plus.py \ ${MMPOSE_CHECKPOINT_FILE} \ --img-root tests/data/coco/ --json-file tests/data/coco/test_coco.json \ --out-img-root vis_resultsCPU 推理只需追加--device=cpu。
使用 mmdet 检测器的图片/视频 Demo
若需端到端"检测 + 姿态估计",可先用 mmdetection 检测人体,再送入本仓库的姿态模型:
python demo/top_down_img_demo_with_mmdet.py \ ${MMDET_CONFIG_FILE} ${MMDET_CHECKPOINT_FILE} \ ${MMPOSE_CONFIG_FILE} ${MMPOSE_CHECKPOINT_FILE} \ --img-root ${IMG_ROOT} --img ${IMG_FILE} \ --out-img-root ${OUTPUT_DIR} \ [--show --device ${GPU_ID or CPU}] \ [--bbox-thr ${BBOX_SCORE_THR} --kpt-thr ${KPT_SCORE_THR}]mmdet 检测器配置可复用仓库自带的 demo/mmdetection_cfg/faster_rcnn_r50_fpn_coco.py 等。视频版本同理:
python demo/top_down_video_demo_with_mmdet.py \ ${MMDET_CONFIG_FILE} ${MMDET_CHECKPOINT_FILE} \ ${MMPOSE_CONFIG_FILE} ${MMPOSE_CHECKPOINT_FILE} \ --video-path ${VIDEO_FILE} \ --out-video-root ${OUTPUT_VIDEO_ROOT} \ [--show --device ${GPU_ID or CPU}] \ [--bbox-thr ${BBOX_SCORE_THR} --kpt-thr ${KPT_SCORE_THR}]相关脚本包括 demo/top_down_img_demo.py、demo/top_down_img_demo_with_mmdet.py、demo/top_down_video_demo_with_mmdet.py,推理 API 封装在 mmpose/apis/inference.py。
评测结果与指标解读
本目录各算法子目录下的.md与.yml文件记录了在 COCO-WholeBody v1.0 val 上的结果(检测器在 COCO val2017 上人体 AP 为 56.4)。指标按部位拆分,包括 Body(身体)、Foot(脚)、Face(脸)、Hand(手)与整体 Whole 的 AP/AR。
以 hrnet_coco-wholebody.md 中 HRNet-w48 为例(384×288 输入):
| Arch | Input Size | Body AP | Body AR | Foot AP | Foot AR | Face AP | Face AR | Hand AP | Hand AR | Whole AP | Whole AR |
|---|---|---|---|---|---|---|---|---|---|---|---|
| pose_hrnet_w48 | 256x192 | 0.700 | 0.776 | 0.672 | 0.785 | 0.656 | 0.743 | 0.534 | 0.639 | 0.579 | 0.681 |
| pose_hrnet_w48 | 384x288 | 0.722 | 0.790 | 0.694 | 0.799 | 0.777 | 0.834 | 0.587 | 0.679 | 0.631 | 0.716 |
可见输入分辨率越高、网络容量越大,各部位指标整体越优;同时手部(Hand)关键点数量多且尺度小,指标通常低于身体(Body)。ResNet 与 ViPNAS 的完整结果分别记录在 resnet_coco-wholebody.md 与 vipnas_coco-wholebody.md。Halpe 上的结果见 halpe/hrnet_dark_halpe.md,其中+后缀表示先在原始 COCO 上预训练、再在 Halpe 上微调,可获得更好的性能。
对应模型权重与日志的元数据索引记录在各.yml文件中,例如 hrnet_coco-wholebody.yml,可用于检索下载对应 checkpoint 与训练日志。
推理加速建议
对于 top-down 模型,可通过调整配置与检测器来提升推理速度:
- 在
test_cfg中设置flip_test=False,关闭翻转测试(省去一次前向传播); - 保持
post_process='default',避免使用更耗时的解码方式; - 使用更快的检测器(如单阶段检测器)作为人体框来源,因为 top-down 流程的总体耗时很大程度上取决于检测阶段。
对应配置项可直接在model.test_cfg中修改,也可以在测试命令中通过--cfg-options model.test_cfg.flip_test=False临时覆盖。
小结
本文围绕 top-down 热图全身姿态估计的两阶段范式展开:先由检测器给出人体框,再由姿态网络输出各关键点的似然热图。仓库在 configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/ 下提供了 ViTPose(S/B/L/H 四种规格)、HRNet、ResNet、ViPNAS 等多套配置,覆盖 COCO-WholeBody(133 点)与 Halpe(136 点)两大数据集。从 TopDown 检测器、TopdownHeatmapSimpleHead 热图头,到 TopDownCocoWholeBodyDataset 数据集类,源码与配置一一对应,读者可以按本文步骤完成数据准备、训练、评测与 Demo 部署的全流程。
- 人工智能
- 计算机视觉
- 深度学习
【免费下载链接】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"
相关推荐
ViTPose 手部姿态估计实战:COCO-WholeBody-Hand 上的 ResNet-50 Top-Down Heatmap 训练与评估全解析
ViTPose 手部姿态估计实战:COCO WholeBody Hand 上的 ResNet 50 Top Down Heatmap 训练与评估全解析 导读 :
人工智能计算机视觉深度学习ViTPose 中 SEResNet 在 COCO 上的 2D 人体姿态估计:top-down 热图模型配置与源码解析
ViTPose 中 SEResNet 在 COCO 上的 2D 人体姿态估计:top down 热图模型配置与源码解析 本文以 ViTPose 仓库中 conf
人工智能计算机视觉深度学习ViTPose 仓库 ResNet+SimpleBaseline2D 人体姿态估计实战:COCO Top-Down 热图配置、训练与评测深度解析
ViTPose 仓库 ResNet+SimpleBaseline2D 人体姿态估计实战:COCO Top Down 热图配置、训练与评测深度解析 本篇技术指南以
人工智能计算机视觉深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考