YOLOv8+MMAction2行人动作识别:双阶段检测与识别实战 📅 发布时间:2026/9/8 11:16:10 👁 浏览次数: 简介一份结合YOLOv8目标检测与MMAction2时序模型的行人动作检测可运行源码面向智能视频监控、行为分析等场景的计算机视觉开发者和研究人员解决视频中行人定位与行为分类的联动问题。资源共11个文件涵盖py算法源码、mp4演示视频、pth预训练权重、md说明文档、html可视化页面及配置文件等压缩包约14KB结构紧凑便于快速部署。源码完整演示了YOLOv8行人提取、MMAction2动作识别与结果融合的关键步骤并针对Temporal Shift Module等预训练模型在小数据集上的选型做了说明同时提供数据集预处理与划分、配置文件修改等实操指引配合可运行脚本与README可复现环境配置、模型训练、测试和推理的完整链路。目前已有122人学习使用适合需要在真实监控场景中落地行人动作检测方案的开发者参考。 最近有朋友在做行人动作检测一上来就问能不能直接用YOLOv8把动作也分类出来我一般会回一句YOLOv8擅长框出目标动作识别是另一个维度的事。与其硬改检测头不如把它和MMAction2配合起来检测负责定位动作识别负责理解行为。这套组合在工程上很成熟尤其适合“先找人、再看人在干嘛”的场景比如安防监控、人机交互、零售行为分析。这次我把整套可运行源码的思路、配置、踩坑点都拆开讲适合刚接触动作识别或者想快速搭一套检测识别pipeline的人。1. 整体思路与双阶段方案选型1.1 为什么不直接用单一模型做检测和分类很多人第一次接触这个需求时会想YOLOv8已经能分类目标了能不能把“走路、跑步、招手、摔倒”当作类别直接在检测框里输出动作标签理论上可以但实际效果会很糟糕。动作识别强依赖时序上下文单帧检测模型只能看到当前帧的姿态和空间位置看不到“过去几秒这个人做了什么”。比如“摔倒”和“蹲下”在单帧画面上可能长得一模一样只有结合连续几帧的变化趋势才能区分。单阶段方案还有一个绕不开的问题动作类别通常比目标类别更细数据标注成本成倍增加。你要标“人”容易标“这个人从第几帧开始举手到第几帧放下”就麻烦得多。所以工程上更通用的做法是两阶段先用目标检测模型把行人的位置框出来再把连续多帧的检测框区域或骨骼关键点喂给时序模型做动作分类。这就是YOLOv8MMAction2的典型分工。1.2 YOLOv8负责“在哪”MMAction2负责“在做什么”这套方案里YOLOv8的角色就是干净利落的目标检测器。它每帧输出行人的边界框和置信度我用它过滤掉背景干扰只保留“人”这个前景。MMAction2是OpenMMLab家族里的动作识别库里面封装了多种时序模型比如TSN、TSM、SlowFast还有基于骨骼的ST-GCN。我这里选的是基于RGB帧序列的TSMTemporal Shift Module它在精度和速度之间比较均衡普通GPU也能跑得动。两者的连接方式也很简单对视频流的每一帧跑YOLOv8得到每个人的检测框后把框内的图像区域按时间顺序截取下来组成一个短片段再交给MMAction2的模型判断动作类别。如果多人同时出现需要先做目标跟踪给每个人分配一个ID再按ID组织各自的时序片段。否则识别结果会在多个人之间来回跳。方案优势劣势单帧检测模型直接分类流程简单、延迟低缺乏时序信息混淆动作多YOLOv8单帧分类头复用检测框仍无法区分同姿不同动YOLOv8MMAction2时序识别利用连续帧动作区分度高多一个时序模型工程链路稍长2. 核心细节解析从检测框到动作片段2.1 YOLOv8行人检测的关键配置YOLOv8本身不复杂但用在动作识别场景里有几个参数值得单独调。首先模型尺寸我建议优先用yolov8n或yolov8s。动作识别需要连续处理大量帧检测部分如果太重整个pipeline的FPS会被拖下来。其次置信度阈值一般取0.4~0.5但在监控场景里行人经常被遮挡或处于画面边缘阈值可以放宽到0.3宁可多出几个框也不能漏掉关键人物。NMS的IoU阈值建议默认0.45如果画面中行人密集可以调低到0.4减少多人框重叠导致的漏检。还有一个容易忽略的点检测输入分辨率。YOLOv8默认是640x640如果原视频是1080p直接resize到640会损失小目标细节。行人动作检测通常人是主体尺寸不算太小我用640基本够但如果摄像头离得远、行人只占几十个像素建议把imgsz调到960或1280代价是推理时间增加。这个需要根据实际摄像头角度去试。在多人场景里我还会给检测结果接一个轻量级追踪器比如ByteTrack。它不需要额外训练用检测框和IoU匹配就能稳定跟踪。有了track IDMMAction2才能拿到“同一段时间里同一个人的连续画面”。这是我踩过比较深的一个坑一开始没做跟踪画面里两个人交叉走过动作识别结果直接串台。2.2 MMAction2动作识别输入构造MMAction2的输入不是随便截几帧图片就行的。以TSM为例它通常接收一个clip也就是连续N帧的堆叠。这个N一般取8或16。实际操作时我会从某个人的跟踪轨迹里均匀取出最近N帧的检测框区域resize成模型需要的尺寸比如224x224然后按时间顺序排列成一个tensor。这里有个重要细节采样帧的方式。不是简单取最近N帧而是先选定一个时间窗口比如过去2秒然后在这个窗口里均匀采样8帧。这样能避免人物动作在时间轴上被压缩或拉伸。MMAction2有现成的SampleFrames模块做这件事但我调试时发现如果直接喂原始视频帧需要先根据检测框做crop再做resize和归一化。顺序不能乱先crop再resize最后归一化到ImageNet的mean/std否则模型输出会莫名其妙。另外MMAction2支持处理整段视频也支持在线流式识别。源码里我会用VideoRecognizer.inference直接处理一个clip tensor。但要注意MMAction2的inference接口默认输入是NCHW格式的原始帧列表类别映射文件要和你训练/下载时的label顺序完全一致。很多“能跑但结果全错”的问题80%出在label对齐上。2.3 数据集与标签对齐的坑如果你用的是预训练模型比如在Kinetics-400上训练的TSM那它的输出标签是400个动作类别比如“开酒瓶”“刷地板”“打保龄球”。把这些类别直接用在行人动作检测业务里会很别扭因为你需要的是“行走、奔跑、站立、挥手、跌倒”这种更贴近场景的标签。这时候就必须准备自己的数据集微调。我建议用已有公开数据集做预训练的起点比如UCF101或Something-Something再采集自己的业务数据做微调。标注格式用MMAction2支持的自定义格式一个视频片段对应一个动作类别标签时间段划分要标清楚。粒度上动作的开始和结束帧尽量标精确TSM这类模型对边界敏感标得粗会让模型学出“过渡动作”。还有一个容易出问题的地方类别不平衡。监控场景里“行走”占了90%“跌倒”可能只有1%。此时不能只看准确率要关注每个类别的recall。可以在训练时给标签加class_weight或者干脆对稀有类别做过采样。这个我在后面训练配置里会提到。3. 实操过程搭建可运行环境与跑通源码3.1 环境配置与版本兼容这套源码依赖OpenMMLab生态版本兼容是最大的门槛。我用的稳定组合是Python 3.8、CUDA 11.7、PyTorch 1.13.1、mmcv 2.0.1对应mmengine、mmdet 3.2.0、mmaction2 1.2.0。YOLOv8部分用ultralytics的8.x版本和OpenMMLab体系分开装互不干扰。特别注意mmcv的安装一定要和你的CUDA、PyTorch版本匹配。用官方命令从源码编译最稳妥但耗时较长。如果想用预编译wheel你得精确选择mmcv2.0.1对应的cu117/torch1.13版本。这里我吃过亏装了mmcv 2.0.1但PyTorch是2.0直接导致cuda算子不匹配整个检测模块跑不起来。所以先定PyTorch再定mmcv顺序不能反。YOLOv8的环境比较简单pip install ultralytics就能搞定。MMAction2安装则需要克隆仓库然后pip install -e .。建议用虚拟环境隔离不要和系统Python混装否则OpenMMLab这套依赖能让你的环境乱成一团。3.2 源码结构与关键模块说明我提供的可运行源码基本是这样的结构project/ ├── detector/ │ └── yolov8_detector.py # 封装YOLOv8检测 ├── tracker/ │ └── bytetrack.py # 简单跨帧跟踪 ├── recognizer/ │ └── mmaction_recognizer.py # 封装MMAction2 ├── pipeline.py # 串联检测、跟踪、识别 ├── configs/ │ └── tsm_r50_8frames.py # MMAction2模型配置 └── requirements.txt核心的pipeline逻辑并不复杂。我用一个视频帧循环来演示# 伪代码展示主流程 while True: frame cap.read() dets detector.detect(frame) # list of [x1,y1,x2,y2,score] tracks tracker.update(dets) # 给每个框分配track_id for track in tracks: clips[track.id].append(crop_by_box(frame, track.box)) if len(clips[track.id]) clip_len: clip sample_frames(clips[track.id]) action recognizer.predict(clip) draw(frame, track.box, action)这里关键的模块是tracker.update和recognizer.predict。ByteTrack的update会先做IoU匹配再处理新出现和消失的轨迹。实际使用中我会保存每个人的历史crop列表长度超过clip_len后就按时间均匀采样而不是直接存最近N帧这样动作识别更稳定。3.3 在GPU/CPU上的运行与性能优化很多人问女孩那类问题GTX 1660Ti能不能跑可以。我实测过YOLOv8s TSM(8帧)在1660Ti上跑1080p视频检测部分大约20ms一帧识别部分每次动作判断约30ms汇总起来每秒大概能处理15~20帧基本满足实时监控需求。如果换成YOLOv8n检测能快一倍但小目标精度会下降。如果你要用CPU跑那就得把输入分辨率降到320识别模型换成TSM的轻量版速度大概在3~5FPS只能做离线分析。优化方面有几个立竿见影的手段。视频帧如果是固定摄像头可以做一个背景差分预处理画面中没有任何运动目标时直接跳过YOLOv8检测能省大量算力。另外MMAction2的推理可以放到TensorRT上加速但配置流程略繁琐纯Python实现先用PyTorch跑通功能性能优化放在后面。还有一个容易被忽略的细节视频帧预处理中bgr和rgb的顺序一定不要搞反。YOLOv8用OpenCV读进来是BGR而MMAction2的tsm模型训练时用的是RGB。如果你直接喂BGR帧给识别模型动作准确率会明显下降。我在pipeline里专门加了一个cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)。4. 常见问题与排查技巧实录4.1 依赖冲突与mmcv版本不匹配这是OpenMMLab全家桶用户最头疼的问题。常见的报错是ModuleNotFoundError: mmcv._ext或者KeyError: mmcv has no attribute ops。这时候先检查版本矩阵python -c import mmcv; print(mmcv.__version__)和python -c import torch; print(torch.__version__)确保它们与mmcv官方兼容表一致。如果已经装错最简单的方法是在虚拟环境里卸载重装而不是尝试修补二进制的cuda算子。另一种隐蔽问题同时装了mmcv-full和mmcv两个包冲突。OpenMMLab从2.0开始已经不做mmcv-full的区分统一叫mmcv。老教程里让你装mmcv-full的在2.x时代是不对的。务必用官方最新安装命令。4.2 检测结果抖动/误检导致动作识别错误视频里行人偶尔被遮挡YOLOv8会短暂漏检ByteTrack的轨迹会断裂然后重新分配新ID。动作识别一旦换了ID前面攒的历史帧就断掉了识别结果跳变。解决方法是让ByteTrack允许轨迹“存活”一段时间比如在丢失目标后保留ID 0.5秒期间如果没有新的框匹配才判定轨迹结束。这样短暂遮挡不会影响动作识别。另一个常见问题误检框把背景砖墙或汽车玻璃当成行人识别模型在里面提取到的“动作”完全没有意义。我一般会加一个尺寸过滤检测框高度小于视频高度5%、宽高比大于2.0或小于0.2的框直接丢弃。这个规则在大多数监控视角下都能有效过滤假目标。4.3 推理速度慢怎么办先别急着换模型先看瓶颈在哪。在pipeline里可以对检测和识别分开计时。通常瓶颈出在YOLOv8的输入分辨率太大或MMAction2的模型太大。我建议的调优顺序是第一YOLOv8从s换成n看精度损失在不在可接受范围内第二MMAction2的TSM采样帧数从8降到4延迟能降低一截第三如果还是在实时场景下卡顿可以把检测和识别放到两个线程里并行识别不阻塞检测用队列传递帧。还有一个性能陷阱每次识别都对同一个clip重复计算。如果视频帧率是30FPS而动作识别模型需要8帧那每帧都做一次推理没意义。我实际代码里设置了一个“识别节流”机制每5帧才跑一次动作识别中间帧沿用上一次的结果。这样能有效降低GPU占用同时动作变化平滑肉眼几乎感知不到延迟。下面是一个问题速查表方便直接对照现象可能原因处理建议一运行就报cuda错误mmcv与PyTorch版本不匹配核对版本矩阵重装mmcv动作类别全是乱的label映射文件与模型不一致检查类别索引逐个对应识别结果反复横跳没有跟踪ID或跟踪断裂接入ByteTrack并延长ID保留时间检测框闪烁严重置信度阈值低导致误检提高阈值增加尺寸过滤速度只有2FPS检测识别串行且输入太大降低imgsz并行化减少识别频率结尾做这个项目时我发现真正花时间的不是调模型而是把“检测-跟踪-识别”三块拼起来还要处理各种边界情况。踩过几次坑之后我现在的体会是动作识别不能在单帧上较劲要让模型看到足够多的上下文YOLOv8和MMAction2的配合已经是很稳的工程范式但你必须清楚每一条数据从摄像头到模型前的每一步发生了什么。这套源码我在自己的监控模拟场景里跑起来很稳定如果你也想做行人动作检测建议先从最简单的三件套入手一个轻量YOLOv8一个TSM识别器一个ByteTrack。跑通之后再慢慢迭代精度和速度你会发现剩下的问题都有迹可循。本文还有配套的精品资源点击获取