基于YOLOv5的烟雾检测系统:训练权重+数据集+实时识别
简介基于YOLOv5的烟雾检测资源聚焦安全监控、火灾预警、智能巡检等应用场景面向深度学习开发者和相关领域工程师也适合有一定基础的学生作为项目参考能够帮助快速搭建一套烟雾识别系统。压缩包共包含两千个文件主要内容有三千六百八十八张烟雾图像、三千六百八十八个文本格式的边界框标注、三千六百八十七个XML格式目标标注同时携带三个训练好的YOLOv5权重模型并附有模型训练脚本、超参数配置、Docker部署文件和使用说明文档数据规模约为三百六十兆。目前已有两千三百四十八人学习使用模型基于多种光照、角度和背景条件下的烟雾数据进行训练能够较好区分烟雾与雾、灰尘等干扰物检测精度和实时性均有保障。借助这份资料使用者可以获得从数据标注、模型训练到实际部署的全流程参考既可直接加载权重进行实时视频流检测也可在自有数据集上开展微调或迁移学习为公共安全领域的烟雾预警项目提供扎实基础。 火灾预警这个方向我接触过不少项目真正落地价值最高的其实不是火焰检测而是经常被人忽略的烟雾检测。原因很简单火焰出现在画面里时火情往往已经烧开了烟雾是火灾早期最明确的可视信号抓住烟雾才有抢时间的价值。这篇文章要说的就是基于YOLOv5做一套烟雾检测方案项目里包含了训练好的模型权重和整理好的数据集拿过去就能对你的图片、视频流、摄像头做实时烟雾识别。无论你是做智慧消防、园区安防、森林防火方向的毕设还是想快速搭一个视觉预警原型这套方案都适合拿来复现。1. 烟雾检测的难点在哪里YOLOv5凭什么能做1.1 烟雾检测的真实应用场景我是做视觉检测出身的前前后后做了不少目标检测项目。如果要我排个序烟雾检测的折腾程度绝对排得上前三。为什么因为烟雾本身就不是个“规矩”的目标。火焰有明确的亮斑和辐射特征车辆行人有固定的形状纹理而烟雾既没有固定形状、边缘又糊成一片颜色变化跨度还特别大。但在实际工程里烟雾检测的需求反而非常刚需。森林防火的林区摄像头覆盖范围广、离目标远烟雾是火情最初的可视信号等监控画面里看到明火时往往已经烧成片了工矿园区、仓库厂房的环境复杂多变白天有阳光阴影晚上有灯光干扰烟雾的颜色和形态会跟着光线剧烈变化还有变电站、机房这类无人值守站点设备冒烟是最早的事故征兆比温度传感器和烟感探头响应得更快。除此之外还有大量本科毕设和课程项目都围绕烟雾检测展开YOLOv5这个量级的目标检测方案正好适合学生复现和二次开发。1.2 烟雾在图像里为什么难识别烟雾在图像里呈现出的特征和普通物体差异非常大我总结了几条无定形同一团烟雾在几十帧内可能完全变个形状检测框的回归目标在帧间剧烈变化模型很难学到稳定的“形状特征”。半透明烟雾的视觉强度由气溶胶粒子浓度和背景亮度共同决定。同一团烟对着深色背景和浅色背景表现完全不一样模型学的其实是“背景和烟雾叠加后的效果”。干扰多雾、霾、水蒸气、厨房油烟、汽车尾气、工地扬尘在图像上和早期淡烟雾的相似度极高没有一个检测器能在单帧上完全区分它们。多尺度几百米外的林火冒烟可能只占画面几十个像素而近处的烟可以充满整个画面目标检测模型最怕的就是这种尺度极端分布。理解了这四条你就明白为什么烟雾检测项目不能只看公开榜单上的精度最终要回到实际场景里的漏报率和误报率。1.3 为什么选YOLOv5而不是更“新”的模型其实现在可选的目标检测方案很多YOLOv8、RT-DETR也都出了而且速度精度都不差。我选择YOLOv5并不是因为它最新而是因为对一个要快速落地的烟雾检测项目来说它最合适工程生态最成熟训练、验证、推理、导出ONNX或TensorRT的链路全是现成的不用二次改造网络结构可以裁剪s、m、l、x四个尺寸覆盖了从边缘设备到服务器的全部场景烟雾检测这种单类别任务用s或m就足够对小目标相对友好PANet加多尺度输出配合Mosaic增强对远距离小烟雾有天然优势参考资料最多遇到问题搜索一圈基本都能解决对做毕设的同学尤其友好。YOLOv5的四个版本我也整理了一个对比方便你选型模型版本参数量推理速度精度表现适用场景YOLOv5s7.2M快中实时视频流、边缘设备YOLOv5m21.2M中中高常规服务器部署YOLOv5l46.5M慢高高精度离线分析YOLOv5x86.7M很慢很高追求极致精度的科研对烟雾检测这个项目我这次用的是YOLOv5s和YOLOv5m各训练了一版最终保留的是YOLOv5s权重。理由后面讲部署时会说到烟雾检测要部署到摄像头端做实时推理速度权重很高YOLOv5s在保证召回率的前提下速度最快。2. 数据集怎么构建模型效果的上限在数据里2.1 数据来源别只盯着现成的烟雾检测数据集的构建我建议按“公开数据集加自采补充”组合的方式来。公开的火灾烟雾数据集有Corsican等优缺点是标注质量参差不齐、场景多集中在森林火灾。所以我额外补充了工业厂房、城市楼宇、道路、室内厨房等场景的图片和视频帧这些场景和实际的消防预警需求更贴近。数据集的组织结构也很重要建议按下面的目录结构放dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml这里有一个很多人会忽略的细节图片和标签要严格同名匹配图片是jpg标签是txt文件名前缀必须完全一致。检查的时候用脚本批量对照一下很容易发现漏标和错位。另外从网上抓图要留意授权问题学术研究和工程demo一般问题不大商用项目最好走自采或授权数据。2.2 标注规则直接决定模型上限很多人第一次标注烟雾会犯一个毛病把半透明的扩散边缘也框进去导致框里一半是背景。我的标注规则是只框烟雾密度较高、肉眼可明确判定的核心区域宁可框小一点不要框大。扩散部分和不透明主体在同一帧里出现时以主体强度为准。如果烟雾和火焰同时出现可以把fire单独作为第二个类别但本项目为了聚焦只做smoke单类。远距离小目标不能删反而要重点保留。这是烟雾检测最难也最需要的样本删掉它们训练出来的模型会变成“近处大烟检测器”。我用的是LabelImg标注导出YOLO格式后每行是class_id x_center y_center width height坐标全部归一化到0到1。以第一行举例如果数据集里只有一个smoke类class_id就是0一张640x640的图上一个中心点在(320, 320)、宽高都是160像素的烟框标注内容是0 0.5 0.5 0.25 0.25标注完成后我习惯写个小脚本扫一遍剔除坐标为0、宽高为负或者宽高比例异常的脏标签。这一步能省掉后面训练时大量的报错排查时间。2.3 数据增强不是越猛越好YOLOv5训练时如果启用Mosaic增强相当于每张图把四张训练图片拼在一起对小目标、多目标的场景收益非常大。烟雾检测场景下我特别推荐这几类增强HSV颜色扰动烟雾在不同光照下颜色变化很大颜色增强能提升泛化能力亮度对比度扰动夜间、雾天、逆光情况下的烟雾检测靠它水平翻转、随机缩放对视频里的烟雾形态多样性有帮助。但注意随机旋转大角度、透视变换这类增强用在烟雾上要谨慎。烟雾本身就是无规则的过度几何变换会让模型学到“模糊块都是烟雾”的错误相关性。我一开始就是增强策略太激进结果模型把很多模糊树影、云层阴影都当成了烟雾撤掉部分增强后才恢复正常。所以增强不是越多越好要让增强保持“物理世界中烟雾可能出现的样子”。2.4 数据划分有讲究按8:1:1划分训练、验证、测试集时有一个视频数据的常见坑如果你用视频抽帧来构建数据集千万不要随即将所有帧随机分到训练和验证集否则同一段视频的连续帧会同时出现在两边验证指标虚高得离谱。正确做法是先把视频按时间切成几段再按段划分保证视频级别的隔离。我最初就是因为没注意到这一点明明模型没泛化好验证集mAP却一度到了0.9换到真实新场景立刻现原形。3. 训练环境和参数从零跑通YOLOv53.1 环境准备YOLOv5的依赖不算复杂我这次的环境是Python 3.9、PyTorch 2.1、CUDA 12.1显卡是RTX 3060 12G。把ultralytics的yolov5仓库clone下来后直接执行git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt如果手头没有NVIDIA显卡CPU也能跑但速度会慢很多。我的建议是先用较小的数据集和YOLOv5s验证一遍完整流程确认代码没报错再上GPU训练完整版本。3.2 配置训练数据YOLOv5训练前要准备三个东西图片、标签、一个数据集描述yaml。我的data.yaml大概长这样path: /your/project/smoke_detect/dataset train: images/train val: images/val nc: 1 names: [smoke]重点是nc类别数要和你标注的类别一致names的顺序必须和标注文件里class_id的顺序一致。顺序错了模型会一直学习错误映射表面上看loss在下降实际精度永远上不来。项目交付时这个data.yaml我会直接放在dataset目录下换机器后在path字段改成自己的绝对路径就能用。3.3 训练命令和关键参数不建议一上来就调一堆参数先按下面这个方式跑通第一版python train.py --img 640 --batch 16 --epochs 100 --data data.yaml --weights yolov5s.pt --project smoke_train几个关键参数我解释一下img 640是主流默认值对视频流推理也够用。如果烟雾场景里目标太远太小可以试试1280代价是显存和速度成倍上涨batch 16在12G显存下跑YOLOv5s没问题。batch过大优化不稳定过小BN层跑不稳尽量不要低于8epochs 100对中小规模数据集是够的配合早停机制可以防止过拟合weights用yolov5s.pt做预训练这是迁移学习的核心不要从零训练。训练过程中建议开启早停我在跑第二轮时加了patience为30连续30个epoch验证集精度不涨就自动停。如果目标尺度特别复杂还可以加入--multi-scale让网络在训练中适应不同分辨率输入烟雾多尺度场景收益很明显。3.4 训练完先看哪些指标训练完成后不要只看loss曲线重点看验证集结果。官方训练结束后会在runs/train/exp目录下生成results.png、混淆矩阵、PR曲线等我会按下面三个优先级看验证集Recall烟雾是安全预警目标漏报比误报严重得多Recall上不去说明还有大量烟没被检出mAP0.5烟雾框标注本身主观性比较强用0.5这个宽松阈值更符合实际评估需求confusion_matrix.png看烟和背景之间的关系如果背景被大量误判成烟说明负样本不足。我的经验是一份合理的数据集加训练配置val集mAP0.5应该能到0.8以上。如果低于0.7先检查数据而不是继续调参。项目里我保留的best.pt在val集上Recall接近0.87mAP0.5约0.83做实时预警的阈值余量是够的。4. 训练好的模型怎么用推理部署与文件说明4.1 项目文件组织整个项目的交付结构我按下面的方式组织拿到手就能直接用smoke_detect/ ├── weights/ │ ├── best.pt # 训练得到的最佳权重日常推理优先用它 │ └── last.pt # 最后一个epoch权重用来续训 ├── dataset/ │ ├── images/ │ ├── labels/ │ └── data.yaml ├── test_images/ # 放测试图片 ├── detect.py # 推理脚本 └── requirements.txtbest.pt和last.pt的区别要搞清楚last.pt是最后一个epoch的产物可能因为训练后期过拟合而效果变差best.pt是验证集上表现最好的那一版日常推理和部署全部用best.pt。如果你拿到项目后想继续训练新数据可以用last.pt作为起点续训不要拿best.pt续训否则会把已经收敛的状态带偏。4.2 推理命令行和Python APIYOLOv5官方提供detect.py一行命令就能对图片、视频、RTSP摄像头流推理python detect.py --weights weights/best.pt --source test_images/ --conf 0.35 --iou 0.45更灵活的方式是用Python API集成到自己的后端服务里用ultralytics库加载模型最直接from ultralytics import YOLO model YOLO(weights/best.pt) results model.predict(test_images/demo.jpg, conf0.35, saveTrue) for r in results: boxes r.boxes.xyxy.cpu().numpy() # 检测框坐标 scores r.boxes.conf.cpu().numpy() # 置信度 print(boxes, scores)detect.py适合快速看效果Python API适合做二次开发。如果你要接入无人机、摄像头或者物联网平台直接在上面代码基础上改就行。4.3 置信度阈值与时序去抖推理时conf阈值一定要根据实际场景调整。我实测时发现conf0.25时召回率很高但误报也多conf0.5时误报少了但漏报又变多。烟雾是安全类目标我的做法是分级处理第一级用偏低的阈值比如0.3保证召回第二级用时间维度过滤同一个区域连续多帧都能检出烟雾才确认报警偶尔闪一帧的“烟雾”大概率是光线或者雾气干扰直接忽略。具体到视频流处理可以维护一个轻量级的帧间缓存记录每个检测框的位置如果下一帧同一个位置附近再次出现检测框就把连续性加一连续三帧以上命中才触发告警。这样做误报能比单帧阈值法下降一多半代价只是延迟一到两秒对烟雾这种慢变化特征是完全可以接受的。5. 实测中的误报、漏报与优化心得5.1 最隐蔽的误报晨雾、水蒸气和灯光光晕实测模型时我发现它最容易被三类东西骗清晨的平流雾、锅炉和高压锅喷出的水蒸气、夜间强灯光周围的光晕。这些目标在单帧画面上和淡烟雾实在太像了。处理方法分三层数据层把这类易混样本收集起来做负样本在训练集中大量加入不含目标的背景图让模型知道“这些不是烟”模型层加大输入分辨率让模型能看到更多纹理细节而不是只看到一团模糊后处理层视频时序过滤加区域逻辑判定。比如机房这类室内场景晨雾不太可能出现在画面里可以直接用区域规则屏蔽。负样本挖掘是我觉得整个烟雾检测项目里性价比最高的优化动作。第一次加了五百多张纯背景图后误报率几乎砍了一半。这比换更大模型、调更高阈值都来得直接。5.2 小目标漏检远距离冒烟怎么办另一个高频问题是小目标漏检烟雾刚出现时往往只占画面很小比例检测器很容易漏。我在实测中总结了几种有效手段训练时保留大量小目标标注样本配合Mosaic增强避免模型只学会检测近处大烟雾推理时对长宽比较大的画面做切片把大图切成几个小块分别推理能明显提升远处小烟雾的检出率增大输入分辨率到1280速度慢一些但小目标召回率能提高不少如果部署环境允许把视频流拉成两路一路全图低阈值扫描一路对重点区域放大检测。这里要提醒一下切片推理会带来重复计数的问题同一个烟分别落在两个切片里可能会被检出两次。后处理时要做IoU合并或者按原图坐标映射去重不然报警计数会乱。5.3 模型压缩与边缘部署训练好的best.pt如果要放到边缘设备上建议先导出ONNX再决定是否转TensorRT或者直接用int8量化。我实测过几轮部署方式推理速度依赖情况精度保留PyTorch原版基准需要PyTorch环境100%ONNX略快只需onnxruntime约99%TensorRT FP16明显更快仅限NVIDIA设备约97%int8量化最快转换麻烦视数据而定导出ONNX的命令python export.py --weights weights/best.pt --include onnx --opset 12导出后会得到best.onnx用onnxruntime就能在ARM设备或者老款嵌入式计算平台上跑。需要说明的是剪枝和蒸馏对烟雾检测有一定效果但烟雾这个类别本身边界就模糊过度压缩后精度掉得很快我的建议是压一步测一步不要一口气上int8先用FP16看效果。最后再分享一点我个人的体会。烟雾检测项目看着简单真正做起来的坑一点都不少核心瓶颈几乎不在网络结构而在数据和后处理策略。如果你拿到权重后直接用自己的摄像头测试发现效果不好不用急着怀疑模型先看数据场景差异再收集你所在场景的负样本把阈值和时序过滤调好效果会有质的提升。作为毕设课题你可以在这个基础上继续扩展接入告警推送、叠加火焰检测、做烟雾浓度的时序预测都是很自然的加分方向。项目里的训练权重、数据集和标注文件我都整理成了开箱即用的结构拿去就能做二次开发复现过程中遇到问题也欢迎多交流。本文还有配套的精品资源点击获取