PP-Human 基于人体 ID 图像分类的行为识别二次开发实战:以“打电话”为例
2026/9/23 7:56:58 网站建设 项目流程

PP-Human 基于人体 ID 图像分类的行为识别二次开发实战:以“打电话”为例

【免费下载链接】PaddleDetectionObject Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleDetection

本文以 PP-Human 的“打电话”行为识别为例,系统讲解在 PaddleDetection 中如何基于“人体 ID + 图像分类”方案完成行为识别模型的二次开发:从数据集准备、标注文件组织、模型训练与评估、模型导出,到接入 PP-Human 推理管线并自定义行为输出的完整闭环。读完本文,你将掌握这套方案的选型逻辑、数据工程要点,以及如何复用到抽烟、摔倒、闯入等自定义行为的开发中。

一、方案概述:为什么“打电话”选择基于人体 ID 的图像分类

PP-Human 在行为识别场景中内置了五种技术方案:基于视频分类、基于图像分类、基于检测、基于跟踪以及基于骨骼点,覆盖 90% 以上的常见动作类型,方案总览见 action_recognotion/README.md。二次开发的第一步,是根据目标行为的时空特征选择最合适的方案:

  • 基于人体 id 检测(如吸烟):目标具有明显的特征物体(香烟),图片级检测即可判定;
  • 基于人体 id 分类(如打电话):动作主要由上半身即可区分,且目标物(手机)常被手、头遮挡,检测方案难以稳定命中;
  • 基于骨骼点(如摔倒):时序性强的单人动作,场景无关、泛化性好;
  • 基于人体 id 跟踪(如闯入):只关心行人的轨迹与区域关系,与人体动作无关;
  • 基于视频分类(如打架):多人交互、目标互相遮挡严重,需整体视频片段判断。

“打电话”属于典型的帧级图像分类任务:打电话持续时间长、人物肢体变化小,且手机常被遮挡,因此 PP-Human 采用基于人体 ID 的分类方案——先用检测 + 跟踪锁定行人并分配稳定 ID,再对每个 ID 对应人物的图像做图片分类,将分类结果作为当前时刻的行为。更重要的是,该动作仅凭上半身即可区分,因此训练与推理都使用半身图来剔除冗余信息、降低训练难度。

该方案在仓库中的工程实现为 deploy/pipeline/pphuman/action_infer.py 中的ClsActionRecognizer类(继承自属性识别器AttrDetector),与 PP-Human 管线通过ID_BASED_CLSACTION配置节挂载,对应的完整配置示例见 deploy/pipeline/config/examples/infer_cfg_calling.yml。

二、环境准备

基于人体 ID 的分类方案,模型训练环节复用 PaddleClas 的能力,因此需要先按 PaddleClas 官方安装说明完成环境安装(包括 PaddlePaddle 框架与 PaddleClas 代码库),安装完成后即可进行后续的模型训练与评估流程。

说明:PaddleClas 是独立的图像分类工具库,不在本仓库内;本文涉及的训练、评估、导出命令均在 PaddleClas 环境中执行,而推理部署环节(模型重命名、接入 infer_cfg.yml、后处理与可视化)则在当前 PaddleDetection 仓库的 deploy/pipeline 目录下完成。

三、数据准备

基于图像分类的行为识别方案,直接对视频中的图像帧结果进行识别,因此模型训练流程与普通图像分类模型完全一致,不涉及时序信息。

3.1 数据集下载

以“打电话”为例,训练数据基于公开数据集 UAV-Human。请通过数据集官方渠道填写申请材料后获取下载链接。下载后,在UAVHuman/ActionRecognition/RGBVideos路径下包含该数据集的 RGB 视频数据,每个视频的文件名即为其标注信息

3.2 训练及测试图像处理

根据视频文件名中与行为相关的字段(即 action),可以筛选出期望识别的动作类型数据:

  • 正样本视频:以打电话为例,只需找到文件名中包含A024的视频文件;
  • 负样本视频:除目标动作以外的所有视频。

由于视频转图像会产生大量冗余帧,需要对数据进行如下处理:

  1. 间隔采样:对正样本视频每隔 8 帧采样一帧;
  2. 行人检测裁剪:使用行人检测模型将采样帧处理为半身图像,取检测框的上半部分,即img = img[:H/2, :, :]
  3. 正负样本划分:正样本视频采样得到的图像视为正样本,负样本视频采样得到的图像视为负样本。

