news 2026/9/8 11:16:08

YOLOv8+MMAction2行人动作识别:双阶段检测与识别实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv8+MMAction2行人动作识别:双阶段检测与识别实战

简介:一份结合YOLOv8目标检测与MMAction2时序模型的行人动作检测可运行源码,面向智能视频监控、行为分析等场景的计算机视觉开发者和研究人员,解决视频中行人定位与行为分类的联动问题。资源共11个文件,涵盖py算法源码、mp4演示视频、pth预训练权重、md说明文档、html可视化页面及配置文件等,压缩包约14KB,结构紧凑便于快速部署。源码完整演示了YOLOv8行人提取、MMAction2动作识别与结果融合的关键步骤,并针对Temporal Shift Module等预训练模型在小数据集上的选型做了说明;同时提供数据集预处理与划分、配置文件修改等实操指引,配合可运行脚本与README,可复现环境配置、模型训练、测试和推理的完整链路。目前已有122人学习使用,适合需要在真实监控场景中落地行人动作检测方案的开发者参考。 最近有朋友在做行人动作检测,一上来就问:能不能直接用YOLOv8把动作也分类出来?我一般会回一句:YOLOv8擅长框出目标,动作识别是另一个维度的事。与其硬改检测头,不如把它和MMAction2配合起来,检测负责定位,动作识别负责理解行为。这套组合在工程上很成熟,尤其适合“先找人、再看人在干嘛”的场景,比如安防监控、人机交互、零售行为分析。这次我把整套可运行源码的思路、配置、踩坑点都拆开讲,适合刚接触动作识别,或者想快速搭一套检测+识别pipeline的人。

1. 整体思路与双阶段方案选型

1.1 为什么不直接用单一模型做检测和分类

很多人第一次接触这个需求时,会想:YOLOv8已经能分类目标了,能不能把“走路、跑步、招手、摔倒”当作类别,直接在检测框里输出动作标签?理论上可以,但实际效果会很糟糕。动作识别强依赖时序上下文,单帧检测模型只能看到当前帧的姿态和空间位置,看不到“过去几秒这个人做了什么”。比如“摔倒”和“蹲下”在单帧画面上可能长得一模一样,只有结合连续几帧的变化趋势才能区分。

单阶段方案还有一个绕不开的问题:动作类别通常比目标类别更细,数据标注成本成倍增加。你要标“人”容易,标“这个人从第几帧开始举手,到第几帧放下”就麻烦得多。所以工程上更通用的做法是两阶段:先用目标检测模型把行人的位置框出来,再把连续多帧的检测框区域或骨骼关键点喂给时序模型做动作分类。这就是YOLOv8+MMAction2的典型分工。

1.2 YOLOv8负责“在哪”,MMAction2负责“在做什么”

这套方案里,YOLOv8的角色就是干净利落的目标检测器。它每帧输出行人的边界框和置信度,我用它过滤掉背景干扰,只保留“人”这个前景。MMAction2是OpenMMLab家族里的动作识别库,里面封装了多种时序模型,比如TSN、TSM、SlowFast,还有基于骨骼的ST-GCN。我这里选的是基于RGB帧序列的TSM(Temporal Shift Module),它在精度和速度之间比较均衡,普通GPU也能跑得动。

两者的连接方式也很简单:对视频流的每一帧跑YOLOv8,得到每个人的检测框后,把框内的图像区域按时间顺序截取下来,组成一个短片段,再交给MMAction2的模型判断动作类别。如果多人同时出现,需要先做目标跟踪,给每个人分配一个ID,再按ID组织各自的时序片段。否则识别结果会在多个人之间来回跳。

方案优势劣势
单帧检测模型直接分类流程简单、延迟低缺乏时序信息,混淆动作多
YOLOv8+单帧分类头复用检测框仍无法区分同姿不同动
YOLOv8+MMAction2时序识别利用连续帧,动作区分度高多一个时序模型,工程链路稍长

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 ID,MMAction2才能拿到“同一段时间里同一个人的连续画面”。这是我踩过比较深的一个坑:一开始没做跟踪,画面里两个人交叉走过,动作识别结果直接串台。

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,你得精确选择mmcv==2.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.updaterecognizer.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。跑通之后再慢慢迭代精度和速度,你会发现剩下的问题都有迹可循。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 11:15:05

Qt集成Tesseract OCR:Windows 64位编译与项目配置完整指南

简介:面向需要在Windows 64位环境下使用Qt进行OCR功能开发的工程师,这份编译好的Tesseract库可直接嵌入开发流程,免去从源码编译、依赖修补的繁琐过程。压缩包共916个文件、大小约39.32MB,其中包含546个头文件、72个DLL动态库、50…

作者头像 李华
网站建设 2026/9/8 11:13:54

S7-1200 PLC与MCGS触摸屏的自动售货机控制系统设计与联调实战

我刚做完一个自动售货机的联机项目,主控用的西门子S7-1200 PLC,上位显示用的昆仑通态MCGS7.7触摸屏,从硬件选型、程序框架到现场联调,整个过程走下来踩了不少坑,也攒了不少心得。这篇文章就把这套方案的完整实现过程拆…

作者头像 李华
网站建设 2026/9/8 11:13:40

AI视频广告实战指南:从脚本到成品的全流程制作方法

1. AI视频广告到底是什么,它和传统视频制作差在哪里 AI视频广告并不是一个模糊的概念,而是指“用生成式AI工具,从脚本、文案、画面、配音到剪辑,尽量用自动化方式完成一支广告视频”的完整流程。很多人一听到“AI一键生成”&#…

作者头像 李华
网站建设 2026/9/8 11:11:44

基于深度学习的舌象诊断系统实战:数据、模型与部署全解析

简介:这是一套基于深度学习的舌象诊断系统项目包,面向人工智能、深度学习方向的开发者与中医信息化研究者,适合用于学习CNN图像分类、医学影像处理及模型训练部署的完整流程。压缩包内共183个文件,以61张jpg舌象图像、54个py脚本和…

作者头像 李华
网站建设 2026/9/8 11:11:26

COMSOL多物理场耦合仿真:多孔介质两相流与物质传递建模实战

先交代一下背景。这个项目是做 COMSOL仿真建模 的朋友经常碰到的一类问题:既要算多孔介质里的两相流动,又要跟踪一种药剂(溶质)在液体里的扩散和传输,同时还不能忽略水池里水体自重产生的压力对流动的影响。听起来物…

作者头像 李华