ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOv5吸烟检测实战:从权重选型到业务落地的避坑指南

YOLOv5吸烟检测实战:从权重选型到业务落地的避坑指南 简介这份资源面向计算机视觉学习者与行为识别方向的开发者提供基于YOLOv5-6.0训练完成的吸烟检测模型用于识别画面中的吸烟行为目标类别为smoke。包内包含YOLOv5m与YOLOv5s两个已训练权重在数千张吸烟数据上迭代得到准确率超过90%并附有PR曲线、loss曲线等训练过程记录便于评估模型表现与复现实验。压缩包共373个文件约128.03MB涵盖pt权重、py源码、yaml配置、jpg样本图、txt标注、png曲线图及csv训练日志等兼顾推理部署与二次训练需求。资源已有2392人学习下载适合希望快速搭建吸烟检测demo、对比不同模型精度或在此基础上迁移到其他行为识别任务的中高级读者参考使用。1. 吸烟行为检测为什么选 YOLOv5从几千张图到 90% 准确率的落地路径吸烟检测这个需求真正做起来比想象中麻烦。烟雾本身是半透明、边界模糊的烟头又小人手夹烟的姿态在不同角度下差异极大用传统图像处理或者颜色阈值去框误报率能高到没法看。这份yolov5-6.0-smoking_detect.zip走的是另一条路用几千张吸烟场景图训练 YOLOv5目标类别只设一个smoke交付了 YOLOv5m 和 YOLOv5s 两个权重准确率标称 90% 以上还附带了 PR 曲线、loss 曲线和results.csv训练日志。它解决的不是能不能识别烟这种演示级问题而是给做安防、工地、加油站、校园禁烟场景的从业者一个可以直接接进业务管线的检测底座。适合谁手上有摄像头流、想快速验证吸烟行为检测可行性、又不打算从零标注和训练的人。下面我按资源里有什么 → 怎么跑起来 → 怎么接自己的数据 → 坑在哪的顺序拆一遍。2. 拆开压缩包yolov5-6.0 目录结构与两个权重的选型逻辑2.1 从文件清单看这份资源到底交付了什么拿到压缩包先别急着跑先看清楚里面是什么。从文件清单能读出几个关键信息events.out.tfevents.1652415975.yuhui.7369.0和events.out.tfevents.1652411824.yuhui.6446.0是 TensorBoard 的事件文件说明训练过程被完整记录下来了你可以直接起 TensorBoard 看曲线不用自己重训一遍才知道收敛情况。results.csv是 YOLOv5 每次 epoch 结束后追加的训练指标表包含train/box_loss、train/obj_loss、metrics/mAP_0.5、metrics/mAP_0.5:0.95这些列是判断模型有没有过拟合、有没有欠训练的第一手依据。Dockerfile和.dockerignore的存在说明作者考虑过容器化部署这对要上服务器或者边缘盒子的场景很实用。.gitattributes、.gitignore、yolov5-6.0.iml是工程配置.iml是 IntelliJ/PyCharm 的项目文件说明作者是在 PyCharm 里开发的你导入项目时 IDE 能直接识别结构。真正要关注的是权重文件。摘要里明确说有 YOLOv5m 和 YOLOv5s 两个训练好的模型类别是smoke。这两个不是随便给的是两种取舍模型参数量级推理速度精度表现适用场景YOLOv5s小快略低边缘设备、多路视频、实时性优先YOLOv5m中中等更高服务器 GPU、单路高清、精度优先选型逻辑很直接如果你要在树莓派 5 或者 Jetson 这类设备上跑先上 YOLOv5s帧率撑得住再考虑换 m如果是机房服务器接几路 RTSP直接 YOLOv5m把 mAP 拉满。别一上来就用 m 去压边缘设备推理延迟会把整个管线拖垮。2.2 环境准备conda 建环境与依赖安装YOLOv5-6.0 这个版本对 PyTorch 和 Python 版本有要求用 conda 隔离环境是最省事的做法避免和你机器上其他项目的 torch 版本打架。# 创建独立环境python 版本建议 3.86.0 版本对 3.9 兼容性偶有问题 conda create -n smoking python3.8 -y conda activate smoking # 安装 PyTorch按你的 CUDA 版本选这里以 CUDA 11.3 为例 pip install torch1.10.0cu113 torchvision0.11.1cu113 -f https://download.pytorch.org/whl/torch_stable.html # 安装 YOLOv5 依赖进到解压后的 yolov5-6.0 目录 cd yolov5-6.0 pip install -r requirements.txt参数说明python3.8是稳妥选择YOLOv5-6.0 的requirements.txt里锁定的 numpy、opencv 版本在 3.8 上验证最充分。torch 版本必须和 CUDA 驱动匹配装完用python -c import torch; print(torch.cuda.is_available())验证返回True才算 GPU 可用。如果返回False先查驱动版本nvidia-smi再回退到对应 CUDA 的 torch 轮子别硬装 CPU 版然后抱怨推理慢。2.3 用训练好的权重直接推理环境好了先拿现成权重跑一张图确认模型能加载、能出框再谈别的。# 用 YOLOv5s 权重推理单张图片--conf 是置信度阈值 python detect.py \ --weights weights/smoke_s.pt \ --source test_imgs/smoking_test.jpg \ --conf 0.4 \ --img-size 640 \ --device 0逻辑说明--weights指向训练好的smoke权重路径按你实际解压位置改--source可以是单图、文件夹、视频文件甚至0本地摄像头--conf 0.4是置信度阈值吸烟检测里这个值很关键调低了误报多调高了漏检多后面避坑章节细说--img-size 640要和训练时的输入尺寸一致训练用 640 推理也用 640否则精度会掉--device 0指定第一块 GPU没有 GPU 就写cpu。跑完结果默认存在runs/detect/exp/下打开图看框的位置和置信度如果烟头、手部夹烟姿态都能框住说明权重是好的。3. 把模型接进自己的业务从 results.csv 读训练质量到自定义推理3.1 用 results.csv 和 PR 曲线判断模型能不能用很多人拿到权重直接跑跑通了就上线这是血泪经验的来源。先花十分钟看训练日志能避开后面一堆玄学问题。results.csv用 pandas 读进来画一下 mAP 和 loss 的走势import pandas as pd import matplotlib.pyplot as plt # 读训练日志列名里带斜杠的字段是 YOLOv5 的标准输出 df pd.read_csv(results.csv) df.columns df.columns.str.strip() # 列名可能带空格先清理 fig, axes plt.subplots(1, 2, figsize(12, 4)) # 左图mAP 走势看是否收敛、有没有过拟合 axes[0].plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) axes[0].plot(df[epoch], df[metrics/mAP_0.5:0.95], labelmAP0.5:0.95) axes[0].set_xlabel(epoch); axes[0].set_ylabel(mAP); axes[0].legend() # 右图box_loss 和 obj_loss看定位和置信度是否还在降 axes[1].plot(df[epoch], df[train/box_loss], labelbox_loss) axes[1].plot(df[epoch], df[train/obj_loss], labelobj_loss) axes[1].set_xlabel(epoch); axes[1].set_ylabel(loss); axes[1].legend() plt.tight_layout(); plt.savefig(train_curve.png)逻辑说明metrics/mAP_0.5是 IoU 阈值 0.5 下的平均精度吸烟检测里这个指标到 0.9 以上说明框得比较准metrics/mAP_0.5:0.95更严格通常低不少别拿它和 0.5 的数值直接比。看曲线重点看两件事mAP 是不是在后期还在涨没收敛就还得训train loss 一直降但验证 mAP 不涨过拟合得加数据或加正则。PR 曲线文件一般在训练输出目录里PR 曲线越靠右上角越好曲线下的面积就是 AP单类别smoke的 AP 就是模型对这个类的综合表现。3.2 自定义推理脚本批量处理视频流并落盘detect.py适合验证接业务得自己写脚本方便加日志、加告警、加存证。下面这个脚本读视频、逐帧推理、把有吸烟的帧存下来import cv2 import torch from pathlib import Path # 加载训练好的权重map_location 保证没 GPU 时也能跑 model torch.hub.load(ultralytics/yolov5, custom, pathweights/smoke_m.pt, force_reloadFalse) model.conf 0.45 # 置信度阈值 model.iou 0.5 # NMS 的 IoU 阈值 model.classes [0] # 只保留 smoke 类类别索引按 data.yaml 来 cap cv2.VideoCapture(rtsp_or_video_path.mp4) save_dir Path(smoke_frames); save_dir.mkdir(exist_okTrue) frame_id 0 while cap.isOpened(): ret, frame cap.read() if not ret: break frame_id 1 # 每 5 帧推理一次降低算力压力吸烟是持续行为不用逐帧 if frame_id % 5 ! 0: continue results model(frame) det results.pandas().xyxy[0] # 转成 DataFrame方便判断 if len(det) 0: # 有检测框就存图文件名带帧号便于回溯 cv2.imwrite(str(save_dir / fframe_{frame_id}.jpg), frame) print(fframe {frame_id}: {len(det)} smoke detected) cap.release()逻辑说明torch.hub.load的custom模式加载本地权重force_reloadFalse避免每次重下model.conf和model.iou是推理期可调参数比改命令行方便model.classes [0]只保留smoke类如果你的data.yaml里 smoke 不是第 0 类改成对应索引。抽帧推理frame_id % 5是实战常用做法吸烟是持续几秒的行为没必要每帧都算省下来的算力可以多接几路。存图而不是存视频是为了后续做告警证据链文件名带帧号方便定位原始时间点。3.3 用 TensorBoard 看 events 文件里的训练细节压缩包里那两个events.out.tfevents文件别浪费起个 TensorBoard 就能看到作者训练时的完整曲线包括学习率、各类 loss 分量# 指向 events 文件所在目录不是文件本身 tensorboard --logdir ./ --port 6006浏览器打开localhost:6006能看到train/box_loss、train/cls_loss、train/obj_loss三条 loss 曲线以及metrics/precision、metrics/recall、metrics/mAP_0.5。重点看 precision 和 recall 的平衡吸烟检测里 recall 低意味着漏检有人抽烟没抓到precision 低意味着误报没抽烟被框成烟。如果 recall 明显低于 precision说明模型偏保守可以把推理时的conf调低一点换 recall反过来就调高conf。这个权衡没有标准答案取决于你的业务是宁可错杀还是宁可放过。4. 避坑与排查吸烟检测落地时最容易翻车的五个点4.1 现象模型在测试图上框得好接摄像头全是误报原因训练数据是静态图摄像头画面有运动模糊、光照变化、背景干扰域差异导致模型把相似纹理比如白色笔、反光、手指误判成烟。解决先别改模型把摄像头实际画面截几十张混进训练集做一轮小学习率微调--weights smoke_m.pt --epochs 30 --lr0 0.001让模型见见真实场景。如果误报集中在某个固定区域比如某个反光点在推理脚本里加 ROI 裁剪把该区域排除掉比重新训练快得多。4.2 现象置信度阈值 0.25 时框一堆调到 0.7 又漏检严重原因smoke是单类别模型输出的置信度分布和 COCO 多类别不一样0.25 这个默认值对吸烟检测偏低。而且烟头小目标本身置信度就上不去。解决用验证集跑一遍画出不同conf下的 precision-recall 曲线找 F1 最大的点。实操里我一般从 0.4 起步按业务容忍度上下调 0.05。别迷信某个固定值每换一批数据都要重新标定。4.3 现象torch.hub.load报网络错误或下载超时原因torch.hub.load(ultralytics/yolov5, ...)默认会去拉 GitHub 上的仓库代码内网或断网环境直接挂。解决把path指向本地权重的同时确保当前工作目录就是解压出来的yolov5-6.0或者用sourcelocal参数强制走本地。更稳的做法是直接import本地models.experimental绕开 hub 的下载逻辑。4.4 现象推理时显存爆了报 CUDA out of memory原因--img-size设太大比如 1280或者批量推理时 batch 太大YOLOv5m 在 640 输入下单张约 1.5G 显存1280 直接翻几倍。解决推理阶段--img-size保持和训练一致大概率是 640别为了看得更清盲目调大批量处理时把 batch 设成 1 或 2用抽帧换吞吐。如果还爆换 YOLOv5s 权重参数量小一半。4.5 现象results.csv里 mAP 很高但实际用起来感觉没那么准原因mAP 是在验证集上算的验证集和训练集同分布如果验证集里正样本占比高、场景单一mAP 会虚高。而且 mAP 是框的精度不直接等于业务上的检出率。解决自己另建一个脏测试集故意混入负样本没吸烟的画面和困难样本遮挡、暗光在这个集上统计误报率和漏报率这两个数才是业务指标。别拿训练日志里的 mAP 当验收标准。5. 进阶技巧把吸烟检测从能跑推到敢上线模型跑通只是起点真正上线要解决的是稳定性和可维护性。第一个技巧是权重版本管理smoke_s.pt和smoke_m.pt别直接覆盖按smoke_s_v1_202405.pt这种命名存推理脚本里权重路径走配置换模型不用改代码。第二个技巧是推理结果结构化别只存图把每帧的[frame_id, timestamp, bbox, conf]写进 SQLite 或 CSV后面做告警去重、行为时长统计都靠这个。吸烟是持续行为单帧检出不算数连续 N 帧比如 15 帧约 0.5 秒都检出才触发告警能砍掉大量瞬时误报。# 连续帧确认逻辑避免单帧误报触发告警 from collections import deque hit_buffer deque(maxlen15) # 滑动窗口15 帧 ALERT_THRESHOLD 10 # 窗口内至少 10 帧检出才告警 def check_alert(det_count): hit_buffer.append(1 if det_count 0 else 0) if sum(hit_buffer) ALERT_THRESHOLD: return True return False参数说明maxlen15是窗口大小按你的抽帧频率算如果 5 帧抽 1 帧、视频 25fps15 帧窗口约覆盖 3 秒ALERT_THRESHOLD10是触发阈值调高更保守、误报更少但可能漏掉短时吸烟调低更灵敏但误报多。这个逻辑我一般会配合业务侧的告警冷却时间一起用同一个人 30 秒内只报一次避免刷屏。第三个技巧是验证方法别只用作者给的测试图自己录一段包含吸烟-不吸烟-吸烟交替的视频跑完整管线人工数一遍检出和误报算出实际 precision 和 recall和results.csv里的数对比。差距大说明域差异严重得补数据微调。从那以后我每次拿到别人训好的权重都强制走一遍脏测试集 连续帧确认 实际视频回放这三步再决定要不要接进生产。希望帮到你。本文还有配套的精品资源点击获取
返回列表