注意:正样本视频中并非每一帧都完全符合“打电话”这一动作,在视频开头和结尾部分会出现冗余动作(例如拿起/放下手机的过程),需要手工移除这些帧,避免引入噪声标签。

半身图处理在推理侧同样存在:源码 deploy/pipeline/pphuman/action_infer.py 中的crop_half_body方法在送入分类模型前对每个行人图像执行image[:h // 2 + 1, :, :]裁剪(实际实现比文档描述多保留 1 行像素,避免边界信息丢失)。训练与推理保持一致的“半身图”策略,是保证该方案效果的关键细节。

3.3 标注文件准备

训练数据的标注文件格式遵循 PaddleClas 图像分类数据集格式,标注文件样例如下,其中01分别是图片对应的类别序号,每一行采用“空格”分隔图像路径与标注

# 每一行采用"空格"分隔图像路径与标注 train/000001.jpg 0 train/000002.jpg 0 train/000003.jpg 1 ...

此外还需要标签文件phone_label_list.txt,用于将分类序号映射到具体的类型名称:

0 make_a_phone_call # 类型0 1 normal # 类型1

完成上述内容后,将其放置于dataset目录下,文件结构如下:

data/ ├── images # 放置所有图片 ├── phone_label_list.txt # 标签文件 ├── phone_train_list.txt # 训练列表,包含图片及其对应类型 └── phone_val_list.txt # 测试列表,包含图片及其对应类型

四、模型优化

4.1 检测-跟踪模型优化

基于分类的行为识别模型效果,强依赖前序的检测与跟踪效果:

  • 若实际场景中不能准确检测到行人位置,分类模型将无法获得正确的输入图像;
  • 若难以在不同帧之间正确分配人物 ID,则基于 ID 的行为结果会发生错乱,使行为识别部分表现受限。

如果在实际使用中遇到上述问题,请参考 目标检测任务二次开发 以及 多目标跟踪任务二次开发 对检测/跟踪模型进行针对性优化。

4.2 半身图预测

在“打电话”这一动作中,实际通过上半身即可实现动作区分,因此在训练和预测过程中,将图像由行人全身图换为半身图。这一策略的价值在于:剔除腿部、背景等与动作无关的冗余信息,让分类模型聚焦于手部-头部区域的判别特征,从而降低训练难度、提升精度与收敛速度。

五、新增行为:完整开发流程

当需要新增一个自定义行为(例如识别其他上半身动作)时,核心工作是复用前述数据流程、修改分类配置并重新训练一个分类模型。整个流程与“打电话”示例完全一致,步骤如下。

5.1 数据准备

参考前述内容完成数据准备,放置于{root of PaddleClas}/dataset下:

data/ ├── images # 放置所有图片 ├── label_list.txt # 标签文件 ├── train_list.txt # 训练列表,包含图片及其对应类型 └── val_list.txt # 测试列表,包含图片及其对应类型

其中训练及测试列表如下,新增的类别直接填写对应类别号即可

# 每一行采用"空格"分隔图像路径与标注 train/000001.jpg 0 train/000002.jpg 0 train/000003.jpg 1 train/000004.jpg 2 # 新增的类别直接填写对应类别号即可 ...

label_list.txt中需要同样对应扩展类型的名称:

0 make_a_phone_call # 类型0 1 Your New Action # 类型1 ... n normal # 类型n

5.2 配置文件设置

PaddleClas 中已集成“打电话半身图”分类的训练配置文件(PPHGNet_tiny_calling_halfbody.yaml,位于 PaddleClas 仓库ppcls/configs/practical_models/下),需要重点关注的设置项如下:

# model architecture Arch: name: PPHGNet_tiny class_num: 2 # 对应新增后的数量 ... # 正确设置image_root与cls_label_path,保证image_root + cls_label_path中的图片路径能够正确访问图片路径 DataLoader: Train: dataset: name: ImageNetDataset image_root: ./dataset/ cls_label_path: ./dataset/phone_train_list_halfbody.txt ... Infer: infer_imgs: docs/images/inference_deployment/whl_demo.jpg batch_size: 1 transforms: - DecodeImage: to_rgb: True channel_first: False - ResizeImage: size: 224 - NormalizeImage: scale: 1.0/255.0 mean: [0.485, 0.456, 0.406] std: [0.229, 0.224, 0.225] order: '' - ToCHWImage: PostProcess: name: Topk topk: 2 # 显示topk的数量,不要超过类别总数 class_id_map_file: dataset/phone_label_list.txt # 修改后的label_list.txt路径

关键配置项说明:

  • Arch.class_num:必须与新增后的类别总数一致(例如原 2 类新增 1 类后改为 3);
  • DataLoader.Train.dataset.image_rootcls_label_path:二者拼接后应能正确访问图片,即image_root为数据集根目录,cls_label_path指向训练列表文件;
  • Infer.PostProcess.class_id_map_file:指向修改后的label_list.txt,用于推理时将类别序号映射为名称;
  • Infer.PostProcess.topk:显示 Top-k 的类别数,不要超过类别总数。

5.3 模型训练及评估

模型训练

通过如下命令启动分布式训练:

export CUDA_VISIBLE_DEVICES=0,1,2,3 python3 -m paddle.distributed.launch \ --gpus="0,1,2,3" \ tools/train.py \ -c ./ppcls/configs/practical_models/PPHGNet_tiny_calling_halfbody.yaml \ -o Arch.pretrained=True

其中Arch.pretrainedTrue表示使用预训练权重帮助训练,可以显著提升收敛速度与最终精度。

模型评估

训练好模型之后,通过以下命令评估模型指标:

python3 tools/eval.py \ -c ./ppcls/configs/practical_models/PPHGNet_tiny_calling_halfbody.yaml \ -o Global.pretrained_model=output/PPHGNet_tiny/best_model

其中-o Global.pretrained_model="output/PPHGNet_tiny/best_model"指定了当前最佳权重所在的路径,如果指定其他权重,只需替换对应的路径即可。

5.4 模型导出

参考 PaddleClas 的分类模型导出文档,可以通过以下命令导出推理模型:

python tools/export_model.py -c ./PPHGNet_tiny_calling_halfbody.yaml \ -o Global.pretrained_model=./output/PPHGNet_tiny/best_model \ -o Global.save_inference_dir=./output_inference/PPHGNet_tiny_calling_halfbody

然后将导出的模型重命名,并加入配置文件,以适配 PP-Human 的使用。PP-Human 推理时约定模型文件名为model.pdmodel/model.pdiparams,因此需要将 PaddleClas 导出的inference.*系列文件重命名:

cd ./output_inference/PPHGNet_tiny_calling_halfbody mv inference.pdiparams model.pdiparams mv inference.pdiparams.info model.pdiparams.info mv inference.pdmodel model.pdmodel # 下载预测配置文件 wget <PP-Human 模型库中提供的 infer_cfg.yml 下载地址>

即从 PaddleDetection 的 PP-Human 模型库中下载与PPHGNet_tiny_calling_halfbody对应的预测配置文件infer_cfg.yml,放置于模型目录下。至此,模型即可被 PP-Human 的ClsActionRecognizer加载并进行实际预测。

值得一提的是,当前仓库中已内置一份该方案的推理管线配置样例 deploy/pipeline/config/examples/infer_cfg_calling.yml,其中ID_BASED_CLSACTION节给出了开箱即用的参数组合:

ID_BASED_CLSACTION: model_dir: <PPHGNet_tiny_calling_halfbody 模型下载地址> batch_size: 8 threshold: 0.8 display_frames: 80 skip_frame_num: 2 enable: True

这些参数与 deploy/pipeline/pphuman/action_infer.py 中ClsActionRecognizer.__init__的形参一一对应:

  • threshold:正类(目标行为)的置信度阈值,低于该值的分类结果按负类处理;
  • display_frames:即源码中的frame_life,单帧分类结果在历史记录中的存活帧数,用于时序平滑;
  • skip_frame_num:跳帧推理间隔,非推理帧直接复用上一帧结果,用于加速;
  • batch_size:分类推理的批大小。

5.5 自定义行为输出

基于人体 ID 分类的行为识别方案,将任务转化为对“人物图像”进行图片级别的分类,分类结果即视为当前阶段的行为。因此,在完成自定义模型的训练与部署后,还需要将分类模型结果转化为最终的行为识别结果作为输出,并修改可视化的显示结果。

转换为行为识别结果

转换逻辑的核心实现在 deploy/pipeline/pphuman/action_infer.py 的match_action_with_id方法中,该方法将分类结果与跟踪 ID 对齐。核心代码为:

# 确定分类模型的最高分数输出结果 cls_id_res = 1 cls_score_res = -1.0 for cls_id in range(len(cls_result[idx])): score = cls_result[idx][cls_id] if score > cls_score_res: cls_id_res = cls_id cls_score_res = score # Current now, class 0 is positive, class 1 is negative. if cls_id_res == 1 or (cls_id_res == 0 and cls_score_res < self.threshold): # 如果分类结果不是目标行为或是置信度未达到阈值,则根据历史结果确定当前帧的行为 history_cls, life_remain, history_score = self.result_history.get( tracker_id, [1, self.frame_life, -1.0]) cls_id_res = history_cls cls_score_res = 1 - cls_score_res life_remain -= 1 if life_remain <= 0 and tracker_id in self.result_history: del (self.result_history[tracker_id]) elif tracker_id in self.result_history: self.result_history[tracker_id][1] = life_remain else: self.result_history[ tracker_id] = [cls_id_res, life_remain, cls_score_res] else: # 分类结果属于目标行为,则使用将该结果,并记录到历史结果中 self.result_history[ tracker_id] = [cls_id_res, self.frame_life, cls_score_res] ...

这段代码背后是一套基于 ID 的时序平滑机制,理解它对于自定义行为非常关键:

  1. 逐 ID 对齐tracker_id来自多目标跟踪结果(mot_result),分类结果按行人框顺序与 ID 一一匹配;
  2. 置信度门控:当前约定类别 0 为正类(目标行为)、类别 1 为负类。当最高分落在负类,或落在正类但置信度低于self.threshold时,认为当前帧分类不可信;
  3. 历史兜底:不可信时从self.result_history中取出该 ID 的历史分类结果与剩余存活帧数life_remain,用历史结果覆盖当前帧,并将存活帧数减 1;存活帧数耗尽则删除该 ID 的历史记录;
  4. 正向刷新:分类结果可信时,将[cls_id_res, self.frame_life, cls_score_res]写入历史,重新开始计生命周期。

self.frame_life由配置中的display_frames决定(默认 80),它决定了“单次可信分类结果能连续覆盖多少帧的不可信结果”,本质上是行为状态的保持时长,可有效消除单帧误判引起的识别抖动。

此外,deploy/pipeline/pphuman/action_infer.py 的predict_with_mot还实现了跳帧复用:当skip_frame_cnt未到达skip_frame_num且当前帧的 ID 集合与上一帧完全一致时,直接调用reuse_result复用历史结果,跳过分类推理,从而在长时监控场景下显著降低计算开销。

修改可视化输出

目前基于 ID 的行为识别,是根据行为识别结果及预定义的类别名称进行展示的。相关逻辑位于 deploy/pipeline/pipeline.py 的visualize_video方法中:

cls_action_res = result.get('cls_action') if cls_action_res is not None: visual_helper_for_display.append(self.cls_action_visual_helper) action_to_display.append("Calling")

其中"Calling"即当前行为的展示名称,随后调用visualize_action在画面中叠加绘制行为标签。如果自定义的行为需要修改为其他的展示名称,请对应修改此处action_to_display.append(...)中的字符串,以正确输出对应结果。同样,若修改了类别定义(例如多类别行为),还需同步检查 deploy/pipeline/pphuman/action_utils.py 中可视化的辅助逻辑是否与类别数量匹配。

六、总结

基于人体 ID 图像分类的行为识别方案,将“视频级行为识别”降维为“帧级图像分类”,具有数据易采集(图片级标注)、预训练资源丰富、训练成本低等优势,特别适合打电话这类“单目标、长持续、上半身可判别”的动作。本文完整覆盖了从方案选型、数据准备、标注组织、模型优化,到 PaddleClas 训练/评估/导出、接入 PP-Human 推理管线,再到后处理与可视化自定义的全链路开发流程。结合 deploy/pipeline/pphuman/action_infer.py 的ClsActionRecognizer实现与 deploy/pipeline/config/examples/infer_cfg_calling.yml 配置样例,你可以快速将其迁移到自定义行为的开发中;同系列的其他方案(基于检测、基于骨骼点、基于视频分类)可参考 action_recognotion 目录 下的对应文档。

【免费下载链接】PaddleDetectionObject Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleDetection

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

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

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

立即咨询