MMPose 2D手部关键点推理实战:从MMDetection手部检测到Top-Down姿态估计的Demo全解

原创2026-09-16 14:35:201,695 阅读
文章标签:计算机视觉人工智能深度学习

MMPose 2D手部关键点推理实战:从MMDetection手部检测到Top-Down姿态估计的Demo全解

本指南面向需要在真实图像或视频上完成 2D 手部关键点(Hand Keypoint)检测的开发者,完整讲解 MMPose 仓库中手部姿态推理的三种主流方式:基于 MMDetection 检测器的 Top-Down 流程(topdown_demo_with_mmdet.py)、统一推理接口(inferencer_demo.py)以及推理加速技巧。读完本文,你将能够基于仓库自带的手部检测器与预训练模型,一行命令跑通"先检测手部框、再估计 21 个关键点"的完整推理链路,并理解其底层参数与源码实现。

前置条件与核心思路

2D 手部关键点检测采用经典的 Top-Down(自上而下)两阶段流程:

  1. 手部框检测:先用目标检测器(如 MMDetection 中的 RTMDet)从图像中定位每一只手的位置;
  2. 关键点估计:将裁剪出的手部区域送入 MMPose 的 Top-Down 姿态估计模型(如 RTMPose、HRNet),输出腕部(wrist)与五根手指共 21 个关键点坐标。

运行本指南中的 Demo 前,需要满足以下条件:

  • 已安装 MMPose 及其依赖;
  • 已安装 MMDetection)。

手部框检测模型准备

Top-Down 流程首先需要一只手部检测器。MMPose 仓库为手部场景准备了专用检测模型,其配置与权重索引在 手部检测模型文档 中列出:

网络结构 数据集 Box AP 配置文件
Cascade R-CNN X-101-64x4d-FPN-1class OneHand10K test 0.817 demo/mmdetection_cfg/cascade_rcnn_x101_64x4d_fpn_1class.py
RTMDet-nano OneHand10K test 0.760 demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py

这两个检测器都在 OneHand10K 数据集上训练,其中 RTMDet-nano 在精度与速度之间取得了较好平衡,是官方 Demo 默认采用的手部检测器。其配置文件 demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py 值得关注:

  • 输入尺寸固定为 320×320(input_shape = 320);
  • 采用 RTMDet 的 nano 轻量化配置(deepen_factor=0.33、widen_factor=0.25、use_depthwise=True);
  • 检测头将类别数改为 num_classes=1,即只预测"手"这一类;
  • 训练数据由 OneHand10K、FreiHand、RHD、HalpeHand 等多个手部数据集拼接而成(ConcatDataset),测试则使用 OneHand10K 的 test 划分。

2D手部图像Demo:MMDetection检测 + MMPose姿态估计

基础命令

官方提供的核心脚本是 topdown_demo_with_mmdet.py,其完整用法如下:

python demo/topdown_demo_with_mmdet.py \
    ${MMDET_CONFIG_FILE} ${MMDET_CHECKPOINT_FILE} \
    ${MMPOSE_CONFIG_FILE} ${MMPOSE_CHECKPOINT_FILE} \
    --input ${INPUT_PATH} [--output-root ${OUTPUT_DIR}] \
    [--show] [--device ${GPU_ID or CPU}] [--save-predictions] \
    [--draw-heatmap ${DRAW_HEATMAP}] [--radius ${KPT_RADIUS}] \
    [--kpt-thr ${KPT_SCORE_THR}] [--bbox-thr ${BBOX_SCORE_THR}]

以 RTMPose-m 手部模型(在 5 个公开手部数据集上训练,即 Hand5 模型)为例,官方给出可直接运行的完整命令:

python demo/topdown_demo_with_mmdet.py \
    demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmdet_nano_8xb32-300e_hand-267f9c8f.pth \
    configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmpose-m_simcc-hand5_pt-aic-coco_210e-256x256-74fb594_20230320.pth \
    --input tests/data/onehand10k/9.jpg \
    --show --draw-heatmap

