资讯动态

MMAction2 PoseC3D 自定义数据集训练实战:从骨架标注提取到模型训练的完整流程

发布时间:2026/10/13 2:49:46 来源:尧图企业网站定制
人工智能计算机视觉深度学习【免费下载链接】mmaction2OpenMMLabs Next Generation Video Understanding Toolbox and Benchmark项目地址https://gitcode.com/gh_mirrors/mm/mmaction2点击查看免费下载本篇技术指南以 custom_dataset_training.md 为核心系统讲解如何使用 MMAction2 中的 PoseC3D 模型在自定义动作数据集上完成训练。读完后你将掌握三件具体的事如何用 ntu_pose_extraction.py 为自定义视频逐条提取 2D 骨架标注并聚合成符合PoseDataset要求的 pickle 标注文件如何改造官方 PoseC3D 配置类别数、标注路径、预训练权重、训练调度使其适配自己的数据以及如何启动、校验整个训练流程。前置概念PoseC3D 只需要骨架信息PoseC3D出自论文Revisiting Skeleton-based Action Recognition不直接消费 RGB 视频帧而是以 3D 伪热图pseudo heatmap为骨架的时空表示从每帧人体关键点坐标出发按帧生成高斯热图堆叠再交给 3D CNN官方基线为 SlowOnly-R50做动作识别。这一设计带来两个对自定义数据集训练很重要的特性输入侧解耦训练数据只需要“逐帧 2D 关键点 置信度”这一份骨架标注无需原始视频帧参与前向传播但你需要先用自己的视频把这份标注生产出来对姿态估计噪声更鲁棒相比 GCN 类方法直接消费骨骼图热图表示对关键点抖动容忍度更高见 configs/skeleton/posec3d/README.md 的摘要部分。官方基线配置 slowonly_r50_8xb16-u48-240e_ntu60-xsub-keypoint.py 中可以看到backbone的in_channels17即 COCO 17 关键点热图通道数——因此自定义数据集的标注必须是COCO-17 关键点格式这正是后续提取与聚合步骤要保证的。第一步安装依赖并提取 2D 关键点环境准备提取脚本 ntu_pose_extraction.py 依赖 MMDetection人体检测和 MMPoseTop-Down 姿态估计。从源码可以确认两条硬性依赖链detection_inference 内部from mmdet.apis import inference_detector, init_detector缺 mmdet 会直接抛ImportErrorpose_inference 内部from mmpose.apis import inference_topdown, init_model同样缺 mmpose 即报错。这两个包可通过 MMAction2 的 extras 安装见 requirements/mminstall.txt 对 mmcv/mmengine 版本的约束mmdet/mmpose 需与之兼容pip install -U openmim mim install mmaction -f # 安装检测/姿态依赖mmcv、mmengine、mmdet、mmpose mim install mmcv2.0.0rc4,2.2.0 mmengine0.7.1,1.0.0 mmdet mmpose逐视频提取骨架对自定义数据集中的每个视频训练集和验证集都要做执行如下命令假设你的视频名为some_video_from_my_dataset.mp4# 用同一命令可以为所有训练/验证视频批量生成 pickle 文件 python tools/data/skeleton/ntu_pose_extraction.py some_video_from_my_dataset.mp4 some_video_from_my_dataset.pkl脚本的参数在 parse_args 中定义video输入视频、output输出 pickle 名、--device默认cuda:0、--skip-postproc是否跳过 NTU 专用后处理。关键注意点来自原文档的社区结论ntu_pose_extraction.py是为 NTU 视频专门开发的其中的 ntu_det_postproc 步骤会解析 NTU 文件名中的A001动作编号、按 NTU 双人动作表mpaction range(50,61) range(106,121)推断人数并做轨迹追踪后处理。用该脚本处理自定义数据集时应通过--skip-postproc跳过这一步否则文件名解析逻辑vid.split(A)[1][:3]会直接报错。此外还需注意 ntu_pose_extraction 中两处与 NTU 强绑定的硬编码label字段从视频文件名...A001...中解析int(osp.basename(vid).split(A)[1][:3]) - 1。自定义视频文件名不含该模式时这一步会失败最简单的做法是跑完提取后对 pickle 做一次后处理覆盖见下一节聚合脚本中的label处理img_shape/original_shape被硬编码为(1080, 1920)NTU 视频分辨率。如果自定义视频不是 1080×1920建议聚合时一并改写为真实分辨率因为训练管线中 PoseCompact 会用它做紧凑化裁剪、GeneratePoseTarget 会用它生成热图的初始画布。从源码看脚本的内部流程是frame_extract抽帧 →detection_inference用 Faster-RCNNR50-FPNCOCO-person 预训练检测配置为 faster-rcnn_r50-caffe_fpn_ms-1x_coco-person.py分数阈值det_score_thr0.5逐帧检测人体框 →pose_inference_with_align用 HRNet-w32 Top-Down 模型配置 td-hm_hrnet-w32_8xb64-210e_coco-256x192_infer.py在人体框内估计关键点并把各帧人数对齐到同一形状。这与 Preparing Skeleton Dataset 的说明一致官方骨架标注默认即用 Faster-RCNN R50 HRNet-w32 提取由于 mmpose 版本升级自行推理的结果与官方发布标注可能略有差异属正常现象。提取完成后每个视频对应一个 pickle 文件其内容为一个 dict字段类型 / 形状含义keypointnp.ndarray[M, T, V, 2]关键点坐标M人数T帧数V17 个 COCO 关键点keypoint_scorenp.ndarray[M, T, V]关键点置信度frame_dirstr视频标识符不含扩展名的文件名img_shapetuple[int]帧形状(height, width)original_shapetuple[int]同上total_framesint视频总帧数labelint动作标签自定义数据集需自行确定第二步聚合标注为训练/验证 pickle 文件接下来把训练集和验证集所有视频的 pickle 收集进同一个文件如custom_dataset_train.pkl/custom_dataset_val.pkl。tools/data/skeleton/README.md 的The Format of Annotations一节规定了聚合文件的结构一个含两个字段split与annotations的字典split字典键为 split 名如train/val值为属于该 split 的视频标识符frame_dir列表annotations骨架标注列表每条为上一节表格所述字段的字典2D 骨架需要keypoint_score3D 骨架则keypoint最后一维为 3、无 score。一个可直接套用的聚合脚本示例同时修正自定义数据集的label与img_shapeimport glob import pickle import cv2 import numpy as np from mmengine import dump # 或直接用 pickle.dump # 1. 自定义标签映射文件名前缀/目录 - 整数标签必须落在 [0, num_classes) 内 label_map {clap: 0, wave: 1, jump: 2, sit: 3} # 2. 逐视频读取提取出的 pickle并按需修正 label / img_shape def load_one(pkl_path, video_path): with open(pkl_path, rb) as f: anno pickle.load(f) frame_id anno[frame_dir] anno[label] label_map[frame_id.split(_)[0]] # 按你的命名规则解析 if video_path: # 用真实分辨率覆盖硬编码的 (1080, 1920) cap cv2.VideoCapture(video_path) w, h int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) cap.release() anno[img_shape] (h, w) anno[original_shape] (h, w) return anno train_annos [load_one(p, None) for p in glob.glob(pkl_train/*.pkl)] val_annos [load_one(p, None) for p in glob.glob(pkl_val/*.pkl)] # 3. 组装为 PoseDataset 要求的 {split, annotations} 结构 dataset { split: { train: [a[frame_dir] for a in train_annos], val: [a[frame_dir] for a in val_annos], }, annotations: train_annos val_annos, } with open(data/posec3d/custom_dataset.pkl, wb) as f: pickle.dump(dataset, f)说明仓库测试中的样例标注 tests/data/annotations/sample.pkl 即为该结构——顶层{split: {train: [...]}, annotations: [...]}可用于在本地验证自己生成的文件能被正确加载mmengine.load后检查 keys 与frame_dir成员关系。两种组织方式都可行一个文件含split字段训练/验证共用同一个 pkl靠配置里的splittrain/splitval切分与官方ntu60_2d.pkl的用法一致两个独立文件训练、验证各一个 pkl如custom_dataset_train.pkl/custom_dataset_val.pkl此时PoseDataset的split参数可不传——从 load_data_list 看split is None时直接使用annotations全量样本无需split字段。生成后可用以下小脚本做 sanity checkimport mmengine data mmengine.load(data/posec3d/custom_dataset.pkl) anno data[annotations][0] print(data[split]) print(anno[frame_dir], anno[label], anno[img_shape]) print(anno[keypoint].shape, anno[keypoint_score].shape) # [M, T, 17, 2] / [M, T, 17]第三步改造 PoseC3D 配置并启动训练以官方 NTU60 基线 slowonly_r50_8xb16-u48-240e_ntu60-xsub-keypoint.py 为模板它定义了PoseDataset SlowOnly-R50 I3DHead 的完整训练管线做以下改动model dict( ... cls_headdict( ... num_classes4, # 改成你的类别数 ... ), ... ) # 改成你的标注文件路径 ann_file_train data/posec3d/custom_dataset_train.pkl ann_file_val data/posec3d/custom_dataset_val.pkl # 可用官方发布权重初始化从头训练则设为 None load_from pretrained_weight.pth需要逐一对应修改的配置项行内注释引自模板配置的实际取值方便你按数据规模缩放配置项位置 / 默认值修改说明num_classesmodel.cls_head.num_classes模板为 60你的类别数label必须落在[0, num_classes)且建议连续无缺号ann_file顶层ann_file模板为data/skeleton/ntu60_2d.pkl你的 train/val pkl 路径若两个 dataloader 分别建则各指各的split各 dataloader 的dataset.split模板为xsub_train/xsub_val与聚合文件中split的键一致独立文件方式可删除该参数load_from默认None模板中backbone.pretrainedNone指向 PoseC3D 发布权重或 ImageNet 预训练权重从头训练保持None训练超参train_dataloader.batch_size16、train_cfg.max_epochs24配合RepeatDataset times10共 240 epoch、SGDlr0.2、CosineAnnealingLR按 GPU 数与数据量调整小数据建议减小lr与 epoch 数RepeatDataset.times控制重复倍率关于load_from与 backbone 预训练的分工init_recognizer/训练入口在加载 checkpoint 时若 backbone 配置了pretrainedinit_recognizer 会先将其置None避免重复加载训练场景下同理设置load_from后建议把backbone.pretrained一并置None以免日志中重复下载/加载。模板管线无需改动仅供核对中每个变换的作用UniformSampleFrames(clip_len48)均匀采样 48 帧 → PoseDecode 按采样帧索引取出对应帧的关键点 → PoseCompact 把关键点裁剪到紧凑包围盒hw_ratio1.、allow_imgpadTrue→Resize/RandomResizedCrop/Flip等图像几何增强Flip通过left_kp/right_kp同步交换左右关键点→ GeneratePoseTarget 以sigma0.6、use_scoreTrue、with_kpTrue生成 17 通道伪热图 →FormatShape(input_formatNCTHW_Heatmap)整形为[N, C, T, H, W]供 3D 骨干网络消费。测试管线test_mode使用num_clips10的多 clip 平均策略GeneratePoseTarget设doubleTrue做左右热图增强与I3DHead(average_clipsprob)配合。启动训练改完配置后按原文档给出的方式启动此处以仓库中实际存在的 NTU60 配置为例python tools/train.py configs/skeleton/posec3d/slowonly_r50_8xb16-u48-240e_ntu60-xsub-keypoint.py \ --work-dir work_dirs/slowonly_r50_u48_240e_custom \ --validate --test-best --gpus 2 --seed 0 --deterministic其中--validate每个val_interval触发一次验证--test-best在训练结束时用最优权重跑一次测试--gpus指定 GPU 数模板配置8xb16即 8 卡 × batch 16需按卡数相应调整 batch 或 epoch 数--seed 0 --deterministic保证结果可复现。训练过程中PoseDataset会先mmengine.load你的 pklload_data_list若指定了split则按split字段过滤并打印过滤后样本数--validate阶段使用 AccMetric 输出 Top-1 精度可作为标注正确性的实时校验信号验证精度长期为 0 通常意味着label或num_classes不匹配。测试与推理训练完成后用 tools/test.py 评估python tools/test.py configs/skeleton/posec3d/slowonly_r50_8xb16-u48-240e_ntu60-xsub-keypoint.py \ work_dirs/slowonly_r50_u48_240e_custom/best_top1_acc_*.pth若要对自己新拍的单条视频做骨架动作推理可参考 demo_skeleton.py 的流程抽帧 →detection_inference人体检测 →pose_inference姿态估计 → inference_skeleton 喂入识别器最后用label_map文件把预测索引翻译为类别名——为自定义数据集准备一份与num_classes对齐的 label map 即可直接复用。常见问题与排查num_classes与标签不一致label必须为非负整数且 num_classes若标签不连续建议统一重映射为0..C-1。帧数/人物数异常keypoint第一维是人数 M可为 0 人帧留空该帧坐标全 0PoseDecode 对采样帧直接索引frame_dir若指向不存在帧会在管线阶段暴露。自定义视频非 NTU 命名务必传--skip-postproc并在聚合阶段显式覆盖labelntu_pose_extraction的label解析依赖文件名中的A三位数模式。分辨率硬编码提取脚本写死img_shape(1080,1920)聚合时按真实视频分辨率改写否则PoseCompact的紧凑化裁剪与热图画布比例会偏离实际内容。依赖缺失报错Failed to import ... from mmdet.apis / mmpose.apis表示未安装 mmdet/mmpose按第一步安装 extras 依赖后重试。小结自定义数据集上的 PoseC3D 训练可以归纳为三步闭环提标注ntu_pose_extraction.py 逐视频提取 COCO-17 关键点并跳过 NTU 后处理→聚标注按 skeleton 标注格式 组装{split, annotations}结构的 train/val pkl修正label与img_shape→改配置训练在 PoseC3D 模板配置 上修改num_classes、ann_file、load_from与调度参数用 tools/train.py 启动。每一步都有仓库内的源码与测试数据如 tests/data/annotations/sample.pkl可供对照验证按此流程即可完成从原始视频到可部署骨架识别模型的完整链路。赞分享人工智能计算机视觉深度学习【免费下载链接】mmaction2OpenMMLabs Next Generation Video Understanding Toolbox and Benchmark项目地址https://gitcode.com/gh_mirrors/mm/mmaction2点击查看免费下载相关推荐Ultralytics自定义数据集从标注到训练完整流程Ultralytics自定义数据集从标注到训练完整流程 你还在为自定义数据集训练发愁3大痛点一次性解决 标注工具选择困难数据格式转换繁琐训练参数调优无人工智能深度学习计算机视觉预训练MMDetection 训练实战指南标准数据集与自定义数据集的完整训练流程MMDetection 训练实战指南标准数据集与自定义数据集的完整训练流程 MMDetection 为检测模型训练提供了开箱即用的完整工具链以 tools/人工智能计算机视觉深度学习模型评测Silero VAD模型训练自定义数据集训练流程Silero VAD模型训练自定义数据集训练流程 引言突破通用模型局限构建专属语音检测系统 你是否在使用通用VAD模型时遇到过这些痛点嘈杂环境下误检率高人工智能语音上一篇终极图表数据提取指南3分钟从图像获取科研数据的完整教程下一篇GetQzonehistoryQQ空间说说备份的完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