MMPose 实操指南:基于 SimCC 与 MobileNetV2 的轻量级人体姿态估计(COCO 256×192)
2026/9/16 20:39:47 网站建设 项目流程

MMPose 实操指南:基于 SimCC 与 MobileNetV2 的轻量级人体姿态估计(COCO 256×192)

【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose

本文围绕 OpenMMLab 姿态估计工具箱 MMPose 中SimCC + MobileNetV2这一轻量级 top-down 人体关键点方案展开:从 SimCC 将关键点估计重构为"一维坐标分类"的核心思想出发,完整解析其在 COCO 上的模型配置、COCO val2017 基准结果,并结合仓库源码逐层剖析 SimCCLabel 编解码器、SimCCHead 网络头与 KLDiscretLoss 的实现细节。读完本文,你将掌握该配置的每一行参数含义、背后的训练与推理流程,以及如何基于它训练、测试和部署自己的轻量级人体姿态估计模型。

一、模型卡片核心信息:SimCC + MobileNetV2 on COCO

仓库中的模型卡片 mobilenetv2_coco.md 对应配置 simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.py,它组合了三项核心技术:

  • SimCC(ECCV'2022):由 Li Yanjie 等人提出的"简单坐标分类"(Simple Coordinate Classification)视角,将姿态估计中连续坐标的回归/热图预测问题,转化为 X、Y 两个方向的一维标签分类问题,论文编号 arXiv:2107.03332。
  • MobileNetV2(CVPR'2018):Mark Sandler 等人提出的基于"倒残差结构 + 线性瓶颈"(Inverted Residuals and Linear Bottlenecks)的轻量级骨干网络,适合移动端与低算力场景。
  • COCO(ECCV'2014):Microsoft COCO 通用物体上下文数据集,本文使用其人体关键点子任务(17 个关键点)。

配置名中的wo-deconv表明这是一个不含反卷积上采样头的轻量变体:SimCC 头直接作用于骨干输出的低分辨率特征图,通过全连接层生成一维分布,从而进一步压缩计算量,是理解 SimCC"省去热图高分辨率上采样"优势的典型示例。

二、COCO val2017 基准结果

模型卡片给出在 COCO val2017 上、使用在 COCO val2017 上人体 AP 为 56.4 的检测器提供人体框(top-down 流程)时,该模型的完整评测结果:

ArchInput SizeAPAP50AP75ARAR50
simcc_mobilenetv2_wo_deconv256×1920.6200.8550.6970.6780.902

以 256×192 输入、8×GPU 每卡 batch 64、训练 210 epoch 的设定,模型在 COCO val2017 上取得AP 0.620 / AP500.855 / AP750.697。权重与训练日志的记录位于模型索引文件 mobilenetv2_coco.yml 中(Weights字段登记了simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192-4b0703bb_20221010.pth及对应指标),可通过该索引按模型名检索获取。

需要说明的是,这里 AP 值是在检测器提供的人体框之上的 top-down 姿态估计结果,评测依赖COCO_val2017_detections_AP_H_56_person.json这一预检测框文件,后文数据加载器部分会详细解释。

三、训练配置逐段解析

完整配置见 simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.py,下面按逻辑模块拆解。

3.1 基础与运行时

_base_ = ['../../../_base_/default_runtime.py'] # runtime train_cfg = dict(max_epochs=210, val_interval=10)
  • 继承 configs/base/default_runtime.py 的通用运行时(日志、钩子、环境等)设置;
  • 训练 210 个 epoch,每 10 个 epoch 在验证集上评测一次。

3.2 优化器与学习率策略

# optimizer optim_wrapper = dict(optimizer=dict( type='Adam', lr=5e-4, )) # learning policy param_scheduler = [ dict( type='LinearLR', begin=0, end=500, start_factor=0.001, by_epoch=False), # warm-up dict( type='MultiStepLR', begin=0, end=train_cfg['max_epochs'], milestones=[170, 200], gamma=0.1, by_epoch=True) ] # automatically scaling LR based on the actual training batch size auto_scale_lr = dict(base_batch_size=512)
  • 使用Adam 优化器,初始学习率 5e-4(ResNet50 版本为 1e-3,见 simcc_res50_8xb64-210e_coco-256x192.py);
  • 前 500 次迭代执行warm-up(LinearLR,by_epoch=False,起始因子 0.001);
  • 之后采用MultiStepLR,在 epoch 170 与 200 处将学习率乘以 0.1(gamma=0.1);
  • auto_scale_lrbase_batch_size=512为基准自动按实际总 batch size 缩放学习率,因此当你改变 batch size 时无需手动重新调 LR。

3.3 Codec 设置:SimCC 标签的定义

# codec settings codec = dict( type='SimCCLabel', input_size=(192, 256), sigma=6.0, simcc_split_ratio=2.0)

这是整个方案的灵魂:SimCCLabel编解码器(源码见 mmpose/codecs/simcc_label.py)负责把关键点坐标编码成一维标签、把网络输出解码回坐标。各参数含义如下:

  • input_size=(192, 256):输入图像宽 192、高 256(w, h 顺序);
  • sigma=6.0:高斯平滑标签的 σ 值,决定一维分布"鼓包"的宽度(对应 3σ 规则下的标签半径);
  • simcc_split_ratio=2.0标签长度 = 输入尺寸 × split ratio。即 X 方向标签长度为192 × 2 = 384,Y 方向为256 × 2 = 512,相当于把每个像素"细分"为 2 个坐标分类单元,这是 SimCC 能够取得亚像素精度的关键设计。

3.4 模型结构:TopdownPoseEstimator

model = dict( type='TopdownPoseEstimator', data_preprocessor=dict( type='PoseDataPreprocessor', mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], bgr_to_rgb=True), backbone=dict( type='MobileNetV2', widen_factor=1., out_indices=(7, ), init_cfg=dict( type='Pretrained', checkpoint='mmcls://mobilenet_v2', )), head=dict( type='SimCCHead', in_channels=1280, out_channels=17, input_size=codec['input_size'], in_featuremap_size=tuple([s // 32 for s in codec['input_size']]), simcc_split_ratio=codec['simcc_split_ratio'], deconv_out_channels=None, loss=dict(type='KLDiscretLoss', use_target_weight=True), decoder=codec), test_cfg=dict(flip_test=True, ))
  • data_preprocessorPoseDataPreprocessor使用 ImageNet 统计的均值/标准差做归一化,bgr_to_rgb=True处理输入通道顺序;
  • backboneMobileNetV2widen_factor=1.0(标准宽度),out_indices=(7,)取第 7 个 stage 的输出作为最终特征图。注意这里未指定 ResNet 式的depth,MobileNetV2 的输出通道数为 1280,与head.in_channels=1280严格对应;init_cfg用 mmcls 的预训练权重初始化;
  • headSimCCHeadin_featuremap_size=tuple([s // 32 for s in input_size])表示骨干输出特征图为输入的 1/32(192×256 → 6×8),deconv_out_channels=None即关闭反卷积(wo-deconv),直接在该低分辨率特征图上接全连接生成一维分布;decoder=codec复用同一 SimCCLabel 配置完成解码;
  • lossKLDiscretLossuse_target_weight=True表示按关键点可见性加权;
  • test_cfgflip_test=True开启水平翻转测试(TTA),推理时对原图与翻转图各预测一次再取平均。

四、源码级原理:SimCCLabel 编解码器

理解 simcc_label.py 是掌握整个方案的关键,它实现了SimCCLabel类,注册在KEYPOINT_CODECS中。

4.1 编码(encode)

encode()接收原始关键点坐标(N, K, D)与可见性(N, K),输出:

  • keypoint_x_labels(形状 (N, K, Wx),Wx = w * simcc_split_ratio);
  • keypoint_y_labels(形状 (N, K, Wy),Wy = h * simcc_split_ratio);
  • keypoint_weights(形状 (N, K),对应关键点权重)。

支持两种标签平滑策略(smoothing_type):

  • gaussian(默认):调用_generate_gaussian(),对每个可见关键点,在 X/Y 轴上分别以关键点位置mu为中心、按exp(-(x-mu)^2 / (2σ²))生成高斯分布,并遵循3σ 规则限定标签半径;sigma超出边界的关键点权重被置 0。当normalize=True(默认)时,标签除以σ·√(2π)做归一化。每个关键点最终由两条一维高斯分布表示;
  • standard:调用_generate_standard(),使用标准标签平滑,label_smooth_weight=0时即退化为 one-hot 向量;该模式下sigma不参与编码。

坐标映射发生在_map_coordinates():关键点坐标乘以simcc_split_ratio并取整,得到 SimCC 空间中的整数索引。

4.2 解码(decode)

decode()接收网络的 X/Y 一维分布,调用 post_processing.py 中的get_simcc_maximum()求取最大响应位置与置信度,再除以simcc_split_ratio还原到输入图像坐标系。可选开关包括:

  • use_dark=True:启用 DARK 亚像素细化(refine_simcc_dark),根据 σ 自动计算高斯模糊核大小并对峰值位置做泰勒展开修正,可进一步提升精度;
  • decode_visibility=True:通过decode_beta(默认 150.0)对分布做带温度 softmax 得到可见性分数,此时返回(scores, visibility)元组。

4.3 测试用例佐证

仓库在 tests/test_codecs/test_simcc_label.py 中对该编解码器进行了完整覆盖,验证了 gaussian/standard 两种平滑方式的编码形状、权重处理以及解码坐标还原的数值正确性,可作为阅读与二次开发的参照。

五、SimCCHead 网络头:两条一维分类分支

SimCCHead(见 mmpose/models/heads/coord_cls_heads/simcc_head.py)负责把骨干特征图转化为 X/Y 两个一维分布:

# Define SimCC layers flatten_dims = self.heatmap_size[0] * self.heatmap_size[1] W = int(self.input_size[0] * self.simcc_split_ratio) H = int(self.input_size[1] * self.simcc_split_ratio) self.mlp_head_x = nn.Linear(flatten_dims, W) self.mlp_head_y = nn.Linear(flatten_dims, H)

其核心结构是两个共享输入特征的全连接分支:把特征图展平为flatten_dims维向量后,mlp_head_x输出长度W = input_w × simcc_split_ratio的 X 方向分布,mlp_head_y输出长度H = input_h × simcc_split_ratio的 Y 方向分布。前向时:

x = torch.flatten(feats, 2) pred_x = self.mlp_head_x(x) pred_y = self.mlp_head_y(x)

这正体现了 SimCC 与热图法的核心差异:无需将特征图上采样回输入分辨率生成二维热图,而是直接在低分辨率特征图上做一维分类,显著减少计算量与参数。

SimCCHead 还保留了对反卷积头的兼容能力:当deconv_out_channels非空时,可通过deconv_type='heatmap'(复用 HeatmapHead)或'vipnas'(复用 ViPNASHead)先做上采样再接 MLP。例如同目录下的 simcc_vipnas-mbv3_8xb64-210e_coco-256x192.py 就配置了deconv_type='vipnas'deconv_out_channels=(160, 160, 160)。而本文主角deconv_out_channels=None走的是零反卷积分支:只保留一个 1×1 conv(final_layer)将 1280 通道压缩到 17,再展平接两个全连接层,是真正的轻量化形态。

六、损失函数:KLDiscretLoss

训练采用KLDiscretLoss(离散 KL 散度损失,实现在 mmpose/models/losses/classification_loss.py):

  • 对预测分布pred * beta施加LogSoftmax,与标签分布计算逐位置KLDivLoss,再按关键点权重加权求和并除以关键点数 K;
  • 可选label_softmax=True对标签也做label_beta温度 softmax;
  • 支持maskmask_weight对指定关键点做额外加权;
  • 由于 X/Y 两个分支共享同一损失函数,forward()内会遍历(pred_x, pred_y)(gt_x, gt_y)两组分布叠加损失。

同时,SimCCHead.loss()在返回loss_kpt之外,还会基于simcc_pck_accuracy计算训练中的 PCK 精度acc_pose,便于在日志中实时观察关键点定位质量。

七、数据管线与评测流程

7.1 数据与管线

dataset_type = 'CocoDataset' data_mode = 'topdown' data_root = 'data/coco/' train_pipeline = [ dict(type='LoadImage'), dict(type='GetBBoxCenterScale'), dict(type='RandomFlip', direction='horizontal'), dict(type='RandomHalfBody'), dict(type='RandomBBoxTransform'), dict(type='TopdownAffine', input_size=codec['input_size']), dict(type='GenerateTarget', encoder=codec), dict(type='PackPoseInputs') ] val_pipeline = [ dict(type='LoadImage'), dict(type='GetBBoxCenterScale'), dict(type='TopdownAffine', input_size=codec['input_size']), dict(type='PackPoseInputs') ]

训练阶段依次执行:加载图像 → 由检测框得到中心与尺度 → 随机水平翻转 → 随机半身增强(RandomHalfBody)→ 随机框变换 → 仿射裁剪到 192×256 → 用SimCCLabel编码目标标签 → 打包数据。验证阶段不引入随机增强,仅做仿射对齐。

7.2 数据加载器与评测

train_dataloader = dict( batch_size=64, num_workers=2, persistent_workers=True, sampler=dict(type='DefaultSampler', shuffle=True), dataset=dict( type=dataset_type, data_root=data_root, data_mode=data_mode, ann_file='annotations/person_keypoints_train2017.json', data_prefix=dict(img='train2017/'), pipeline=train_pipeline, )) val_dataloader = dict( batch_size=32, ... dataset=dict( ... ann_file='annotations/person_keypoints_val2017.json', bbox_file=f'{data_root}person_detection_results/' 'COCO_val2017_detections_AP_H_56_person.json', data_prefix=dict(img='val2017/'), test_mode=True, pipeline=val_pipeline, ))
  • 训练数据为person_keypoints_train2017.json(COCO 2017 训练集),data_mode='topdown'表明是 top-down 模式;
  • 验证数据使用COCO_val2017_detections_AP_H_56_person.json作为预检测人体框输入——这正是模型卡片中"检测器人体 AP 为 56.4"的前提,评测的是姿态估计本身在给定检测框下的表现;
  • 评估指标由val_evaluator中的CocoMetric提供(基于person_keypoints_val2017.json),覆盖 AP/AP50/AP75/AR 等标准 COCO 关键点指标;
  • default_hooks中配置save_best='coco/AP', rule='greater',训练过程中自动保存验证 AP 最高的检查点。

八、同系列配置横向对比

configs/body_2d_keypoint/simcc/coco/目录下还提供了同一套训练范式下的其他骨干与输入尺寸变体,方便横向对比 SimCC 框架的扩展方式:

配置骨干输入尺寸头结构
simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.pyMobileNetV2(1280 ch)256×192SimCCHead 无反卷积
simcc_res50_8xb64-210e_coco-256x192.pyResNet-50(2048 ch)256×192SimCCHead 默认三层反卷积
simcc_res50_8xb32-140e_coco-384x288.pyResNet-50384×288SimCCHead,140 epoch
simcc_vipnas-mbv3_8xb64-210e_coco-256x192.pyViPNAS_MobileNetV3(160 ch)256×192SimCCHead,deconv_type='vipnas'

对比要点:

  • MobileNetV2 版本通过deconv_out_channels=None去掉全部反卷积,而 ResNet-50 版本保留默认的(256, 256, 256)三层反卷积,两者在精度与算力之间取舍不同;
  • 输入尺寸变化会同步影响input_sizein_featuremap_size(仍是 1/32)以及一维标签长度,Codec 中simcc_split_ratio=2.0sigma=6.0保持一致;
  • 更高分辨率(384×288)对应更短的训练周期(140 epoch)与更小 batch(32),学习率同为 1e-3 但实际有效学习率由auto_scale_lr依据 batch 自动折算。

九、训练、测试与推理

在完成 COCO 数据准备(结构为data/coco/annotations/data/coco/train2017|val2017/,详见 数据准备指南)后,可按 训练与测试指南 操作:

训练

python tools/train.py configs/body_2d_keypoint/simcc/coco/simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.py

测试(指定权重):

python tools/test.py configs/body_2d_keypoint/simcc/coco/simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.py \ /path/to/simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192-4b0703bb_20221010.pth

单张图片推理(使用 inferencer_demo.py):

python demo/inferencer_demo.py tests/data/coco/000000000785.jpg \ --pose2d configs/body_2d_keypoint/simcc/coco/simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192.py \ --pose2d-weights /path/to/simcc_mobilenetv2_wo-deconv-8xb64-210e_coco-256x192-4b0703bb_20221010.pth \ --vis-out-dir vis_results

由于该配置是纯 top-down 模型,端到端人体姿态估计通常需要搭配检测器,可参考 2D 人体姿态 Demo 中topdown_demo_with_mmdet.py的用法。

十、总结与使用建议

  • SimCC 的价值:把二维热图估计降维为两条一维分布,配合simcc_split_ratio获得亚像素精度,且可省去反卷积上采样(wo-deconv),非常适合轻量级、边缘端人体姿态估计;
  • MobileNetV2 的定位:在本配置中承担低算力骨干角色,1280 通道输出直接对接无上采样 SimCCHead,与 ResNet-50 变体形成"精度/速度"两个档位的选择;
  • 关键调参入口sigma(标签平滑宽度)、simcc_split_ratio(坐标细分粒度)、smoothing_type(gaussian/standard)、use_dark(亚像素细化)、flip_test(翻转 TTA)、deconv_out_channels(是否启用反卷积头),这些参数在 mmpose/codecs/simcc_label.py 与 mmpose/models/heads/coord_cls_heads/simcc_head.py 中均有对应实现可查。

该配置连同同目录下的 ResNet-50、ViPNAS-MobileNetV3 变体,共同构成了 MMPose 中 SimCC 家族在 COCO 上的完整参考基线,既是入门 top-down 姿态估计的理想起点,也是在此基础上进行轻量化改造与算法对比的可靠基准。

【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose

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

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

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

立即咨询