该命令的四组必选参数含义如下:

参数 本例取值 说明
MMDET_CONFIG_FILE demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py 手部检测器配置
MMDET_CHECKPOINT_FILE RTMDet-nano 手部检测权重 检测器权重(URL 或本地路径)
MMPOSE_CONFIG_FILE configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py 手部姿态估计模型配置
MMPOSE_CHECKPOINT_FILE RTMPose-m Hand5 权重 姿态模型权重(URL 或本地路径)

若使用的姿态模型为热力图类(Heatmap-based),加上 --draw-heatmap 参数后,预测热力图会与关键点一起被可视化叠加在图像上。

将可视化结果保存到磁盘

不带任何输出参数时结果只会在弹窗中显示。指定 --output-root 即可将可视化图片/视频写入指定目录,同时保留 --show 弹窗:

python demo/topdown_demo_with_mmdet.py \
    demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmdet_nano_8xb32-300e_hand-267f9c8f.pth \
    configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmpose-m_simcc-hand5_pt-aic-coco_210e-256x256-74fb594_20230320.pth \
    --input tests/data/onehand10k/9.jpg \
    --output-root vis_results --show --draw-heatmap

如果需要把预测的关键点坐标结果(而非可视化图像)保存为 JSON 文件,请追加 --save-predictions。从源码看,该参数要求同时指定 --output-root,预测结果会写入 {output_root}/results_{输入文件名}.json,其中包含检测器输出与姿态估计结果(见 demo/topdown_demo_with_mmdet.py 与 demo/topdown_demo_with_mmdet.py)。

在CPU上运行

没有 GPU 时,只需将 --device 指定为 cpu:

python demo/topdown_demo_with_mmdet.py \
    demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmdet_nano_8xb32-300e_hand-267f9c8f.pth \
    configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmpose-m_simcc-hand5_pt-aic-coco_210e-256x256-74fb594_20230320.pth \
    --input tests/data/onehand10k/9.jpg \
    --show --draw-heatmap --device cpu

2D手部视频Demo

视频与图像共享完全相同的接口与脚本。唯一的区别是 --input 既可以是本地视频文件路径,也可以是指向视频文件的 URL 链接(脚本会按输入类型自动分流处理,见 demo/topdown_demo_with_mmdet.py)。处理视频时还会自动写回一个 25 FPS 的 mp4 输出文件(demo/topdown_demo_with_mmdet.py)。

python demo/topdown_demo_with_mmdet.py \
    demo/mmdetection_cfg/rtmdet_nano_320-8xb32_hand.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmdet_nano_8xb32-300e_hand-267f9c8f.pth \
    configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py \
    https://download.openmmlab.com/mmpose/v1/projects/rtmposev1/rtmpose-m_simcc-hand5_pt-aic-coco_210e-256x256-74fb594_20230320.pth \
    --input data/tests_data_nvgesture_sk_color.avi \
    --output-root vis_results --kpt-thr 0.1

视频示例中把 --kpt-thr 调低到 0.1,以便在低置信度场景下保留更多关键点用于可视化(默认值为 0.3)。播放窗口按 ESC 键即可提前退出(demo/topdown_demo_with_mmdet.py)。

2D手部Demo的Inferencer统一推理接口

除了拼接检测器+姿态模型的传统方式,MMPose 还提供更简洁的 Inferencer(统一推理接口),通过模型别名(Model Alias)代替繁琐的配置文件和权重路径,并支持图像路径、视频路径、图像文件夹、摄像头等多种输入。其入口为 demo/inferencer_demo.py,底层由 MMPoseInferencer 实现。

python demo/inferencer_demo.py tests/data/onehand10k \
    --pose2d hand --vis-out-dir vis_results/onehand10k \
    --bbox-thr 0.5 --kpt-thr 0.05

