MMDetection 之外的 29 点人脸关键点定位:MMPose 中 HRNetv2 在 COFW 数据集上的完整配置与复现指南
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
导读
本文以 MMPose 仓库中的 configs/face_2d_keypoint/topdown_heatmap/cofw/hrnetv2_cofw.md 模型页为核心,系统讲解基于 HRNetv2 骨干网络在 COFW 人脸关键点数据集上的 top-down 热图回归方案。你将了解到该模型页记录的官方评测结果(NME 3.48)、完整配置文件 td-hm_hrnetv2-w18_8xb64-60e_cofw-256x256.py 的每一处参数含义、COFW 数据集的组织与转换流程,以及从数据准备到训练、测试、推理的完整实操路径。
模型页概览:HRNetv2 × COFW 的结果与引用信息
hrnetv2_cofw.md是一个典型的 Model Zoo 结果页,它记录了该模型在 COFW 测试集上的官方成绩,并附带了算法与数据集的 BibTeX 引用,方便学术使用。
算法与数据集出处
- HRNetv2(TPAMI'2019):《Deep High-Resolution Representation Learning for Visual Recognition》,作者为 Jingdong Wang、Ke Sun、Tianheng Cheng 等。HRNet 的核心思想是全程保持高分辨率特征表示,并通过并行多分辨率子网不断交换信息,这一设计在 2D 人体/人脸关键点任务上带来了明显精度提升。本仓库中对应实现位于 mmpose/models/backbones/hrnet.py。
- COFW(ICCV'2013):《Robust face landmark estimation under occlusion》,作者为 Burgos-Artizzu、Perona、Dollár。COFW 数据集以其"遮挡下的鲁棒人脸关键点估计"著称,共标注 29 个关键点,是评估人脸关键点模型在遮挡场景下鲁棒性的重要基准。其数据集元信息定义在 configs/base/datasets/cofw.py,对应的加载实现为 mmpose/datasets/datasets/face/cofw_dataset.py 中的
COFWDataset。
官方评测结果
模型页给出的官方结果表如下(模型仅在 COFW 训练集上训练):
| Arch | Input Size | NME | ckpt | log |
|---|---|---|---|---|
| pose_hrnetv2_w18 | 256x256 | 3.48 | ckpt | log |
这一结果同时被记录在配套的 hrnetv2_cofw.yml 元数据文件中:任务为 Face 2D Keypoint,训练数据为 COFW,权重文件为hrnetv2_w18_cofw_256x256-49243ab8_20211019.pth。
说明:本文不展开外部下载链接的细节,ckpt 与 log 的实际获取方式请以模型页中的链接为准;权重文件通常由
tools/misc/pth_transfer.py等工具配合init_cfg的Pretrained方式载入。
配置逐段解析:td-hm_hrnetv2-w18_8xb64-60e_cofw-256x256.py
配置文件命名遵循 MMPose 的语义化规范:td-hm(top-down heatmap 范式)、hrnetv2-w18(骨干网络为 HRNetV2-W18)、8xb64(8 卡 × batch size 64)、60e(60 个 epoch)、cofw-256x256(数据集与输入尺寸)。下面按模块拆解其每一部分。
训练配置与优化器
_base_ = ['../../../_base_/default_runtime.py'] # runtime train_cfg = dict(max_epochs=60, val_interval=1) # optimizer optim_wrapper = dict(optimizer=dict(type='Adam', lr=2e-3)) # 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=50, milestones=[40, 55], gamma=0.1, by_epoch=True) ] # automatically scaling LR based on the actual training batch size auto_scale_lr = dict(base_batch_size=512)- 训练 60 个 epoch,每个 epoch 后做一次验证(
val_interval=1)。 - 优化器使用 Adam,初始学习率
2e-3。 - 学习率策略分两段:前 500 次迭代(
by_epoch=False,即按 iteration 计)用LinearLR做 warm-up,从start_factor=0.001线性爬升;之后按 epoch 采用MultiStepLR,在第 40、55 个 epoch 各衰减为原来的 0.1(gamma=0.1)。 auto_scale_lr声明基准 batch size 为 512,实际训练 batch size 与之不同时,MMPose 会自动按比例缩放学习率。
编解码器:MSRAHeatmap
codec = dict( type='MSRAHeatmap', input_size=(256, 256), heatmap_size=(64, 64), sigma=1.5)MSRAHeatmap来自论文《Simple Baselines for Human Pose Estimation and Tracking》(Xiao et al., 2018),其实现位于 mmpose/codecs/msra_heatmap.py。编码阶段将 256×256 输入图像中的关键点坐标按scale_factor = input_size / heatmap_size = 4缩放,并生成 64×64 分辨率、标准差sigma=1.5的高斯热图;解码阶段则通过get_heatmap_maximum取热图最大值位置,再配合refine_keypoints做亚像素细化,最后乘以scale_factor还原到原图坐标。该 codec 还支持unbiased=True开启 DarkPose 无偏编码(见generate_unbiased_gaussian_heatmaps),本配置未开启。
模型结构: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='HRNet', in_channels=3, extra=dict( stage1=dict(num_modules=1, num_branches=1, block='BOTTLENECK', num_blocks=(4, ), num_channels=(64, )), stage2=dict(num_modules=1, num_branches=2, block='BASIC', num_blocks=(4, 4), num_channels=(18, 36)), stage3=dict(num_modules=4, num_branches=3, block='BASIC', num_blocks=(4, 4, 4), num_channels=(18, 36, 72)), stage4=dict(num_modules=3, num_branches=4, block='BASIC', num_blocks=(4, 4, 4, 4), num_channels=(18, 36, 72, 144), multiscale_output=True), upsample=dict(mode='bilinear', align_corners=False)), init_cfg=dict(type='Pretrained', checkpoint='open-mmlab://msra/hrnetv2_w18'), ), neck=dict(type='FeatureMapProcessor', concat=True), head=dict( type='HeatmapHead', in_channels=270, out_channels=29, deconv_out_channels=None, conv_out_channels=(270, ), conv_kernel_sizes=(1, ), loss=dict(type='KeypointMSELoss', use_target_weight=True), decoder=codec), test_cfg=dict(flip_test=True, flip_mode='heatmap', shift_heatmap=True))- 骨干:HRNet-W18,四个 stage 分别输出 1/2/3/4 条并行分支,通道数依次为 (18, 36, 72, 144);
multiscale_output=True使 stage4 保留多分辨率输出,以便 neck 做特征融合。预训练权重来自open-mmlab://msra/hrnetv2_w18。 - neck:
FeatureMapProcessor以concat=True将 HRNet 的多尺度特征图在通道维拼接。 - head:
HeatmapHead的in_channels=270恰好等于 18+36+72+144 之和;out_channels=29对应 COFW 的 29 个关键点;deconv_out_channels=None表示不采用 SimpleBaselines 式的反卷积上采样,而是用 1×1 卷积在原始热图分辨率上输出。损失为KeypointMSELoss(带use_target_weight=True的加权 MSE),配合decoder=codec完成热图到坐标的解码。 - 测试策略:
flip_test=True开启水平翻转测试融合,flip_mode='heatmap'表示在热图层面融合,shift_heatmap=True补偿翻转引起的像素偏移。
数据管线与数据加载
dataset_type = 'COFWDataset' data_mode = 'topdown' data_root = 'data/cofw/'训练管线包含LoadImage→GetBBoxCenterScale→RandomFlip→RandomBBoxTransform(rotate_factor=60、scale_factor=(0.75, 1.25),不做平移)→TopdownAffine→GenerateTarget→PackPoseInputs;验证管线仅包含LoadImage→GetBBoxCenterScale→TopdownAffine→PackPoseInputs,不引入任何随机增强。
数据加载部分:训练集 batch size 64、2 个 worker,标注文件为annotations/cofw_train.json;验证集 batch size 32,标注文件为annotations/cofw_test.json,test_mode=True;test_dataloader = val_dataloader。评估器使用NME指标并指定norm_mode='keypoint_distance'。
指标解析:COFW 上的 NME(Normalized Mean Error)
NME度量类实现在 mmpose/evaluation/metrics/keypoint_2d_metrics.py 中。NME计算关键点的平均欧氏距离并除以一个归一化因子,支持两种归一化模式:
use_norm_item:使用 datainfo 中指定的归一化项(如 AFLW 的bbox_size);keypoint_distance:使用数据集默认的左右眼外眼角关键点距离作为归一化因子。
COFW 的默认关键点索引在NME.DEFAULT_KEYPOINT_INDICES中定义为'cofw': [8, 9],即右、左眼最外侧关键点。模型页给出的NME 3.48即是在这一归一化约定下得到的测试精度,数值越小代表定位越准。
COFW 数据集准备:从 .mat 到 COCO 格式
COFW 数据集的原生格式为 MATLAB 的.mat文件,需要转换为 COCO 风格 JSON 后才能被COFWDataset(继承自BaseCocoStyleDataset)加载。官方数据准备流程记录在 docs/en/dataset_zoo/2d_face_keypoint.md:
- 下载
COFW_color.zip,将COFW_train_color.mat与COFW_test_color.mat放入data/cofw/目录; - 在仓库根目录下运行转换脚本:
python tools/dataset_converters/parse_cofw_dataset.py- 转换完成后得到
data/cofw/annotations/cofw_train.json、cofw_test.json以及data/cofw/images/下的解包图片。
转换脚本位于 tools/dataset_converters/parse_cofw_dataset.py。转换后的数据集元信息(29 个关键点、左右对称点的swap关系、关键点权重与 sigma)定义在 configs/base/datasets/cofw.py,其中joint_weights=[1.] * 29表示各点权重一致,sigmas=[]表明该数据集不使用基于 sigma 的 OKS 评估,而是以 NME 为主。
训练、测试与单图推理
单卡/多卡训练
# 单卡 python tools/train.py configs/face_2d_keypoint/topdown_heatmap/cofw/td-hm_hrnetv2-w18_8xb64-60e_cofw-256x256.py # 8 卡分布式训练 bash tools/dist_train.sh configs/face_2d_keypoint/topdown_heatmap/cofw/td-hm_hrnetv2-w18_8xb64-60e_cofw-256x256.py 8训练过程中,default_hooks中的checkpoint被配置为save_best='NME', rule='less', interval=1,即每个 epoch 都会评估 NME 并保存最优权重(NME 越小越好)。SLURM 集群用户可参考 tools/slurm_train.sh。
测试与推理
python tools/test.py configs/face_2d_keypoint/topdown_heatmap/cofw/td-hm_hrnetv2-w18_8xb64-60e_cofw-256x256.py <checkpoint路径>测试时会自动加载 hrnetv2_cofw.yml 中登记的权重,或指定本地权重路径。单张图片的快速推理可使用 demo/topdown_demo_with_mmdet.py(需配合检测器提供人脸框)或 demo/inferencer_demo.py(直接使用 mmpose/apis/inferencers/pose2d_inferencer.py 提供的统一推理接口)。
源码佐证:COFWDataset 与测试数据
COFWDataset在 mmpose/datasets/datasets/face/cofw_dataset.py 中定义,其 docstring 明确指出:标注采用 29 点 mark-up,论文为《Robust face landmark estimation under occlusion》(ICCV'2013),METAINFO直接从configs/_base_/datasets/cofw.py加载。这意味着只要保持_base_元信息不变,任何以from_file='configs/_base_/datasets/cofw.py'为元信息的自定义数据集都可以复用该模型配置。仓库还提供了 COFW 的测试样例数据(tests/data/cofw 下的*.json与*.jpg),可用于快速验证数据管线是否正常工作。
小结
从 hrnetv2_cofw.md 出发,本文完整还原了 MMPose 中 HRNetv2-W18 在 COFW 29 点人脸关键点任务上的落地全貌:官方 NME 3.48 的结果基线、MSRAHeatmap 编解码原理、TopdownPoseEstimator各模块参数、NME 指标的归一化细节、.mat原始数据到 COCO 格式的转换流程,以及训练、测试与推理命令。无论你是要复现该基线、在其基础上调参,还是将 COFW 作为遮挡场景人脸关键点基准,都可以直接以本仓库的配置与源码作为起点。
【免费下载链接】mmposeOpenMMLab Pose Estimation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考