基于YOLOv5的行为识别实战:从检测框到动作语义的落地指南
发布时间:2026/10/2 2:36:54来源:尧图网络
简介这份资源面向计算机视觉初学者与行为识别方向的开发者提供将YOLOv5目标检测模型应用于人体行为分析的完整项目代码与说明文档。包内共6个文件以2个Python脚本detect.py、train.py为核心配合data.yaml数据集配置、基于YOLOv5的行为识别.doc原理说明、README.md使用指引及LICENSE授权文件压缩包约1.6MB结构精简便于快速上手。项目围绕YOLOv5的网络结构、Anchor机制、Mosaic数据增强等特性展开并延伸至特征提取、轨迹建模与LSTM/GRU行为分类的完整流程可帮助读者理解从视频帧检测到行为识别的技术链路。目前已有572人学习下载适合希望以轻量代码切入智能监控、安全预警等实时视频分析场景的读者参考实践。1. 基于 YOLOv5 的行为识别从检测框到动作语义的那一层窗户纸很多人第一次听到「基于 YOLOv5 的行为识别」脑子里浮现的是把视频丢进模型直接吐出「打架」「摔倒」「抽烟」这类标签。真上手才发现YOLOv5 本身只做目标检测它输出的是人、车、物体的边界框和类别压根不认识「行为」。所谓行为识别是在检测框的基础上再叠一层时序或姿态逻辑把「有人」升级成「这个人在做什么」。我做过几个工地安全帽佩戴、跌倒检测、区域入侵的项目核心思路都是YOLOv5 负责稳定地框出人后面的行为判定交给轻量规则或第二个小模型。这套方案适合算力有限、要落地到边缘盒子或树莓派5上的场景不适合追求学术 SOTA 的纯视频分类任务。下面把我踩过的路拆开讲从环境配置到训练自己的数据集再到后处理和部署尽量让新手能照着跑通熟手能看到参数边界。2. 环境配置与 YOLOv5 源码结构conda 里那点事2.1 用 conda 把 YOLOv5 环境配到不翻车YOLOv5 对环境不算挑剔但版本对不上就是各种玄学报错。我一般用 conda 建一个干净环境Python 锁 3.8 或 3.9PyTorch 按 CUDA 版本走。下面这套命令在 Ubuntu 20.04 和 Windows WSL2 上都跑通过树莓派5上则要换成 ARM 版 PyTorch后面部署章会提。# 创建 conda 环境Python 版本别追新3.8/3.9 最稳 conda create -n yolov5 python3.9 -y conda activate yolov5 # 安装 PyTorch以 CUDA 11.3 为例其他版本去官网查对应命令 pip install torch1.12.1cu113 torchvision0.13.1cu113 --extra-index-url https://download.pytorch.org/whl/cu113 # 克隆 YOLOv5 源码注意这里不写具体仓库地址按官方仓库操作即可 git clone yolov5官方仓库地址 cd yolov5 # 安装依赖requirements.txt 里有些包版本会冲突建议先装基础再补 pip install -r requirements.txt逻辑说明先隔离环境避免和系统里其他 PyTorch 项目打架。PyTorch 版本和 CUDA 驱动必须匹配否则torch.cuda.is_available()返回 False训练直接掉到 CPU 上速度差几十倍。参数上python3.9是甜点版本3.10 以上有些依赖轮子还没跟上。装完依赖后跑一句python -c import torch; print(torch.cuda.is_available())输出 True 才算过关。2.2 源码目录里哪些文件你非改不可YOLOv5 源码结构清晰但新手容易在几个文件里迷路。我按改动频率排个序文件/目录作用改动频率data/数据集配置 yaml、超参数 yaml高models/网络结构 yaml、common 模块中utils/数据加载、损失、指标、绘图中train.py训练入口参数都在 argparse 里低detect.py推理入口后处理逻辑在这中runs/训练输出权重和日志不手动改重点看data/coco128.yaml这种模板你要训练自己的数据集就是照它写一份。models/yolov5s.yaml决定网络宽度和深度树莓派5上建议用 yolov5n 或 yolov5s别上 m/l。utils/general.py里的non_max_suppression是后处理核心行为识别里如果要做框的时序关联得从这里拿输出。提示不要一上来就改网络结构先把默认 yolov5s 跑通再根据行为识别的需求调。3. 训练自己的数据集从标注到超参数调优3.1 行为识别数据集怎么标才不白干行为识别的数据标注和纯目标检测不一样。纯检测只标「人」行为识别要标出「人在做什么」对应的状态。我的做法是如果行为靠姿态区分跌倒、下蹲就标人体框加关键点如果靠场景规则进入禁区、未戴安全帽就标人框加区域多边形。YOLOv5 本身只吃矩形框所以关键点或区域信息要另存一份 json后处理时和检测框做匹配。标注工具用 labelImg 或 CVAT 都行导出 YOLO 格式每张图一个 txt每行class_id x_center y_center width height坐标归一化到 0~1。行为类别不要设太多我一般控制在 5~10 类类间差异要肉眼可辨。比如「跌倒」和「躺下」在单帧里几乎一样就得靠时序单帧标注解决不了。# 检查标注文件是否规范的小脚本 import os def check_labels(label_dir, img_dir): issues [] for txt in os.listdir(label_dir): if not txt.endswith(.txt): continue img_name txt.replace(.txt, .jpg) if not os.path.exists(os.path.join(img_dir, img_name)): issues.append(f图片缺失: {img_name}) continue with open(os.path.join(label_dir, txt)) as f: for line in f: parts line.strip().split() if len(parts) ! 5: issues.append(f格式错误: {txt} - {line}) continue cls, x, y, w, h parts vals [float(x), float(y), float(w), float(h)] if any(v 0 or v 1 for v in vals): issues.append(f坐标越界: {txt} - {line}) return issues # 用法传入 labels 和 images 目录 # print(check_labels(labels/train, images/train))逻辑说明这个脚本不依赖 YOLOv5纯标准库用来在训练前扫一遍标注。参数上x_center和width是相对整图宽度的比例y_center和height相对高度。常见错误是标的时候用了绝对像素或者类别 id 从 1 开始YOLO 要求从 0 开始。跑一遍能省下训练到一半才发现标签错的血泪时间。3.2 写数据集 yaml 和选超参数数据集 yaml 告诉 YOLOv5 去哪找图、有哪些类。我一般这样写# data/behavior.yaml path: ../datasets/behavior # 数据集根目录 train: images/train val: images/val test: images/test nc: 6 # 类别数按实际改 names: [person, fall, sit, stand, wave, run] # 类别名逻辑说明path是根train/val/test是相对路径。nc必须和 names 长度一致否则训练时分类头维度对不上报错很直接。names 顺序要和标注时 class_id 对应错一个类整个模型语义就乱了。超参数在data/hyp.scratch.yaml里。行为识别场景我常调这几个参数默认值建议调整原因lr00.010.001~0.01小数据集调小防震荡batch-size168~32看显存树莓派5上只能 1~4epochs300100~300行为数据少100 够收敛img-size640416~640边缘设备降到 416anchor自动可重聚类行为框偏长条时重算训练命令python train.py --data data/behavior.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --batch-size 16 --epochs 150 --img 640 --device 0参数说明--weights用预训练权重行为识别数据少从头训基本废。--device 0指第一块 GPUCPU 训练去掉这参数但会慢到怀疑人生。--img 640是输入分辨率行为识别里小目标多就保持 640只检测人框可以降到 416。3.3 训练过程看什么指标训练日志里重点看三个box_loss、obj_loss、cls_loss。行为识别如果类别不平衡cls_loss会降得慢。验证集看mAP0.5和mAP0.5:0.95行为类别少的话 mAP 容易虚高要单独看每个类的 AP。我习惯用val.py跑一遍输出混淆矩阵看「跌倒」有没有被误判成「躺下」。python val.py --data data/behavior.yaml --weights runs/train/exp/weights/best.pt --img 640 --task val如果某个类 AP 一直上不去先查标注量够不够再看该类在训练集里是不是被其他类框重叠严重。行为识别里「人」框和「行为」框经常重叠NMS 阈值要适当调高否则行为框被吞。4. 后处理与行为判定YOLOv5 输出之后的那一步4.1 从检测框到行为标签的三种常见做法YOLOv5 推理输出是[x1, y1, x2, y2, conf, cls]的列表。行为判定我常用三种第一种规则法。检测到人框后算框的宽高比、中心点位置、与区域多边形的交并比。比如跌倒宽高比从直立时的 0.4 突变到 1.2 以上且中心点下移。这种方法零训练成本适合固定摄像头。第二种姿态法。人框里再跑一个轻量姿态模型如 MoveNet拿关键点算关节角度。下蹲、举手、跌倒靠角度阈值区分。比规则稳但多一个模型树莓派5上要算力。第三种时序分类法。把连续 N 帧的人框裁剪出来缩放到固定大小送进一个小 CNN 或 LSTM 做分类。适合「走路」「跑步」「打架」这种靠运动模式区分的。代价是要缓存帧延迟高。我一般混合用规则做一级过滤姿态做二级确认时序只在关键行为上开。4.2 后处理代码里必须改的几个参数YOLOv5 的detect.py里non_max_suppression有几个参数直接影响行为判定# utils/general.py 里的 non_max_suppression 调用处 pred non_max_suppression( pred, conf_thres0.25, # 置信度阈值行为识别建议 0.3~0.5 iou_thres0.45, # NMS IoU 阈值人框重叠多时调到 0.5~0.6 classesNone, # 只保留特定类如 [0] 只留人 agnosticFalse, # 是否跨类 NMS行为识别一般 False max_det100 # 每图最大检测数人多场景调大 )逻辑说明conf_thres太低会引入大量误检行为判定跟着乱太高会漏人行为直接丢失。iou_thres在人群密集时调高否则相邻人被合并成一个框行为归属就错了。classes[0]只留人类能减少后处理负担但如果你行为类别本身也当检测类训就别过滤。参数怎么定拿一段典型视频跑detect.py --save-txt看输出框数量和实际人数差多少。差太多就调conf_thres和iou_thres直到框数稳定。4.3 把行为判定写成可复用的后处理模块我习惯把行为逻辑从detect.py里抽出来单独一个behavior.py输入是检测框列表和帧时间戳输出是行为事件。这样换模型、换规则都不用动 YOLOv5 源码。# behavior.py 简化示例 import numpy as np class BehaviorAnalyzer: def __init__(self, fall_ratio_thres1.2, history_len5): self.fall_ratio_thres fall_ratio_thres self.history [] # 缓存最近几帧的人框 self.history_len history_len def update(self, boxes, timestamp): # boxes: [[x1,y1,x2,y2,conf,cls], ...] events [] persons [b for b in boxes if int(b[5]) 0] # 只取人类 for p in persons: w p[2] - p[0] h p[3] - p[1] ratio w / (h 1e-6) if ratio self.fall_ratio_thres: events.append((fall_suspect, p, timestamp)) self.history.append(persons) if len(self.history) self.history_len: self.history.pop(0) return events逻辑说明fall_ratio_thres是宽高比阈值直立人约 0.3~0.5跌倒后接近 1 以上。history_len缓存帧数用于后续加时序确认比如连续 3 帧 ratio 都超阈值才报跌倒减少单帧误报。参数上阈值因摄像头角度而异俯拍和侧拍差别大要拿现场视频标定。注意单帧宽高比判跌倒误报率不低蹲下、弯腰都可能触发务必加时序确认或姿态二次判断。5. 部署到树莓派5与边缘设备算力不够怎么砍5.1 树莓派5上跑 YOLOv5 的现实预期树莓派5比4代强不少但跑 YOLOv5s 原始 PyTorch 模型帧率也就 2~5 FPS行为识别要连续帧基本不够用。我的做法是三步砍换模型、转格式、降分辨率。换模型用 yolov5n参数量约 1.9M比 s 小一半多。行为识别如果只检测人框n 够用。转格式PyTorch - ONNX - NCNN 或 TFLite。NCNN 在 ARM 上优化好树莓派5上 yolov5n 能到 10~15 FPS。降分辨率输入从 640 降到 320 或 416帧率翻倍小目标会丢但人框通常够大。# 导出 ONNX python export.py --weights yolov5n.pt --include onnx --img 416 --opset 12 # 转 NCNN需装 ncnn 工具链 python export.py --weights yolov5n.pt --include ncnn --img 416参数说明--opset 12兼容性好别追高。--img 416要和训练时一致或成比例否则精度掉。导出后拿benchmark脚本测帧率别只看理论值。5.2 部署时的内存和线程调优树莓派5内存 4GB/8GBYOLOv5n 推理时内存占用约 300~500MB加上行为缓存和视频解码4GB 版要省着用。我一般设调优项做法效果线程数torch.set_num_threads(4)避免线程争抢输入队列视频解码丢帧只处理关键帧降延迟行为缓存只存人框坐标不存图省内存模型量化INT8 量化再提速 30%行为识别在边缘设备上我建议把「检测」和「行为判定」分线程检测线程跑 YOLOv5行为线程拿框做规则/姿态中间用队列传。这样检测帧率不受行为逻辑拖累。6. 避坑与排查行为识别落地时最容易翻车的五件事6.1 现象训练 mAP 很高实际视频误报一堆原因训练集和现场分布不一致。训练图多是正面、光照好现场是俯拍、逆光、遮挡。YOLOv5 对域偏移很敏感。解决拿现场视频抽帧标 200~500 张加入训练集做增量训练。或者推理时加亮度均衡、直方图匹配。别指望一个 COCO 预训练权重打天下。6.2 现象行为判定延迟高视频卡成幻灯片原因每帧都跑检测加行为逻辑树莓派5扛不住。或者行为缓存太大内存换页。解决检测降频比如每 3 帧检一次中间帧用跟踪算法如 ByteTrack补框。行为逻辑只在有人的帧跑。缓存只存坐标和 ID不存图像。6.3 现象人一多行为标签乱串原因NMS 把相邻人框合并或者行为判定没绑定人 IDA 的行为算到 B 头上。解决调高iou_thres到 0.5~0.6加跟踪器给每个人分配 ID行为事件绑定 ID 而不是框坐标。跟踪器用轻量的别上重模型。6.4 现象导出 ONNX 后精度掉一大截原因导出时--img和训练不一致或者 opset 版本导致某些算子行为变化。还有动态轴设置错。解决导出用和训练相同的 img sizeopset 用 11 或 12。导出后拿同一张图对比 PyTorch 和 ONNX 输出差异大就查算子。NCNN 转换时注意--simplify选项。6.5 现象树莓派5上跑几小时就死机原因散热不够CPU 降频或者内存泄漏行为缓存没清。解决加散热片或小风扇限制线程数别跑满。行为缓存设上限用collections.deque(maxlenN)。定期重启推理进程别让它跑几天。7. 一个具体技巧用「检测框时序差分」低成本区分走和跑行为识别里「走」和「跑」单帧几乎一样但时序差分很便宜。我的做法跟踪每个人框的中心点算连续帧的位移速度超过阈值判跑否则判走。不需要额外模型树莓派5上零负担。# 基于中心点位移的速度判定 from collections import deque class SpeedClassifier: def __init__(self, fps15, run_thres0.08): self.tracks {} # id - deque of (cx, cy) self.fps fps self.run_thres run_thres # 归一化位移阈值按画面宽度比例 def update(self, track_id, cx, cy): if track_id not in self.tracks: self.tracks[track_id] deque(maxlen5) self.tracks[track_id].append((cx, cy)) if len(self.tracks[track_id]) 3: return unknown (x1, y1), (x2, y2) self.tracks[track_id][0], self.tracks[track_id][-1] dist ((x2 - x1) ** 2 (y2 - y1) ** 2) ** 0.5 frames len(self.tracks[track_id]) - 1 speed dist / frames # 每帧归一化位移 return run if speed self.run_thres else walk逻辑说明run_thres是核心参数按画面宽度归一化后走约 0.01~0.03跑约 0.08~0.15具体拿现场视频标。deque(maxlen5)限制缓存防内存涨。跟踪 ID 从 ByteTrack 或简单 IoU 匹配来。这个技巧的边界摄像头视角变化大时阈值要重标人群遮挡时 ID 切换会导致速度跳变要加平滑。我自己的习惯是每接一个新场景先拿手机拍 5 分钟现场视频跑一遍检测加这个速度分类看阈值合不合适再决定要不要上姿态模型。行为识别没有一劳永逸的参数现场标定比调模型重要。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网