该命令会:

  • 对 tests/data/onehand10k 目录下的全部图片逐张推理(--pose2d hand 自动选用手部姿态模型别名);
  • 将可视化结果保存到 vis_results/onehand10k 目录(--vis-out-dir);
  • 用 --bbox-thr 0.5 过滤掉置信度低于 0.5 的检测框,用 --kpt-thr 0.05 过滤低分关键点。

Inferencer 的常用参数(见 demo/inferencer_demo.py):

参数 作用
--pose2d 2D 姿态模型:支持模型别名或配置文件路径
--pose2d-weights 自定义姿态模型权重路径,缺省时从 metafile 自动加载
--det-model / --det-weights 自定义检测模型(配置路径/别名 + 权重)
--device 推理设备,缺省时自动选择可用设备
--bbox-thr / --nms-thr / --kpt-thr 检测框分数阈值、NMS IoU 阈值、关键点分数阈值
--draw-heatmap 是否绘制热力图
--show-alias 打印当前 scope 下所有可用的模型别名列表

此外,Inferencer 也支持将预测结果(prediction)保存到磁盘(对应 --pred-out-dir 参数),便于下游做数据分析或二次开发。--show-alias 可以快速列出可用别名,例如执行 python demo/inferencer_demo.py --show-alias 即可查看包括 hand 在内的全部模型别名与其对应模型名(demo/inferencer_demo.py)。

关键参数与底层调用链详解

topdown_demo_with_mmdet.py 的完整参数集(默认值与含义,来自 demo/topdown_demo_with_mmdet.py):

参数 默认值 说明
--input '' 输入图像/视频路径,也可为 URL
--show False 是否弹出窗口实时显示
--output-root '' 输出文件根目录,缺省不保存可视化结果
--save-predictions False 是否将预测结果保存为 JSON
--device cuda:0 推理设备(GPU ID 或 cpu)
--det-cat-id 0 检测模型的目标类别 ID(手部检测器为 0)
--bbox-thr 0.3 检测框分数阈值
--nms-thr 0.3 检测框 NMS 的 IoU 阈值
--kpt-thr 0.3 关键点可视化分数阈值
--draw-heatmap False 绘制模型预测的热力图
--show-kpt-idx False 是否显示关键点索引编号
--skeleton-style mmpose 骨架绘制风格:mmpose 或 openpose
--radius 3 关键点绘制半径
--thickness 1 骨架连线粗细
--show-interval 0 视频逐帧显示的间隔秒数
--alpha 0.8 检测框透明度
--draw-bbox False 是否绘制实例检测框

从源码调用链看,单帧推理的核心流程集中在 process_one_image(demo/topdown_demo_with_mmdet.py):

  1. inference_detector(detector, img) 用 MMDetection 检测手部框;
  2. 按 det_cat_id 与 bbox_thr 过滤检测结果,再用 nms 抑制重叠框;
  3. inference_topdown(pose_estimator, img, bboxes) 对每个框执行 Top-Down 关键点估计;
  4. merge_data_samples 合并多实例结果,交由 Visualizer 渲染;
  5. 若 --draw-heatmap 为真,会在初始化姿态模型时注入 test_cfg.output_heatmaps=True(demo/topdown_demo_with_mmdet.py),从而让模型在推理时额外输出热力图。

推理加速:关闭测试时翻转

对于手部关键点模型,最直接的加速手段是修改配置文件中的 flip_test 开关。以 OneHand10K 上的 HRNet 模型为例:

将 model.test_cfg.flip_test 改为 False,可跳过翻转推理分支,显著减少推理耗时(约接近减半的前向计算量),代价是精度略有下降,适合对速度敏感、或翻转对称性不敏感的手部场景。

