拓冰建站拓冰建站
首页 / 资讯中心 / 正文

YOLOv8+MMAction2组合实战:行人动作检测完整管线

简介这是一个基于 YOLOv8 与 MMAction2 的行人动作检测可运行源码包面向计算机视觉、行为识别及深度学习方向的开发者和研究者适合用于智能视频监控、行人行为分析等场景的算法验证与二次开发。压缩包共 11 个文件包含 Python 训练/推理脚本、已训练模型权重.pth、演示视频、配置文件、环境说明文档与可视化页面整体仅 14KB轻量而完整。目前已有 122 人学习下载。源码以 Temporal Shift Module 等预训练模型为例完整覆盖 MMAction2 的环境配置、数据集预处理与划分、配置文件修改以及模型训练、测试和推理环节同时展示了如何将 YOLOv8 集成进来实现行人目标提取、动作识别与结果融合流程中每一步都有脚本、配置和演示视频相互对应便于读者对照复现。对于想在有限数据集上快速验证动作检测算法、或需要一套可运行代码骨架的研究人员与工程开发者该资源提供了清晰的目录结构和可直接修改的实验框架可直接在此基础上替换数据集、调试参数或接入自己的视频流颇具实用价值。 做行人动作检测这个方向我见过太多人一上来就在YOLOv8和MMAction2之间做“二选一”。问他们为什么不用另一个回答往往是“没听过”或者“听说很难”。其实这两个框架解决的问题完全是两回事YOLOv8负责在画面里框出行人回答“人在哪”MMAction2负责分析一段连续帧里的人体姿态变化回答“在干什么”。真正要做行人动作检测恰恰需要把两者串联成一条完整的处理管线。这篇分享就是这个组合的完整落地笔记从设计思路、环境配置、核心源码到推荐避坑点全部摊开适合正在做毕业设计、安防监控、运动分析这类项目的朋友直接参考。1. 为什么不是“二选一”检测与识别的互补逻辑1.1 两套框架各自擅长什么YOLOv8由Ultralytics维护目标检测生态非常成熟支持检测、实例分割、姿态估计等任务。在行人动作检测场景里它承担“空间定位”职责——从每一帧画面中找出所有行人的边界框Bounding Box。它的优势是速度快COCO数据集上预训练的权重直接可用行人这一类的检测置信度通常能稳定在0.8以上。我用一块GTX 1660 Ti跑yolov8n输入640x640分辨率单帧推理大概在10毫秒级别完全能满足实时需求。MMAction2是OpenMMLab体系下的动作识别工具箱集成了TSN、TSM、SlowFast、VideoMAE等主流模型。它解决的才是“动作”本身的问题——给定一段连续的视频帧序列输出该序列属于哪个动作类别。它和图像分类最大的区别在于输入带时序维度模型必须看到目标在时间上的变化趋势才能判断“举手”和“放下手”、“走路”和“跑步”这些差异。所以它跟YOLOv8天然互补一个给空间位置一个给时间语义。1.2 直接整帧识别效果为什么让人抓狂可能有人会说我不用YOLOv8直接把整个视频帧喂给MMAction2不就行了我最初也这么干过实测结果非常不稳定。第一个问题是多目标干扰。动作识别模型大多在主体已相对居中的数据集上训练比如Kinetics、UCF101。当画面中有多个行人时模型不知道该关注谁输出变成了多个动作的混合概率分布哪个类别置信度都上不去。第二个问题是目标占比太小。监控画面通常覆盖一大片区域行人可能只占几十个像素举手、弯腰这些细微动作在降采样后几乎丢失。YOLOv8的检测框把有效区域裁剪出来再缩放至模型输入尺寸相当于做了一个“注意力放大”。第三个问题是算力浪费整帧识别让模型处理了大量无关背景同等推理开销下信息密度很低。1.3 两阶段方案真正带来的精度收益检测-裁剪-识别这个两阶段结构等于把“在哪里识别”这个问题先交给了YOLOv8让MMAction2只聚焦于行人区域。我在自建的摔倒测试集上做过对比整帧识别摔倒动作的F1分数只有0.62左右走检测裁剪管线后提升到0.87以上。原因是动作模型终于能“看清”肢体变化了。另外检测结果绑定了个体身份下游逻辑能知道“画面左边第二个人正在摔倒”而不是“画面中检测到摔倒”。这对联动报警、人群统计、轨迹回溯这些真实业务需求非常关键。两套框架合起来不是简单叠加而是各取所长。2. 流水线设计从原始视频到动作标签的完整数据流2.1 完整处理链路整个项目的处理链路可以拆成八个环节按执行顺序列出来读取视频帧来源可以是本地视频文件或RTSP摄像头流。YOLOv8检测行人输出N个边界框及置信度。接入ByteTrack或DeepSORT做目标跟踪给每个行人分配稳定ID。根据边界框裁剪行人图像缩放到模型输入尺寸。按行人ID维护固定长度的时序缓冲也就是clip buffer。当缓冲长度达到clip要求时组合成clip交给MMAction2推理。将动作类别概率映射为可读标签回传到当前帧。在原始帧上绘制检测框和动作标签输出渲染画面。两个框架官方都没有提供“如何集成”的现成API因为它们解决问题的层级不同。真正工程的工程量几乎都花在步骤4和5这个桥接层上。很多初学者满世界找“YOLOv8接入MMAction2的现成代码”其实理解了数据流自己写桥接代码才是可控的。2.2 时序窗口这样设clip_len 与 frame_intervalMMAction2推理时需要一个clip也就是一组有序帧。我的做法是给每个行人维护一个deque环形缓冲区容量设为clip_len。检测线程每处理一帧就把裁剪后的行人图push进对应ID的缓冲长度达到clip_len后识别线程取走整段做推理。clip_len和frame_interval直接影响模型对动作时间跨度的感知。TSN这类轻量模型通常用8帧、间隔1帧在25帧每秒的视频里覆盖约0.3秒适合检测短促动作。SlowFast这类模型设计上就更侧重时序建模我用16帧、间隔2帧覆盖接近1秒。如果是“打架”“摔倒”这类持续1秒以上的动作我建议把interval调大覆盖更长时间窗口否则模型容易把动作前段和后段割裂识别导致漏报。还有一个关键认知动作识别的滞后性是原理决定的不是bug。一个动作用了0.5秒完成你最早也要在动作开始后的0.5秒加上模型推理时间才能给出判定。如果业务要求在动作刚发生的那一帧就报警单靠动作分类是不够的需要结合姿态关键点或运动速度做前置预判。2.3 滑窗策略别把缓冲一锅端在deque达到容量后我采用滑窗弹出最老的一帧而不是清空整个缓冲。这个细节很影响使用体验。如果每次推理完就清空下一次要重新收集8帧才能再判定动作标签会变成“有-无-有-无”的闪烁状态。滑窗能做到持续识别每一帧滑动后都产生一个新的clip模型不断输出新结果。代价是推理频率提高但配合后面的双缓冲线程设计完全跑得动。3. 环境搭建两套框架共存最容易翻车的地方3.1 版本选型与依赖冲突这是整个项目在本地复现时最劝退新手的一步。YOLOv8要求PyTorch运行环境MMAction2的安装会强制依赖mmcv、mmengine、mmdet等OpenMMLab组件。麻烦在于mmcv的预编译轮子与PyTorch和CUDA版本严格绑定CUDA 10.2、11.3、11.7、12.1各自的预编译包不通用。直接pip install mmcv拿到的默认版本大概率在import mmcv阶段报不匹配。我给出一个实测能共存的组合组件推荐版本Python3.8或3.9CUDA Toolkit11.3或11.7PyTorch1.10至1.13对应cuda113mmcv-lite2.0.1或2.1.0mmengine0.8.4及以上mmaction21.2.0或1.3.xultralytics8.0.x特别注意OpenMMLab 2.0架构mmcv2.0和1.0架构mmcv2.0的API有破坏性变化新旧文本文档混用会造成大规模报错。建议直接用mmaction2 1.x加mmcv 2.x这个组合避开旧版API被废弃的坑。3.2 conda隔离不要硬装进base环境两套框架在Python包级没有必然冲突但顶层依赖存在细微差异比如opencv、numpy的版本要求。最省心的方式是新建独立的conda虚拟环境不要直接装进base。我的安装顺序是这样的conda create -n action_rec python3.9 -y conda activate action_rec # 注意按官网链接安装CUDA版PyTorch不要简单pip install torch否则默认装CPU版 pip install torch1.13.0cu117 torchvision0.14.0cu117 pip install ultralytics # 这里根据你自己的CUDA版本替换链接只装lite即可不用编译完整算子 pip install mmcv-lite2.1.0 -f https://download.openmmlab.com/mmcv/dist/cu117/torch1.13/index.html pip install mmengine mmpycocotools git clone https://github.com/open-mmlab/mmaction2.git cd mmaction2 pip install -v .有个血泪教训mmcv完整版在安装时会编译大量自定义算子如果机器没有装好Visual C Build Tools或gcc会卡在编译阶段然后回退下载预编译轮子。如果只是做推理用mmcv-lite足够省掉编译时间。代价是部分自定义算子不可用但跑标准模型推理完全没问题。3.3 权重准备与自定义数据集边界YOLOv8直接下载官方yolov8n.pt或yolov8s.pt即可COCO数据集里person就是第0类开箱即用。如果场景特殊比如俯视摄像头、夜间、密集人群才需要准备自定义行人数据集做微调。MMAction2官方Model Zoo提供大量预训练权重下载.pth文件后在配置文件中修改权重路径即可。想快速验证环境先跑官方demo的人体动作识别配置再替换业务权重。如果业务需要识别特定动作比如摔倒、挥手、打架OpenMMLab预训练类别往往覆盖不全。这时有两条路一是基于Kinetics预训练权重在自建数据集上微调二是用模型识别“站立”“躺倒”“弯腰”等基础姿态再靠规则逻辑组合成业务判断。对毕业设计和工程初验第二种方案成本最低效果也最可控。4. 核心源码拆解检测裁剪与动作识别的衔接4.1 检测端封装从YOLOv8拿到干净的目标框我习惯把YOLOv8封装成独立的PersonDetector类输入一帧BGR图像输出像素坐标的行人框和置信度。from ultralytics import YOLO class PersonDetector: def __init__(self, weightsyolov8n.pt, conf0.35, iou0.5, devicecuda): self.model YOLO(weights) self.conf conf self.iou iou self.device device def detect(self, frame_bgr): results self.model.predict( sourceframe_bgr, confself.conf, iouself.iou, classes[0], # 只保留person类别极重要 deviceself.device, verboseFalse, ) boxes results[0].boxes.xyxy.cpu().numpy() # (N,4)像素坐标 scores results[0].boxes.conf.cpu().numpy() return boxes, scores两个容易忽略的地方第一classes[0]一定要加否则画面里所有目标都会进入后续识别动作标签会被车、狗、树的框污染我之前见过项目跑出来标签乱跳最后排查就是这行没加。第二conf阈值别设太高。clip buffer需要连续帧都有检测框阈值设成0.9行人稍微侧身或遮挡就漏检时序直接断掉。我实测0.3到0.45比较稳妥宁可多几个误检框也要保证轨迹连续。4.2 裁剪与构建MMAction2的时序输入裁剪本身简单难点在于把一堆行人图变成MMAction2能吃的张量格式。MMAction2底层期望的输入是(N, C, T, H, W)或(C, T, H, W)T是clip帧数。裁剪后的行人图尺寸不一致需要先缩放再堆叠、归一化。import cv2 import torch from torchvision.transforms import Compose, Resize, ToTensor, Normalize class ActionInference: def __init__(self, cfg_path, ckpt_path, devicecuda): from mmaction.apis import init_recognizer self.model init_recognizer(cfg_path, ckpt_path, devicedevice) self.transform Compose([ Resize((224, 224)), ToTensor(), Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) def predict_clip(self, clip_frames): tensors [self.transform(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) for f in clip_frames] input_tensor torch.stack(tensors, dim1).unsqueeze(0) # (1,C,T,H,W) return self.model(input_tensor, return_lossFalse) # 版本相关注意返回值不同版本的mmaction2对外推理接口差异较大。1.0版本的inference_recognizer接受视频路径2.0版本推数据样本格式。我实测最稳妥的方式是直接调用recognizer的forward接口构造好批次张量传入而不是依赖对外封装函数。这样代码虽然多一点但版本兼容性最稳。4.3 主循环把检测和识别串成一条线主循环逻辑不难但性能优化关键点在于别让检测和识别在同一线程里串行执行。YOLOv8推理很快但MMAction2哪怕是TSN8帧输入也要几十毫秒。串行执行整体FPS会掉到个位数。我采用独立线程加双缓冲的思路检测线程读取视频帧 → 检测行人 → 裁剪 → 写入按ID维护的clip buffer。识别线程从clip buffer取够帧 → 推理动作 → 更新该ID的最新标签。主线程渲染当前帧叠加检测框和最新动作标签。import threading import queue from collections import defaultdict, deque CAP 8 clip_buffers defaultdict(lambda: deque(maxlenCAP)) action_labels {} label_lock threading.Lock() def worker_recognize(pid, recognizer): while len(clip_buffers[pid]) CAP: frames list(clip_buffers[pid]) label recognizer.predict_clip(frames) with label_lock: action_labels[pid] label clip_buffers[pid].popleft() # 滑窗 while cap.isOpened(): ret, frame cap.read() if not ret: break boxes, scores detector.detect(frame) for idx, box in enumerate(boxes): x1, y1, x2, y2 box.astype(int) person_img frame[y1:y2, x1:x2] pid track_id if track_id is not None else idx clip_buffers[pid].append(person_img) if len(clip_buffers[pid]) CAP: t threading.Thread(targetworker_recognize, args(pid, recognizer)) t.start() draw_frame draw_results(frame, boxes, action_labels)跨线程共享clip buffer时注意加锁不要直接操作可变对象。在GTX 1660Ti上yolov8s加TSN 8帧组合整体能跑到25FPS左右对于多数监控场景已经足够。5. 实测踩坑记录跑通之后才是真问题5.1 版本混用导致import阶段直接崩溃我有一次把mmaction2装成了0.24.0旧版YOLOv8用的是最新的ultralytics 8.2。两个包分别看都装成功了但一import mmaction就报mmcv版本不匹配。排查半天发现mmcv 2.x和mmaction2 0.24根本不兼容。建议装任何OpenMMLab系框架之前先看官方requirements里锁定的mmcv版本号不要凭印象。用pip show mmaction2确认版本再按版本要求装mmcv。三步走确定mmaction2版本 → 查它的mmcv依赖 → 装对应mmcv-lite。5.2 检测框抖动导致动作识别像抽疯最初我没接跟踪器直接把每个检测框当独立目标。结果同一人连续帧的框顺序是乱的clip buffer被不同的人反复填充识别结果完全随机。这个问题解法分两层简单做法是只处理面积最大的检测框适合单人场景正规做法是接ByteTrack做跨帧关联先给每个行人稳定ID。我用ByteTrack的ID切换率比DeepSORT低不少而且不依赖ReID模型部署负担小。接入跟踪后识别稳定性肉眼可见提升。5.3 推理速度瓶颈和高CPU占用很多人的第一版实现FPS只有3到5帧以为是模型太慢。实际瓶颈往往在裁剪后的图像频繁缩放和颜色转换上每个clip需要反复复制、堆叠图像数组纯Python层开销非常可观。我的优化三板斧一是用torchvision的GPU transform处理裁剪图把缩放和归一化放到GPU上二是只对每帧新增的裁剪图做transform不要对整段clip重复transform三是对TSN和SlowFast开启FP16半精度推理在RTX系列显卡上能提升30%以上速度。如果只做离线视频分析还可以把中间帧检测框缓存成JSON二次运行直接读缓存省掉检测耗时。6. 部署与后续扩展思路6.1 算力预算与帧率权衡不同配置的测试数据提供一个参考GPU模型组合视频流分辨率实际帧率GTX 1660Ti (6GB)yolov8n TSN 8帧1080p20~25 FPSRTX 3060 (12GB)yolov8s TSN 8帧1080p30~35 FPSJetson Orin Nanoyolov8n TSM 8帧720p15~20 FPS这些数据都基于单人目标场景。如果画面里同时有10个行人每个行人都要在clip buffer里维护一份识别耗时会成倍增长。此时要么提高检测置信度阈值减少误检框要么做“选择性识别”只对进入指定区域的行人做动作识别这样能大幅节约算力。6.2 可落地的扩展方向这套组合的通用性很强换数据集、换配置就能变成不同业务系统摔倒检测用TSN/SlowFast识别“站立到倒地”的时序模式配合检测框中心点骤降做双重判断误报率下降明显。打架报警把“踢打、推搡”等类别融合进动作分类器检测到后联动声光报警。工厂安全帽检测YOLOv8换安全帽数据集训练动作识别换“戴或没戴”分类可做实时安全巡检。运动姿态分析结合YOLOv8-pose提取关键点再用MMAction2识别走、跑、跳等动作能直接用于体育训练反馈。部署层面Jetson类设备上可以把YOLOv8转成TensorRT EngineMMAction2模型导出ONNX再转TensorRT做更深度加速。多路摄像头并发场景可以把检测和识别拆成独立服务中间用消息队列传检测结果识别服务用batch推理提升吞吐。我在同一套架构上跑过四路摄像头稳定性和实时性都可接受。最后分享一点个人体会这套系统如果只求“能跑”官方demo加yolov8n就够了想做到“真正可用”跟踪模块和clip缓冲管理对最终效果的影响比换更强动作模型大得多。很多同学一上来就想换SlowFast巨模型其实先把检测-跟踪-识别的数据流理顺精度自然就上来了。项目源码我按模块拆分维护核心桥接逻辑只有几百行后续无论是换模型还是接报警业务改动成本都很低。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门