☰
ViTPose 仓库 3D 手部姿态估计演示指南:interhand3d_img_demo.py 单图推理与可视化实战
2026/10/15 16:24:17 网站建设 项目流程
  • 人工智能
  • 计算机视觉
  • 深度学习

【免费下载链接】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 仓库中的 3D 手部演示文档 为主体,围绕interhand3d_img_demo.py脚本,系统讲解如何基于 InterHand2.6M 数据集完成单张 RGB 图像的 3D 交互手部姿态推理与可视化。读完本文,你将掌握该演示脚本的全部命令行参数、两种典型运行模式(带/不带 Ground Truth 与相机参数)、底层推理调用链、相机空间坐标变换原理,以及模型配置与测试验证方法,可直接在本仓库环境中复现完整演示。

一、3D 手部姿态估计与 InterHand2.6M 数据集背景

3D 手部姿态估计(3D Hand Pose Estimation)的目标是从 RGB 图像中恢复手部关节的三维坐标,是手势交互、AR/VR、人机接口等应用的关键技术。其中最具挑战性的场景是双手交互(interacting hands):双手互相遮挡、形状高度相似,导致左右手区分与深度估计都更加困难。

仓库中的 3D 手部模型基于InterNet(ECCV'2020,论文题为 "InterHand2.6M: A Dataset and Baseline for 3D Interacting Hand Pose Estimation from a Single RGB Image")算法与InterHand2.6M数据集构建,相关引用与算法说明可参见 模型页面 和 internet_interhand3d.md。数据集的完整定义位于 interhand3d.py,其关键点体系为左右手各 21 个关节、共 42 个关键点:每只手包含拇指、食指、中指、无名指、小指 5 根手指(每根 4 个指节,编号 1~4 从掌根到指尖),外加 1 个手腕(wrist),索引 0~20 为右手,21~41 为左手,左右手对应关节互为 swap 关系(如right_thumb4↔left_thumb4)。

二、演示脚本与输入数据准备

2.1 脚本位置与作用

演示脚本位于 demo/interhand3d_img_demo.py。它的输入不是任意一张图片,而是给定的 COCO 格式 JSON 标注文件(其中包含手部 GT 边界框),逐帧读取图片、逐框调用模型进行 3D 关键点推理,并输出可视化结果。因此文档中将其归类为 "Using gt hand bounding boxes as input"——即使用 GT 手部边界框作为检测输入,适合在数据集上验证模型效果,而非端到端的目标检测演示。

2.2 测试数据文件

仓库的 tests/data/interhand2.6m/ 目录下提供了 4 张测试图像和 3 个配套 JSON 文件,开箱即可运行演示:

文件用途
test_interhand2.6m_data.jsonCOCO 格式图像与标注文件,记录每张图像的file_name、capture、camera、frame_idx以及手部bbox(格式为xywh)
test_interhand2.6m_camera.json相机参数文件,按capture→camera两级索引组织,包含campos(相机在世界空间中的位置)、camrot(世界到相机的旋转矩阵)、focal(焦距)、princpt(主点)
test_interhand2.6m_joint_3d.jsonGT 3D 关节文件,按capture→frame_idx索引,包含world_coord(世界坐标)与joint_valid(关节有效性标志)
image2017.jpg等 4 张图像RGB 输入图像

2.3 完整数据集组织方式

如需在完整数据集上运行,可参考 docs/en/tasks/3d_hand_keypoint.md 的准备说明:从 InterHand2.6M 官方渠道下载数据集与标注,解压后组织为如下目录结构,并软链接到仓库的data/目录下(若目录结构不同,需同步修改配置中的路径):

data └── interhand2.6m ├── annotations │ ├── all │ ├── human_annot │ ├── machine_annot │ ├── skeleton.txt │ └── subject.txt └── images ├── train ├── val └── test

三、命令行参数全解

interhand3d_img_demo.py的命令行参数在脚本的ArgumentParser中定义(见 demo/interhand3d_img_demo.py),完整说明如下:

参数类型默认值说明
pose_configstr必填姿态网络配置文件路径
pose_checkpointstr必填模型权重文件路径(可为本地图或下载 URL)
--json-filestr''包含图像信息与手部边界框的 COCO 格式 JSON 文件
--img-rootstr''图像根目录,脚本内部通过osp.join(img_root, image['file_name'])拼接出完整图像路径
--camera-param-filestrNone相机参数文件;提供时,预测的 3D 关键点将从像素空间转换到相机空间进行可视化;为None时在像素空间可视化
--gt-joints-filestrNoneGT 3D 关键点参数文件;提供后可与预测结果对照显示,并用于将预测的相对深度恢复为绝对深度
--rebase-keypoint-heightflagFalse将预测 3D 姿态的最低有效关键点高度归零(即"落地"效果),适用于模型不预测全局位置时的可视化
--show-ground-truthflagFalse若 GT 可用,同时显示 GT 关键点
--showflagFalse是否弹出窗口实时显示结果
--out-img-rootstrNone可视化图像输出目录;None时不保存图像
--devicestrcuda:0推理设备,可指定 GPU ID 或cpu
--kpt-thrfloat0.3关键点分数阈值,低于该分数的关键点不绘制
--radiusint4可视化关键点的圆点半径(像素)
--thicknessint1可视化关键点连接线的粗细(像素)

需要特别注意的是,脚本开头有一条硬性校验(第 103 行):assert args.show or (args.out_img_root != '')——即--show与--out-img-root必须至少提供其一,否则脚本直接报错退出。

四、使用 GT 手部边界框进行单图推理

4.1 完整命令模板

原文档给出的命令模板如下,其中方括号[...]内的参数为可选项:

python demo/interhand3d_img_demo.py \ ${MMPOSE_CONFIG_FILE} ${MMPOSE_CHECKPOINT_FILE} \ --json-file ${JSON_FILE} \ --img-root ${IMG_ROOT} \ [--camera-param-file ${CAMERA_PARAM_FILE}] \ [--gt-joints-file ${GT_JOINTS_FILE}]\ [--show] \ [--device ${GPU_ID or CPU}] \ [--out-img-root ${OUTPUT_DIR}] \ [--rebase-keypoint-height] \ [--show-ground-truth]

4.2 带 GT 关键点与相机参数的完整示例

使用仓库自带的测试数据,同时提供相机参数与 GT 3D 关键点,可以输出"预测 + 真值"对照、且坐标已转换到相机空间的完整可视化:

python demo/interhand3d_img_demo.py \ configs/hand/3d_kpt_sview_rgb_img/internet/interhand3d/res50_interhand3d_all_256x256.py \ https://download.openmmlab.com/mmpose/hand3d/internet/res50_intehand3d_all_256x256-b9c1cf4c_20210506.pth \ --json-file tests/data/interhand2.6m/test_interhand2.6m_data.json \ --img-root tests/data/interhand2.6m \ --camera-param-file tests/data/interhand2.6m/test_interhand2.6m_camera.json \ --gt-joints-file tests/data/interhand2.6m/test_interhand2.6m_joint_3d.json \ --out-img-root vis_results \ --rebase-keypoint-height \ --show-ground-truth

命令含义拆解:

  • pose_config与pose_checkpoint指定了 res50_interhand3d_all_256x256.py 配置及其配套权重;
  • --camera-param-file提供相机参数后,脚本会把 GT 关节从世界坐标变换到相机坐标,并把模型预测的相对深度(相对各自手腕的深度)借助 GT 手腕深度恢复为绝对深度,再转换到相机空间(详见第六节);
  • --show-ground-truth会在可视化结果中同时绘制 GT 关键点;
  • --rebase-keypoint-height将最低有效关键点的高度归零,使姿态"落地"在统一基准上,便于比较左右手与帧间姿态。

权重下载提示:上述命令中的 checkpoint 为演示文档中附带的官方权重。若希望使用模型页面列出的更新版本(v1.0,256×256 输入,含all训练集权重),可将 checkpoint 参数替换为模型页面 internet_interhand3d.md 中提供的res50_intehand3dv1.0_all_256x256-42b7f2ac_20210702.pth下载地址。

4.3 无 GT 与相机参数的最小示例

若只想快速查看预测效果、不关心相机空间坐标,可以省略--camera-param-file与--gt-joints-file。此时 GT 3D 关节不可用,--show-ground-truth不会生效(脚本会打印提示),预测关键点直接在像素空间可视化:

python demo/interhand3d_img_demo.py \ configs/hand/3d_kpt_sview_rgb_img/internet/interhand3d/res50_interhand3d_all_256x256.py \ https://download.openmmlab.com/mmpose/hand3d/internet/res50_intehand3d_all_256x256-b9c1cf4c_20210506.pth \ --json-file tests/data/interhand2.6m/test_interhand2.6m_data.json \ --img-root tests/data/interhand2.6m \ --out-img-root vis_results \ --rebase-keypoint-height

五、推理与可视化调用链源码解析

演示脚本的核心调用链为:init_pose_model→ 解析 COCO 标注 →inference_interhand_3d_model→ 后处理 →vis_3d_pose_result。

5.1 模型初始化:init_pose_model

mmpose/apis/inference.py 中的init_pose_model(config, checkpoint, device)负责读取配置文件(mmcv.Config.fromfile)、通过build_posenet构建模型、加载 checkpoint,并将配置保存在model.cfg中供推理阶段复用,最后将模型置于指定设备并切换为eval()模式。

5.2 标注解析与数据组装

脚本使用xtcocotools.coco.COCO加载--json-file(第 105 行),遍历每张图像及其标注,为每个手部实例组装det_result字典(第 153-158 行),包含:

  • image_name:由--img-root与标注中的file_name拼接;
  • bbox:标注中的手部边界框(xywh格式);
  • camera_param:按capture→camera两级索引从相机参数文件中取出,并经_transform_interhand_camera_param转换格式(见 5.4);
  • keypoints_3d_gt:按capture→frame_idx索引取出 GT 关节,将world_coord与joint_valid沿最后一维拼接成[42, 4]的数组。

5.3 核心推理:inference_interhand_3d_model

mmpose/apis/inference_3d.py 中的inference_interhand_3d_model(model, img_or_path, det_results, ...)完成单图多框推理,流程如下:

  1. 从det_results中收集所有边界框(支持xywh/xyxy两种格式,默认xywh),可选的bbox_thr按分数过滤;
  2. 从model.cfg读取test_pipeline并用Compose构建数据预处理管线;
  3. 为每个边界框调用_box2cs计算中心center与尺度scale,组装包含joints_3d占位、ann_info(图像尺寸、关节数、flip_pairs、深度边界等)的data字典,其中左右手flip_pairs定义为[[i, 21 + i] for i in range(21)];
  4. 数据经过 pipeline 后collate、scatter到推理设备,在torch.no_grad()下前向得到preds(3D 关键点)、rel_root_depth(相对根深度)与hand_type(左右手类型)三部分输出;
  5. 后处理:将rel_root_depth加到左手(索引 21 及之后)关节的深度通道上,并按hand_type对左右手关键点的置信度加权(第 603-608 行)。

5.4 相机参数格式转换

InterHand2.6M 的原始相机参数格式(camrot为世界到相机的旋转矩阵、campos为相机在世界空间的位置、focal、princpt)与SimpleCamera期望的格式(R为相机到世界的旋转、T为平移、f、c)并不一致,因此 demo/interhand3d_img_demo.py 中的_transform_interhand_camera_param做了如下转换:

camera_param['R'] = np.array(interhand_camera_param['camrot']).T camera_param['T'] = np.array(interhand_camera_param['campos'])[:, None] camera_param['f'] = np.array(interhand_camera_param['focal'])[:, None] camera_param['c'] = np.array(interhand_camera_param['princpt'])[:, None]

即对旋转矩阵转置、把 3×1 的位置向量重塑为列向量。转换后的参数交给 mmpose/core/camera/single_camera.py 中的SimpleCamera:world_to_camera(第 85 行)将世界坐标转到相机坐标,pixel_to_camera(第 117 行)利用焦距f与主点c将像素空间坐标(含深度)反投影到相机空间。

5.5 演示脚本的后处理与可视化

推理结果返回后,演示脚本在 第 170-235 行 做如下后处理:

  1. 分数归一化:若关键点分数的最大值大于 1(模型输出为 0~255 或 0~1 的差异),统一除以 255;
  2. 提取 2D 关键点:取 3D 关键点的前两维与分数维作为像素空间 2D 关键点;
  3. 坐标空间转换:当同时提供相机参数与 GT 3D 关节时,将 GT 从世界坐标转到相机坐标;用 GT 手腕(右手索引 20、左手索引 41)的深度把模型预测的相对深度补齐为绝对深度(keypoints_3d[:21, 2] += keypoints_3d_gt[20, 2],左手同理用索引 41);最后将像素空间关键点反投影到相机空间;
  4. 坐标轴旋转:用旋转矩阵vis_R = [[1, 0, 0], [0, 0, -1], [0, 1, 0]]将关键点坐标旋转,使 z 轴对应"高度"方向,以便直观比较姿态的高低;
  5. 高度归零:若指定--rebase-keypoint-height,将有效关键点(分数大于 0)的最小高度减到 0;
  6. 可视化:调用 vis_3d_pose_result 绘制骨架,结果经model.show_result输出;若指定--out-img-root,以vis_{i}.jpg命名保存到该目录(第 238-242 行)。vis_3d_pose_result内置了InterHand3DDataset的骨架连接关系(第 408-447 行),左右手各 20 条骨骼连线,并配有区分手指的颜色。

六、模型与配置深度解读

6.1 配置结构

演示所用的 res50_interhand3d_all_256x256.py 以default_runtime.py与 interhand3d.py 为基座,核心设置如下:

配置项值说明
输入尺寸256×256data_cfg.image_size
3D 热图尺寸64×64×64data_cfg.heatmap_size
深度边界heatmap3d_depth_bound=400.0、root_depth_bound=400.0关键点 3D 热图与根深度 1D 热图的深度量化边界(单位 mm)
输出通道42左右手各 21 个关节
骨干网络ResNet,depth=50预训练权重torchvision://resnet50
优化器Adam,lr=2e-4total_epochs=20,学习率在 epoch 15、17 阶梯下降
评价指标MRRPE、MPJPE、Handedness_acc相对根深度误差、关节误差、左右手判别准确率,save_best='MPJPE_all'

6.2 三分支头部:Interhand3DHead

模型头部 interhand_3d_head.py 的Interhand3DHead由三个子分支组成(前向见 第 383-392 行):

  • 关键点头(keypoint_head_cfg):输出21×64通道的 3D 热图(depth_size=64,配合 3 层反卷积 256 通道),对左右手各 21 个关节的深度维进行 64 层量化,解码时将热图索引映射回毫米级深度(见 decode 实现);
  • 根深度头(root_head_cfg):输出 64 格的 1D 热图,预测左右手腕的相对深度,解码后得到rel_root_depth(第 514-517 行);
  • 手型分类头(hand_type_head_cfg):输出 2 分类(左右手),解码为hand_type(第 519-520 行),用于区分左右手并对置信度加权。

三个分支的监督损失分别为JointsMSELoss(3D 热图)、L1Loss(相对根深度)、BCELoss(手型分类),与推理时preds / rel_root_depth / hand_type三路输出一一对应。数据侧,训练与测试数据由 mmpose/datasets/datasets/hand/interhand3d_dataset.py 的InterHand3DDataset提供,支持use_gt_root_depth(使用 GT 手腕深度或来自rootnet_result_file的深度)等选项。

6.3 参考精度

根据模型页面 internet_interhand3d.md 的记录,InterNet_resnet_50(256×256)在 InterHand2.6M 上的官方结果为:test(H+M) 集 MPJPE-all 11.59mm、MRRPE 29.28mm、APh 0.99;val(M) 集 MPJPE-all 13.16mm、MRRPE 31.73mm、APh 0.98。这些数字可作为运行演示后主观观察的量化参考。

七、测试验证

仓库在 tests/test_apis/test_inference_3d.py 中提供了test_interhand3d_demo测试用例,完整覆盖了本演示的核心路径:

  • 在 CPU 上构建 res50_interhand3d_all_256x256.py 模型(不加载权重);
  • 用tests/data/interhand2.6m/image2017.jpg与一个人为指定的bbox=[50, 50, 50, 50]构造det_result,调用inference_interhand_3d_model推理并调用vis_3d_pose_result可视化;
  • 验证空det_results的边界情况(返回空列表);
  • 若 CUDA 可用,额外验证 GPU 推理路径;
  • 验证传入未知数据集名会抛出NotImplementedError。

该测试证明:即使不加载任何训练权重,模型结构、数据管线与推理接口也能完整走通——因此演示脚本可以放心地在 CPU 上进行流程调试。

八、常见问题与注意事项

  1. 必须提供--show或--out-img-root之一,否则脚本因assert直接退出;
  2. --camera-param-file与--gt-joints-file需成对提供才有最佳效果:只有两者同时给出,预测才能转换到相机空间并叠加 GT 对照;只给其一或都不给时,关键点将在像素空间可视化,--show-ground-truth会打印提示而不生效;
  3. 设备选择:默认cuda:0,无 GPU 时将--device指定为cpu;测试用例证实该链路在 CPU 上可完整运行;
  4. 数据格式:--json-file必须是 COCO 标注格式(含images与annotations字段),边界框为xywh;相机与关节文件的索引层级(capture/frame_idx)必须与标注中的capture、frame_idx字段一致;
  5. 深度边界语义:heatmap3d_depth_bound与root_depth_bound定义了 3D 热图的深度量化范围,更换数据集或相机时需检查是否匹配;
  6. 完整数据集路径:使用完整 InterHand2.6M 时,按 docs/en/tasks/3d_hand_keypoint.md 组织data/interhand2.6m目录,并保持配置中ann_file、camera_file、joint_file、img_prefix与之一致。

通过本文,你可以从一张带 GT 边界框标注的手部图像出发,完整复现 3D 手部姿态的推理、坐标变换与可视化流程,并理解从inference_interhand_3d_model到Interhand3DHead三分支解码、再到SimpleCamera相机投影的完整技术链路。

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

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询