这一机制的底层实现可在模型头部源码中确认:RTMCCHead、SimCCHead、RTMWHead 等头部在 predict 时都会读取 test_cfg.get('flip_test', False),一旦开启,则从数据样本的 metainfo 中取出 flip_indices(关键点镜像索引),对翻转分支的输出进行还原与融合。例如 mmpose/models/heads/coord_cls_heads/rtmcc_head.py 中展示了 SimCC 坐标分类头的翻转融合实现,热力图头则在 mmpose/models/heads/heatmap_heads/ae_head.py 中按 flip_mode='heatmap' 处理。

若希望进一步提速,还可以换用更轻量的手部检测器(例如将 RTMDet-nano 替换为其他轻量检测模型),检测阶段本身也是 Top-Down 流程的主要开销之一。

模型与数据集配置深度解析

RTMPose-m Hand5:多数据集训练的实时手部模型

官方 Demo 使用的姿态模型 configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py 具备以下特征:

  • Codec:采用 SimCCLabel(SimCC 坐标分类),输入 256×256,simcc_split_ratio=2.0,即把坐标预测转化为一维坐标分类问题;
  • Backbone:复用 MMDetection 的 CSPNeXt(_scope_='mmdet'),arch 为 P5,宽深因子对应 RTMPose-m;
  • Head:RTMCCHead,输出通道 out_channels=21(21 个手部关键点),配合 KLDiscretLoss 与 GAU(门控注意力单元);
  • 数据集:名为 "Hand5",即在 COCO-Wholebody-Hand、OneHand10K、FreiHand2d、RHD2d、Halpe 五个公开数据集上联合训练(CombinedDataset),因此泛化能力更强;
  • 评估指标:PCKAccuracy(thr=0.2)、AUC、EPE 三个手部关键点标准指标(configs/hand_2d_keypoint/rtmpose/hand5/rtmpose-m_8xb256-210e_hand5-256x256.py)。

该模型的详细指标(包括在 COCO-Wholebody-Hand 与 Hand5 上的 PCK@0.2、AUC、EPE 以及 FLOPS)可查阅 configs/hand_2d_keypoint/rtmpose/hand5/rtmpose_hand5.md。

HRNet OneHand10K:经典热力图方案

若需要对比热力图方案,可参考 OneHand10K 上的 HRNetv2-w18 配置 configs/hand_2d_keypoint/topdown_heatmap/onehand10k/td-hm_hrnetv2-w18_8xb64-210e_onehand10k-256x256.py:

  • Codec 为 MSRAHeatmap,输入 256×256,输出 64×64 热力图,sigma=2;
  • Backbone 为 HRNet(HRNetv2-w18),Head 为 HeatmapHead(out_channels=21),Loss 为 KeypointMSELoss;
  • 训练 210 个 epoch,optimizer 为 Adam(lr=5e-4),评价指标同样为 PCK/AUC/EPE。

21个手部关键点的定义

手部关键点采用业界通用的 21 点定义:1 个腕部(wrist)+ 每根手指 4 个关节点(共 20 个),顺序为拇指(thumb)、食指(forefinger)、中指(middle_finger)、无名指(ring_finger)、小指(pinky_finger)。每个关键点的名称、序号、颜色与骨架连接关系(含各手指的颜色区分)定义在 configs/base/datasets/coco_wholebody_hand.py 中,可视化时会依据该文件中的 keypoint_info、skeleton_info 与 keypoint_colors 进行绘制。

总结与下一步

本文围绕 MMPose 的 2D 手部关键点推理,给出了三种可立即落地的方案:传统 MMDetection+MMPose 两阶段 Demo(图像/视频/CPU/结果保存全覆盖)、Inferencer 统一推理接口(模型别名+目录/摄像头输入),以及通过关闭 flip_test 实现的推理加速。同时从源码与配置层面解释了检测-估计的完整调用链、关键参数默认值以及 21 点手部骨架的数据定义。

如果希望深入底层,建议继续阅读仓库内的以下资源:

以此为起点,你可以进一步将该推理链路集成到手势识别、人机交互、AR/VR 手部追踪等实际业务中。

登录后查看全文
mmpose