news 2026/10/15 18:06:07

ViTPose 仓库 MPI-INF-3DHP 上 SimpleBaseline3D(PoseLift)训练与评估实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ViTPose 仓库 MPI-INF-3DHP 上 SimpleBaseline3D(PoseLift)训练与评估实战指南
  • 人工智能
  • 计算机视觉
  • 深度学习

【免费下载链接】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"

项目地址:https://gitcode.com/gh_mirrors/vi/ViTPose
点击查看免费下载

本篇技术指南围绕 ViTPose 仓库中 simplebaseline3d_mpi-inf-3dhp.md 文档,系统讲解如何在 MPI-INF-3DHP 数据集上使用 SimpleBaseline3D 完成「2D 关键点 → 3D 姿态」的 lifting 任务:包括完整配置解析、数据预处理、训练与测试命令、评估指标(MPJPE / P-MPJPE / 3DPCK / 3DAUC)的源码级实现原理,以及官方记录的模型精度。读完本文,你将掌握在 ViTPose 仓库内复现该实验的全部关键环节。

一、文档与背景:SimpleBaseline3D 在 ViTPose 中的定位

ViTPose 仓库的 pose_lift 目录下提供了「2D 人体关键点 → 3D 人体姿态」的经典基线方案。SimpleBaseline3D 出自论文A simple yet effective baseline for 3d human pose estimation(ICCV'2017),其核心思想是把 3D 姿态估计拆成两个阶段:

  1. Image → 2D Pose(由成熟的 2D 姿态估计模型完成);
  2. 2D Pose → 3D Pose(即本配置所实现的 lifting 阶段)。

正如 pose_lift/README.md 所述,作者发现将 Ground Truth(GT)2D 关节位置「提升」到 3D 空间是一个可以用很低误差解决的任务。基于 2D 人体姿态估计的成功经验,该方案直接对 2D 关节坐标进行回归,结构简单但效果扎实。

本文对应的文档给出了在 MPI-INF-3DHP 数据集上、使用 GT 2D 检测结果作为输入的官方实验结果:

ArchMPJPEP-MPJPE3DPCK3DAUCckptlog
simple_baseline_3d_tcn84.353.285.052.0ckptlog

注:与原论文不同,ViTPose 仓库的实现没有使用max-norm constraint,因为作者发现去掉该约束后收敛更好、性能更优。该结论在模型结构中表现为 tcn.py 的max_norm参数保持为None。

对应结果同样记录在 simplebaseline3d_mpi-inf-3dhp.yml 中(3DAUC 52.0、3DPCK 85.0、MPJPE 84.3、P-MPJPE 53.2),可直接通过model-index.yml检索。

二、数据集:MPI-INF-3DHP 与 17 关键点定义

MPI-INF-3DHP(3DV'2017)是一个面向 in-the-wild 场景的单目 3D 人体姿态估计数据集,论文为Monocular 3D Human Pose Estimation In The Wild Using Improved CNN Supervision。ViTPose 仓库在 configs/base/datasets/mpi_inf_3dhp.py 中定义了它的关键点信息,共 17 个关键点:

idx名称类型swap 对称点
0head_topupper—
1neckupper—
2right_shoulderupperleft_shoulder
3right_elbowupperleft_elbow
4right_wristupperleft_wrist
5left_shoulderupperright_shoulder
6left_elbowupperright_elbow
7left_wristupperright_wrist
8right_hiplowerleft_hip
9right_kneelowerleft_knee
10right_anklelowerleft_ankle
11left_hiplowerright_hip
12left_kneelowerright_knee
13left_anklelowerright_ankle
14root(pelvis)lower—
15spineupper—
16headupper—

数据集实现位于 body3d_mpi_inf_3dhp_dataset.py,其JOINT_NAMES与dataset_info一致。该类支持三种 2D 关节来源(SUPPORTED_JOINT_2D_SRC):

  • gt:直接读取注解文件中的 2D 标注;
  • detection:从 2D 关键点检测结果文件(npz)中读取;
  • pipeline:在数据流水线中由 2D 检测模型在线生成。

本配置使用joint_2d_src='gt',即文档标题所指的「with ground truth 2D detections」实验设定。2D 关节来源的可选值与加载逻辑可在 body3d_mpi_inf_3dhp_dataset.py 中看到。

2.1 数据预处理

使用仓库提供的预处理脚本 preprocess_mpi_inf_3dhp.py 将原始数据转换为 npz 注解文件:

python tools/dataset/preprocess_mpi_inf_3dhp.py

该脚本的核心处理逻辑(可从源码确认)包括:

  • 训练集使用 subject 1–8、每个 subject 的 Seq1/Seq2、8 个相机视角(Cam0/1/2/4/5/6/7/8),帧数表见 preprocess_mpi_inf_3dhp.py;
  • 测试集使用 TS1–TS6,可输出mpi_inf_3dhp_test_valid.npz(仅有效帧)或mpi_inf_3dhp_test_all.npz(全部帧),见 preprocess_mpi_inf_3dhp.py;
  • 从 3D 关节坐标生成 2D 投影,并按可见性规则生成关节权重;
  • 计算 2D/3D 关节坐标的 mean/std 统计量(joint2d_stats.pkl、joint3d_rel_stats.pkl),这些统计量被直接嵌入配置的归一化参数中(详见下文第四节);
  • 3D 坐标统一乘以0.001转为米制单位,训练图像尺寸为 2048×2048,测试图像分辨率为 1920×1080(subject 5/6),相机内参通过最小二乘估计,见 preprocess_mpi_inf_3dhp.py。

处理后建议将数据放在data/mpi_inf_3dhp目录下(配置中data_root = 'data/mpi_inf_3dhp'),目录内应包含annotations/(mpi_inf_3dhp_train.npz、mpi_inf_3dhp_test_valid.npz、cameras_train.pkl、cameras_test.pkl、joint3d_rel_stats.pkl、joint2d_stats.pkl)与images/图像目录。

三、模型结构:PoseLifter + TCN + TemporalRegressionHead

本配置的模型定义如下(见 simplebaseline3d_mpi-inf-3dhp.py):

model = dict( type='PoseLifter', pretrained=None, backbone=dict( type='TCN', in_channels=2 * 17, stem_channels=1024, num_blocks=2, kernel_sizes=(1, 1, 1), dropout=0.5), keypoint_head=dict( type='TemporalRegressionHead', in_channels=1024, num_joints=16, # do not predict root joint loss_keypoint=dict(type='MSELoss')), train_cfg=dict(), test_cfg=dict(restore_global_position=True))

3.1 PoseLifter:整体检测器框架

PoseLifter 是「把 2D 姿态提升到 3D 姿态」的检测器,内部由 backbone(TCN)、可选的 neck、keypoint_head(TemporalRegressionHead)组成;同时支持可选的traj_backbone/traj_head轨迹模型用于预测绝对根关节位置,并支持loss_semi半监督训练。本配置只使用 pose 模型(无 traj 分支、无半监督分支)。

训练时前向过程为:backbone(input) → keypoint_head(features) → get_loss,回归损失由TemporalRegressionHead计算(见 pose_lifter.py);测试时则通过inference_model与decode恢复归一化前的绝对坐标(见 pose_lifter.py)。

3.2 TCN:时间卷积骨干网络

TCN(Temporal Convolutional Networks)源自 VideoPose3D(CVPR'2019),以 1D 卷积在时间维度上处理关键点序列。本配置的实例化参数含义:

  • in_channels=2 * 17:输入通道数 = 关键点数 × 每关键点特征维数。由于seq_len=1且每个 2D 关键点只取 x、y 两个坐标(PoseSequenceToTensor把[T,K,C]重排为[K*C, T],见 pose3d_transform.py),故为 34 通道;
  • stem_channels=1024:第一个扩展卷积(expand_conv)输出的特征通道数;
  • num_blocks=2、kernel_sizes=(1, 1, 1):一个 1×1 扩展卷积 + 2 个BasicTemporalBlock。由于核大小全为 1,网络退化为纯逐帧映射(无时间上下文),这正是单帧 lifting 的配置;
  • dropout=0.5:每个卷积块后施加 dropout;
  • max_norm=None:不施加权重范数裁剪,这是本实现相对原论文的关键差异。

从 tcn.py 可以看到assert num_blocks == len(kernel_sizes) - 1,且所有核大小必须为奇数;BasicTemporalBlock由conv1(mid_channels=1024)→ dropout → conv2(1×1)→ dropout → 残差连接构成,dilation逐块累积(见 tcn.py)。

3.3 TemporalRegressionHead:回归头与 loss 计算

TemporalRegressionHead 是 VideoPose3D 的回归头:用num_joints * 3个输出通道的 1×1 卷积把 TCN 特征映射为每个关节的 (x, y, z),最终 reshape 为[N, num_joints, 3](见 temporal_regression_head.py)。

  • num_joints=16:由于 root 关节(idx=14)在数据流水线中被移除(remove_root=True),head 只回归 16 个非根关节;
  • loss_keypoint=dict(type='MSELoss'):回归损失采用均方误差,训练时在get_loss中输出键名为reg_loss(见 temporal_regression_head.py);
  • test_cfg=dict(restore_global_position=True):推理/评测时把预测的根相对坐标加上根关节位置恢复为全局坐标,并通过root_position_index把根关节插回第 14 位,见_restore_global_position实现(temporal_regression_head.py)。

四、数据流水线:根中心化、归一化与张量化

训练/验证/测试共用同一套 pipeline(见 simplebaseline3d_mpi-inf-3dhp.py),其背后是 pose3d_transform.py 中注册的三个变换类:

train_pipeline = [ dict( type='GetRootCenteredPose', item='target', visible_item='target_visible', root_index=14, root_name='root_position', remove_root=True), dict( type='NormalizeJointCoordinate', item='target', mean=joint_3d_normalize_param['mean'], std=joint_3d_normalize_param['std']), dict( type='NormalizeJointCoordinate', item='input_2d', mean=joint_2d_normalize_param['mean'], std=joint_2d_normalize_param['std']), dict(type='PoseSequenceToTensor', item='input_2d'), dict( type='Collect', keys=[('input_2d', 'input'), 'target'], meta_name='metas', meta_keys=[ 'target_image_path', 'flip_pairs', 'root_position', 'root_position_index', 'target_mean', 'target_std' ]) ]

各步骤的源码级原理:

  1. GetRootCenteredPose(pose3d_transform.py):把 3D 目标姿态以root_index=14(root/pelvis)为原点做零中心化,root_position保存根关节的全局坐标,remove_root=True时删除根关节并把root_position_index=14存入 meta,供推理时恢复全局坐标;
  2. NormalizeJointCoordinate × 2(pose3d_transform.py):分别对 3D 目标与 2D 输入做(x - mean) / std标准化,mean/std 来自预处理脚本生成的统计量 pkl,并被硬编码在配置中(joint_3d_normalize_param形状为 [16,3],因为根关节已被移除;joint_2d_normalize_param形状为 [17,2])。变换还会把{item}_mean、{item}_std存入结果,供 head 在get_accuracy/decode阶段反归一化(见 temporal_regression_head.py);
  3. PoseSequenceToTensor(pose3d_transform.py):把[T, K, C]的 2D 序列重排为[K*C, T],匹配 TCN 的 1D 卷积输入格式;seq_len=1时即[34, 1];
  4. Collect:打包模型输入(input)、回归目标(target)与 meta 信息。

值得说明的是,GetRootCenteredPose会提示删除根关节后关节索引不再与flip_pairs、num_joints等注解信息对齐(pose3d_transform.py),因此head.num_joints=16与 17 关节的 dataset_info 存在刻意差异,这是设计使然而非配置错误。

五、训练配置细节

5.1 优化器与学习率

optimizer = dict(type='Adam', lr=1e-3) optimizer_config = dict(grad_clip=None) lr_config = dict( policy='step', by_epoch=False, step=100000, gamma=0.96, ) total_epochs = 200
  • 优化器为 Adam,初始学习率 1e-3,不做梯度裁剪;
  • 学习率调度为按 iteration 衰减的 step 策略:训练到第 100000 个 iteration 时学习率乘以 0.96;
  • 共训练 200 个 epoch。该部分与 Human3.6M 的 SimpleBaseline3D 配置(simplebaseline3d_h36m.py)完全一致。

5.2 评估配置

evaluation = dict( interval=10, metric=['mpjpe', 'p-mpjpe', '3dpck', '3dauc'], key_indicator='MPJPE')

每 10 个 epoch 在验证集上评估一次,同时计算 4 个指标,并以 MPJPE 作为选择最优 checkpoints 的关键指标。

5.3 数据加载

data = dict( samples_per_gpu=64, workers_per_gpu=2, val_dataloader=dict(samples_per_gpu=64), test_dataloader=dict(samples_per_gpu=64), train=dict( type='Body3DMpiInf3dhpDataset', ann_file=f'{data_root}/annotations/mpi_inf_3dhp_train.npz', img_prefix=f'{data_root}/images/', data_cfg=train_data_cfg, ...), val=dict( type='Body3DMpiInf3dhpDataset', ann_file=f'{data_root}/annotations/mpi_inf_3dhp_test_valid.npz', ...), test=dict(..., ann_file=f'{data_root}/annotations/mpi_inf_3dhp_test_valid.npz', ...))

train_data_cfg/test_data_cfg中与本实验直接相关的字段(定义见 Kpt3dSviewKpt2dDataset):

  • seq_len=1:每个样本只取 1 帧,对应核大小为 1 的 TCN;
  • seq_frame_interval=1:相邻帧间隔;
  • causal=True:causal 模式下目标帧为序列最右帧(此处即唯一帧);
  • joint_2d_src='gt':2D 输入使用 GT 标注(本实验的前提条件);
  • need_camera_param=False:本实验不需要相机参数;
  • camera_param_file:指向cameras_train.pkl/cameras_test.pkl,仅在need_camera_param=True时加载(见 body3d_mpi_inf_3dhp_dataset.py)。

六、训练、测试与推理实战

6.1 单卡训练

python tools/train.py configs/body/3d_kpt_sview_rgb_img/pose_lift/mpi_inf_3dhp/simplebaseline3d_mpi-inf-3dhp.py

常用可选参数(由 tools/train.py 定义):

  • --work-dir:指定日志与 checkpoint 保存目录;
  • --resume-from:从指定 checkpoint 恢复训练;
  • --no-validate:训练期间不进行验证;
  • --gpu-id/--gpus:指定 GPU。

6.2 多卡分布式训练

bash tools/dist_train.sh configs/body/3d_kpt_sview_rgb_img/pose_lift/mpi_inf_3dhp/simplebaseline3d_mpi-inf-3dhp.py 8

tools/dist_train.sh的第一个参数为配置文件路径,第二个参数为 GPU 数量。若使用 Slurm 集群,可改用tools/slurm_train.sh。

6.3 测试与评估

python tools/test.py configs/body/3d_kpt_sview_rgb_img/pose_lift/mpi_inf_3dhp/simplebaseline3d_mpi-inf-3dhp.py \ https://download.openmmlab.com/mmpose/body3d/simplebaseline3d/simplebaseline3d_mpi-inf-3dhp-b75546f6_20210603.pth

常用可选参数(由 tools/test.py 定义):

  • --eval {mpjpe, p-mpjpe, 3dpck, 3dauc}:指定要计算的指标,与配置中evaluation.metric对应;
  • --out:输出结果文件路径;
  • --fuse-conv-bn:融合 conv 与 bn 层以略微提升推理速度。

6.4 推理脚本

对于通用 3D 人体姿态两阶段推理,可参考 body3d_two_stage_img_demo.py(图片)与 body3d_two_stage_video_demo.py(视频):第一阶段用 2D 姿态估计模型(如 topdown_heatmap 系列的 HRNet)得到 2D 关键点,第二阶段用 PoseLifter 类模型把 2D 关键点提升为 3D 姿态。两阶段使用说明可查阅 3d_human_pose_demo.md。

七、评估指标源码级解析

MPI-INF-3DHP 数据集的评估在 body3d_mpi_inf_3dhp_dataset.py 中实现,支持的指标包括mpjpe、p-mpjpe、3dpck、p-3dpck、3dauc、p-3dauc(见ALLOWED_METRICS)。底层计算函数位于 pose3d_eval.py:

  • MPJPE(Mean Per Joint Position Error):所有关节预测与 GT 的欧氏距离均值,不做任何对齐(alignment='none'),实现见 pose3d_eval.py;
  • P-MPJPE:先通过相似变换(Procrustes alignment:尺度 + 旋转 + 平移)把预测对齐到 GT 后再计算 MPJPE,对齐由 mesh_eval.py 的compute_similarity_transform求解正交 Procrustes 问题完成;
  • 3DPCK(Percentage of Correct Keypoints):预测与 GT 的 L2 距离小于阈值(默认 0.15 米)的关节占比 ×100,见 pose3d_eval.py;
  • 3DAUC(Area Under the Curve):在一系列 3DPCK 阈值上计算得到的曲线下面积,实现派生自 MPI-INF-3DHP 官方测试数据发布中的mpii_compute_3d_pck.m(见 pose3d_eval.py)。

此外,TemporalRegressionHead.get_accuracy在训练/验证过程中也会计算 MPJPE 与 P-MPJPE:它会先根据 meta 中的target_mean/target_std反归一化预测与目标,再依据restore_global_position恢复全局坐标,最后用compute_similarity_transform计算两种误差(见 temporal_regression_head.py)。

八、常见问题与注意事项

  1. 数据目录结构:配置硬编码data_root = 'data/mpi_inf_3dhp',若目录结构不同需要同步修改配置中的data_root及相关文件路径。
  2. joint_2d_src的含义:本实验结果基于 GT 2D 检测('gt')。若要验证 2D 检测误差对 3D 提升结果的影响,可将joint_2d_src改为'detection'并指定joint_2d_det_file指向 2D 检测结果 npz(检测结果形状需与joints_3d对齐且最后一维为 3,见 body3d_mpi_inf_3dhp_dataset.py)。
  3. 17 vs 16 关节:root 关节在 pipeline 中被移除,因此 head 输出 16 个关节;推理时通过restore_global_position与root_position_index将根关节插回,最终输出仍为 17 关节的完整 3D 姿态。
  4. 单帧 vs 时序:本配置为seq_len=1、kernel_sizes=(1,1,1)的单帧模型;若需要利用时序信息,可参考同目录下 video_pose_lift 的 videopose3d_mpi-inf-3dhp 配置,其中 TCN 使用更大的核大小与更长的序列。
  5. checkpoint 下载:官方预训练权重与训练日志的下载地址见文档表格(simplebaseline3d_mpi-inf-3dhp.md)与 simplebaseline3d_mpi-inf-3dhp.yml;模型权重与日志由 OpenMMLab 官方托管,属于仓库文档中明确给出的资源。

通过上述配置、数据与源码层面的完整梳理,你可以在 ViTPose 仓库中直接复现 SimpleBaseline3D 在 MPI-INF-3DHP 上的 84.3 MPJPE / 85.0 3DPCK 基线结果,并进一步替换 2D 检测来源、扩展为时序模型或迁移到其他 3D 人体姿态数据集。

  • 人工智能
  • 计算机视觉
  • 深度学习

【免费下载链接】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"

项目地址:https://gitcode.com/gh_mirrors/vi/ViTPose
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:06:06

OpenCV幽灵版本4.9.0真相:本地编译避坑与版本校验实战

简介:本资源为OpenCV 4.9.0官方版本的完整构建包(含contrib扩展模块),面向计算机视觉初学者、算法工程师及深度学习开发者,提供开箱即用的C开发支持,适用于图像处理、目标检测、特征匹配、工业质检与AR应用…

作者头像 李华
网站建设 2026/10/15 18:05:28

用C语言读写STL文件:二进制与ASCII格式解析实战

看到标题里的“stl”,估计不少人的第一反应是:C标准模板库?怎么又和C语言文件读写凑一块了?这里先澄清一下,我们要聊的是另一种STL——STereoLithography,也就是3D打印和CAD领域最常见的三角网格文件格式。…

作者头像 李华
网站建设 2026/10/15 18:02:48

网络排障必备的8个命令,从原理到实战一次讲透

搞网络维护或者经常帮人处理电脑问题的人,应该都见过这种场景:打开命令行,敲字母,回车,屏幕滚出一堆数字和英文,懂的人三秒定位问题,不懂的人只能截图到处问。其实这些网络命令就是操作系统自带…

作者头像 李华
网站建设 2026/10/15 18:01:32

Python八股文PDF怎么背才有效?从对象模型到GIL的面试突围指南

简介:这是一份面向 Python 求职者与基础学习者的面试知识点速查 PDF,聚焦生成器、迭代器、列表与元组、字典实现、GIL 全局解释器锁、Py2/Py3 差异、可变与不可变对象、闭包与装饰器等高频问题,以问答形式给出精炼结论与代码示例,…

作者头像 李华