ARTICLE DETAIL

资讯详情

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

YOLOv5吸烟检测实战:从数据标注到部署的完整指南

YOLOv5吸烟检测实战:从数据标注到部署的完整指南 简介本资源为基于YOLOv5-6.0训练完成的吸烟行为检测模型包面向计算机视觉学习者、行为识别方向的研究人员及需要落地吸烟检测功能的开发者。包内提供YOLOv5m与yolov5s两个已训练权重目标类别为smoke在数千张吸烟数据上训练准确率超过90%并附有PR曲线、loss曲线等训练过程记录便于评估模型表现与复现实验。资源共373个文件以jpg图像、txt标注、yaml配置、py脚本为主另含pt权重、png曲线图、md说明及Dockerfile等部署文件压缩包约128.03MB目录结构完整覆盖数据、训练与推理环节。目前已有2392人学习下载适合希望快速获得可用吸烟检测模型、对照曲线分析训练效果或在此基础上继续微调的中高级视觉开发者。1. 吸烟检测为什么值得用 YOLOv5 单独做一遍厂区、加油站、化工厂这类场景里吸烟检测不是识别一个人那么简单它要的是在监控画面里实时框出烟头、叼烟动作和烟雾并且把误报压到能接受的水平。YOLOv5 之所以在这个任务上被反复拿出来用是因为它单阶段、推理快、对小目标有一定容忍度而且 yolov5-6.0 这个版本结构稳定、生态成熟改数据集、调超参、导出部署都有现成路径。yolov5-6.0-smoking_detect.zip这类工程包本质就是把吸烟当成一个独立检测类别用 YOLOv5 走一遍从数据标注到训练再到推理的完整链路。它适合两类人一类是手里已经有摄像头和标注数据、想快速验证可行性的工程人员另一类是想拿一个真实小目标检测任务练手 YOLOv5 全流程的开发者。下面我按自己实际跑这类项目的顺序把选型、数据、训练、调参和踩坑讲清楚。2. 把吸烟检测拆成 YOLOv5 能吃的任务类别设计与数据准备2.1 为什么吸烟检测不能直接套用 COCO 的 person 类很多人第一反应是检测到人再判断有没有抽烟这条路在工程上很容易翻车。COCO 里没有 cigarette、smoke 这些类person 框只给你一个人的整体位置烟头在画面里可能只有十几个像素靠人体框去裁再分类等于把检测问题硬转成分类问题中间任何一步框偏了后面全错。更稳的做法是直接把吸烟相关目标定义成独立类别让 YOLOv5 在整图上做回归。常见做法是定义 2 到 3 个类smoking叼烟/手持烟的动作区域、cigarette烟头本身、smoke明显烟雾。如果数据量不大我一般先合并成一个smoking类跑通再考虑拆分。原因是类别越细小目标样本越稀疏YOLOv5 在 6.0 版本下对小目标的召回本来就吃数据拆太细会让 mAP 掉得很难看。选型上还要注意吸烟检测的负样本极其重要。工区里大量手靠近脸白色反光蒸汽都会被误判成烟所以数据里必须刻意塞入这些困难负样本否则模型上线后误报会让你怀疑人生。2.2 标注规范框到哪、留多少边距标注质量直接决定上限。我的习惯是smoking类框住嘴部到烟头的整体区域不要只框烟头也不要框整张脸cigarette类紧贴烟头外沿留 1 到 2 像素边距遮挡超过 70% 的目标直接标ignore或不标别硬标硬标会教坏模型。标注工具用 labelImg 或 CVAT 都行导出 YOLO 格式。YOLO 格式是每行class x_center y_center width height全部归一化到 0 到 1。这里有个高频错误有人把像素坐标直接写进去训练时 loss 不降排查半天才发现没归一化。2.3 目录结构与 data.yaml 的写法YOLOv5-6.0 对目录结构有约定我一般整理成这样smoking_detect/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml是训练入口写错一个路径就白跑# data.yaml train: ../smoking_detect/images/train # 训练集图片目录 val: ../smoking_detect/images/val # 验证集图片目录 nc: 1 # 类别数先跑通就写 1 names: [smoking] # 类别名顺序必须和标注里的 class id 对应逻辑说明train和val指向的是图片目录YOLOv5 会自动去找同级的labels目录所以 labels 路径不用写。nc必须等于names长度否则训练启动就报维度不匹配。参数上names的顺序就是标注文件里 class id 的顺序0 对应第一个名字错位会导致类别全乱。提示先用 50 到 100 张图跑一个 epoch确认能正常读数据、loss 有变化再上全量数据。这一步能省掉大量训练半天发现路径错的时间。3. 用 yolov5-6.0 训练吸烟检测模型命令、超参与断点续训3.1 环境搭建与依赖版本YOLOv5-6.0 对 PyTorch 和 CUDA 有版本要求我一般用 conda 隔离环境避免和系统里其他项目打架# 创建并激活环境 conda create -n smoking python3.8 -y conda activate smoking # 安装 PyTorch按自己 CUDA 版本选这里以 cu113 为例 pip install torch1.10.0cu113 torchvision0.11.1cu113 -f https://download.pytorch.org/whl/torch_stable.html # 安装 yolov5-6.0 依赖 cd yolov5-6.0 pip install -r requirements.txt逻辑说明Python 3.8 是 6.0 版本验证过的组合太新容易在torch和numpy上出兼容问题。requirements.txt里锁了numpy、opencv-python等版本别手动升级。参数上CUDA 版本要和驱动匹配nvidia-smi看右上角支持的 CUDA 版本装高了会报no kernel image。3.2 训练命令与关键超参跑通数据后训练命令我一般这样写python train.py \ --data ../smoking_detect/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 150 \ --hyp data/hyps/hyp.scratch-low.yaml \ --name smoking_v1 \ --cache逻辑说明--weights yolov5s.pt用官方预训练权重做迁移学习比从头训收敛快得多小数据集尤其明显。--img 640是输入分辨率烟头小的话可以提到 960但显存和速度要权衡。--cache把图片缓存到内存数据量不大时能明显加速。参数上重点说三个--batch-size显存够就往上加16 是 8G 显存的稳妥值太小会让 BN 统计不稳--hyp6.0 提供 low/mid/high 三档小数据集用 low增强弱一点避免过拟合--epochs150 是起点看results.csv里 mAP 是否还在涨涨就继续。3.3 断点续训与多卡训练中断是常事6.0 支持从last.pt续python train.py \ --data ../smoking_detect/data.yaml \ --weights runs/train/smoking_v1/weights/last.pt \ --resume逻辑说明--resume会读取last.pt里保存的优化器状态和 epoch接着跑不用重头来。注意--resume时其他参数会被忽略以 checkpoint 里存的为准所以别指望续训时改 batch size。多卡用--device 0,1但 6.0 的多卡是 DataParallelbatch 会均分小数据集不一定划算我一般单卡跑。3.4 训练过程看什么指标runs/train/smoking_v1/下有results.csv和results.png。重点看metrics/mAP_0.5整体检测能力吸烟检测一般能到 0.8 以上算可用metrics/mAP_0.5:0.95更严格小目标任务这个值通常偏低别慌train/box_loss和val/box_loss如果 train 一直降、val 开始涨就是过拟合该早停或加数据。注意验证集里一定要有困难负样本否则 mAP 虚高上线后误报爆炸。我吃过这个亏验证集全是干净正样本指标好看实际一跑全是误检。4. 吸烟检测的推理、导出与部署前验证4.1 单图与批量推理训练完先本地验证别急着上设备# 单张图 python detect.py \ --weights runs/train/smoking_v1/weights/best.pt \ --source ../test_imgs/smoke1.jpg \ --img 640 \ --conf-thres 0.4 \ --iou-thres 0.45 # 整个目录 python detect.py \ --weights runs/train/smoking_v1/weights/best.pt \ --source ../test_imgs/ \ --save-txt逻辑说明--conf-thres是置信度阈值吸烟检测我一般从 0.4 起调太低误报多太高漏检。--iou-thres控制 NMS 合并重叠目标多时调低。--save-txt会把框存成 YOLO 格式方便后续统计。参数上--img要和训练时一致训练 640 推理 960 会有尺度偏差虽然 6.0 会自适应但一致性更好。4.2 导出 ONNX 与 TensorRT部署到边缘设备前通常先导出# 导出 ONNX python export.py \ --weights runs/train/smoking_v1/weights/best.pt \ --include onnx \ --img 640 \ --batch-size 1 # 导出 TensorRT需要 GPU 环境 python export.py \ --weights runs/train/smoking_v1/weights/best.pt \ --include engine \ --img 640 \ --batch-size 1 \ --device 0逻辑说明ONNX 通用性好TensorRT 在 NVIDIA 设备上快很多。--batch-size 1是边缘部署常用值动态 batch 要额外指定--dynamic。导出后务必用val.py在 ONNX 上再跑一遍验证确认精度没掉。参数上TensorRT 的--workspace默认 4G显存小就调低--half开 FP16 能提速但精度可能掉一点吸烟检测这种小目标要谨慎。4.3 部署前必须做的三件事第一用真实摄像头视频流跑一遍别只看图片。视频里运动模糊、光照变化会暴露很多问题。第二统计误报率连续跑几小时看每小时误报几次超过可接受阈值就回去补负样本。第三确认推理延迟边缘设备上单帧超过 100ms 就要考虑降分辨率或换更小的模型yolov5n。5. 吸烟检测训练与部署的避坑清单5.1 现象训练 loss 不降mAP 一直是 0原因最常见是标注格式错比如没归一化、class id 越界或者data.yaml里nc和实际类别数不一致。其次是图片和标签文件名对不上YOLOv5 是按文件名找标签的a.jpg必须对应a.txt。解决先用python utils/general.py里的检查逻辑或者自己写脚本遍历 labels确认每行 5 个值、都在 0 到 1 之间、class id 小于nc。文件名不一致就批量重命名。5.2 现象验证集 mAP 很高实际部署误报严重原因验证集和训练集同分布且缺少困难负样本。模型没学过手靠近脸白色反光这些干扰一到真实场景就乱框。解决从实际场景里截取误报帧标成背景不标任何目标加进训练集重新训练。负样本比例我一般控制在 1:3 到 1:5 之间太多会压制正样本召回。5.3 现象小烟头检测不到大目标正常原因YOLOv5 的 P3 特征图负责小目标但如果训练分辨率低、小目标样本少P3 学不好。另外 anchor 尺寸如果不匹配小目标回归也困难。解决提高--img到 960 或 1280增加小目标样本必要时用--anchor重新聚类 anchor。6.0 默认 anchor 是 COCO 的吸烟检测的小目标可能需要更小的 anchor。5.4 现象导出 ONNX 后精度下降明显原因导出时的预处理和后处理与 PyTorch 不一致比如归一化方式、NMS 实现差异。另外 FP16 导出会掉精度。解决导出后用val.py --weights best.onnx对比 mAP差距大就检查export.py里的--img和--batch-size是否和训练一致。FP16 先别开确认 FP32 没问题再试。5.5 现象边缘设备上推理速度慢原因模型太大用了 yolov5l 或 x或者没做 TensorRT 加速或者输入分辨率过高。解决换 yolov5n 或 yolov5s导出 TensorRT降--img到 416 或 320。吸烟检测如果场景固定、摄像头距离近320 往往够用。6. 把吸烟检测做稳的一个进阶习惯用困难样本挖掘持续迭代模型上线不是终点。我自己的习惯是部署后每周从实际视频里抽一批误报和漏检帧人工确认后加进训练集重新训练一版。这个循环跑上三四轮误报率通常能降一个数量级。具体做法是写个脚本把detect.py --save-txt输出的框和人工复核结果对比自动挑出置信度在 0.3 到 0.6 之间的模糊样本这些样本对模型提升最大。# 从检测结果里挑模糊样本供人工复核 import os def pick_hard_samples(txt_dir, low0.3, high0.6): hard [] for f in os.listdir(txt_dir): if not f.endswith(.txt): continue with open(os.path.join(txt_dir, f)) as fp: for line in fp: parts line.strip().split() if len(parts) 6: continue conf float(parts[5]) # 第6列是置信度 if low conf high: hard.append(f) break return hard if __name__ __main__: samples pick_hard_samples(../runs/detect/exp/labels) print(f待复核模糊样本数: {len(samples)})逻辑说明detect.py --save-txt存出的每行是class x y w h conf第 6 列是置信度。挑 0.3 到 0.6 之间的这些是模型拿不准的人工标一遍加进训练集比随机加样本有效得多。参数上low和high按自己模型的置信度分布调如果模型整体置信度偏低区间可以下移。另一个习惯是固定验证集。每次迭代都用同一批验证图这样 mAP 变化才有可比性。我见过有人每次随机切验证集指标忽高忽低根本没法判断模型是变好还是变差。最后说个血泪经验吸烟检测的标注一致性比数量重要。同一个人叼烟今天框大明天框小模型学出来就是抖的。标注前先定好规范找两个人交叉检查一批确认一致了再全量标。这个前期投入比后面反复调参省时间得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表