news 2026/10/21 2:46:24

YOLOv5烟雾检测实战:数据集、模型权重与训练全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv5烟雾检测实战:数据集、模型权重与训练全流程

简介:这份资源面向安全监控、火灾预警方向的开发者与深度学习学习者,提供一套基于YOLOv5的烟雾检测完整方案,包含已训练好的模型权重与配套数据集,可直接用于实时视频流中的烟雾识别与预警系统搭建。压缩包共约2000个文件,整体360.52MB,以jpg烟雾图像、txt标签与xml标注文件为主,辅以yaml配置、py脚本、pt模型权重及docker部署文件,覆盖从数据到推理的完整链路。资源中已有多环境条件下的标注样本,模型经过充分训练,能区分烟雾与雾、灰尘等易混目标,提升检测精度与泛化能力。目前已有2356人学习下载,适合希望快速复现烟雾检测、集成到监控或无人机巡检场景的读者,也可在此基础上微调再训练以适配特定需求。

1. 烟雾检测项目落地:从数据集到训好的模型,一套能直接跑的 YOLOv5 方案

工厂仓库的烟感摄像头经常误报,灰尘一飘就触发警报,值班人员跑过去发现啥事没有。这种场景下,传统传感器方案确实力不从心,而视觉烟雾检测又面临一个现实问题:公开数据集少、标注成本高、训好的模型更难找。这个项目解决的就是这个痛点——它提供了一套完整的 YOLOv5 烟雾检测方案,包含已经标注好的数据集和训练完成的权重文件。你拿到手之后,不需要从零开始收集烟雾图片、不需要自己画标注框、更不需要从头训练模型,直接就能在测试集上跑推理看效果。适合两类人:一是想快速验证视觉烟雾检测可行性的开发者,二是拿它做二次开发、迁移到实际监控场景的工程人员。数据集和模型都齐了,剩下的就是怎么跑起来、怎么改的问题。

2. 项目结构拆解:数据集、模型权重和训练脚本怎么组织

2.1 目录布局与文件职责

拿到一个包含数据集和训练权重的 YOLOv5 项目,第一件事不是急着跑detect.py,而是先把目录结构看清楚。这个项目的组织方式遵循了 YOLOv5 的标准工程惯例,常见做法是长这样:

smoke-detection-yolov5/ ├── data/ │ ├── smoke.yaml # 数据集配置文件 │ ├── images/ │ │ ├── train/ # 训练集图片 │ │ ├── val/ # 验证集图片 │ │ └── test/ # 测试集图片 │ └── labels/ │ ├── train/ # 训练集标注(YOLO格式txt) │ ├── val/ │ └── test/ ├── models/ │ ├── yolov5s.yaml # 模型结构定义 │ └── hub/ # 预训练权重缓存 ├── weights/ │ ├── best.pt # 训练好的最优权重 │ └── last.pt # 最后一轮权重 ├── utils/ # 工具函数(NMS、坐标变换等) ├── detect.py # 推理脚本 ├── train.py # 训练脚本 ├── val.py # 验证脚本 └── requirements.txt # 依赖清单

data/smoke.yaml是整个数据集的入口配置,它告诉训练脚本去哪里找图片、去哪里找标签、类别名是什么。这个文件通常只有几行,但写错一个路径就会导致训练时找不到数据。weights/best.pt是已经训练好的权重文件,也是这个项目最核心的产出物——你不需要自己跑训练就能直接用它做推理。models/yolov5s.yaml定义了网络结构,如果你想把骨干网络换成更大的 yolov5m 或 yolov5l,改的就是这个文件。

2.2 数据集配置与标注格式

YOLO 格式的标注和 VOC 那种 XML 不一样,它用纯文本存,每行一个目标,格式是类别索引 中心x 中心y 宽度 高度,所有坐标都归一化到 0 到 1 之间。这个项目的smoke.yaml内容大致如下:

# data/smoke.yaml path: ../data # 数据集根目录 train: images/train # 训练集路径(相对 path) val: images/val # 验证集路径 test: images/test # 测试集路径 nc: 1 # 类别数量,烟雾检测只有一类 names: ['smoke'] # 类别名称列表

这里有几个参数需要留意。nc是类别数,烟雾检测通常只检测烟雾本身,所以是 1;如果你还想同时检测火焰,就改成 2,并在names里加上'fire'。path建议用相对路径,这样整个项目拷到别的机器上也能跑,不用改绝对路径。标注文件要和图片一一对应,比如images/train/001.jpg对应的标签就是labels/train/001.txt,文件名必须一致,只是扩展名不同。

注意:如果标签文件缺失或者文件名对不上,训练时不会报错,但那个样本会被当成负样本处理,模型学不到东西。跑训练前最好写个脚本检查一下图片和标签的配对情况。

2.3 模型结构与预训练权重

YOLOv5 提供了 s、m、l、x 四个规格,这个项目用的是 yolov5s,参数量最小、推理速度最快,适合边缘设备部署。模型结构定义在models/yolov5s.yaml里,核心参数是depth_multiple和width_multiple,分别控制网络的深度和宽度缩放系数。yolov5s 的这两个值都是 0.33 和 0.50,意味着它是在基础结构上做了裁剪的轻量版本。

# models/yolov5s.yaml 关键片段 nc: 1 # 类别数,要和 smoke.yaml 保持一致 depth_multiple: 0.33 # 深度缩放系数 width_multiple: 0.50 # 宽度缩放系数 backbone: [[-1, 1, Conv, [64, 6, 2, 2]], # 第0层:卷积下采样 [-1, 1, Conv, [128, 3, 2]], # 第1层 [-1, 3, C3, [128]], # 第2层:C3模块 ... ]

nc这个参数必须和smoke.yaml里的nc一致,否则加载权重时会报维度不匹配。如果你要改类别数,除了改这两个地方,还需要重新训练最后一层分类头,不能直接拿原权重做推理。depth_multiple和width_multiple一般不动,除非你有明确的精度和速度权衡需求——想提精度就换 yolov5m 的配置文件,想再快就自己裁剪通道数。

3. 环境搭建与推理跑通:从零到看见检测框

3.1 依赖安装与版本选择

YOLOv5 对 PyTorch 版本有一定要求,太新或太旧都可能出问题。这个项目常见做法是锁定在 PyTorch 1.8 到 1.12 之间,配合 CUDA 11.x。如果你没有 GPU,用 CPU 也能跑推理,只是速度慢一些。安装步骤不复杂,但顺序要对:

# 创建虚拟环境(推荐,避免污染全局包) conda create -n smoke-yolo python=3.8 -y conda activate smoke-yolo # 安装 PyTorch(根据你的 CUDA 版本选择对应命令) # 有 GPU 且 CUDA 11.3 的情况: pip install torch==1.12.0+cu113 torchvision==0.13.0+cu113 -f https://download.pytorch.org/whl/torch_stable.html # 没有 GPU 的情况: # pip install torch==1.12.0 torchvision==0.13.0 # 安装项目依赖 pip install -r requirements.txt

requirements.txt里通常包含opencv-python、numpy、pyyaml、tqdm、matplotlib这些包。有一个坑是opencv-python和opencv-python-headless不能同时装,如果你在服务器上跑没有图形界面,用 headless 版本更合适。另外pillow的版本也要注意,太新的版本和旧版 torchvision 可能不兼容。

3.2 推理脚本参数详解

环境装好之后,直接用detect.py跑推理是最快的验证方式。这个脚本的参数不少,但常用的就那么几个:

python detect.py \ --weights weights/best.pt \ --source data/images/test \ --img-size 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --device 0 \ --save-txt \ --project runs/detect \ --name smoke_test

--weights指定训练好的权重路径,这里用best.pt而不是last.pt,因为 best 是在验证集上表现最好的那一轮保存的。--source可以是单张图片、整个文件夹、视频文件,甚至填0调用摄像头。--img-size是推理时的输入分辨率,训练时用的多少推理就用多少,一般 640 是默认值。--conf-thres是置信度阈值,低于这个值的检测框会被过滤掉,烟雾检测场景下建议设 0.25 到 0.3 之间——设太高会漏检淡烟,设太低会误检类似烟雾的云彩或灰尘。--iou-thres控制 NMS 的合并阈值,0.45 是通用值。--device 0表示用第一块 GPU,填cpu就用 CPU 推理。--save-txt会把检测结果的坐标保存成 txt 文件,方便后续做统计分析。

3.3 推理结果解读与置信度调参

跑完推理后,结果默认保存在runs/detect/smoke_test/目录下。图片上会画出检测框,框上方标注smoke 0.87这样的类别和置信度。如果你发现漏检比较多,先把--conf-thres降到 0.15 试试;如果误检多,就往上提到 0.4。这个参数没有绝对的最优值,取决于你的场景——仓库里灰尘大,误检容忍度低,就设高一点;森林防火场景漏检代价大,就设低一点。

# 如果你想在代码里批量统计检测结果,可以这样读 save-txt 的输出 import os txt_dir = "runs/detect/smoke_test/labels" for txt_file in os.listdir(txt_dir): with open(os.path.join(txt_dir, txt_file)) as f: lines = f.readlines() if lines: # 每行格式:类别 中心x 中心y 宽 高 置信度 for line in lines: cls, cx, cy, w, h, conf = line.strip().split() print(f"{txt_file}: 检测到烟雾,置信度 {float(conf):.2f}") else: print(f"{txt_file}: 未检测到烟雾")

这段代码遍历save-txt生成的标签文件,统计每张图是否检测到烟雾以及对应的置信度。cls是类别索引,烟雾检测里只有 0 这一类。cx、cy、w、h是归一化坐标,乘以图片宽高就能还原成像素坐标。这个统计结果可以用来评估模型在你自己的测试集上的表现,也可以作为后续报警逻辑的输入——比如连续 3 帧检测到置信度大于 0.5 的烟雾才触发报警,避免单帧误检。

4. 训练与微调:用自己的数据提升检测效果

4.1 训练脚本参数配置

虽然项目已经提供了训好的模型,但实际场景中你大概率需要用自己的数据微调。train.py的参数比推理脚本多得多,但核心的也就那几个:

python train.py \ --data data/smoke.yaml \ --cfg models/yolov5s.yaml \ --weights weights/best.pt \ --epochs 100 \ --batch-size 16 \ --img-size 640 \ --device 0 \ --workers 8 \ --project runs/train \ --name smoke_finetune

--weights这里填的是已有的best.pt,这叫迁移学习——在已经学会检测烟雾的基础上,用新数据继续训练,比从零开始快得多,通常 50 到 100 个 epoch 就能收敛。--batch-size根据你的显存来定,8G 显存跑 640 分辨率大概能开到 16,显存不够就往下调,调到 8 甚至 4 都行,只是训练会慢一些。--workers是数据加载的线程数,设成 CPU 核心数的一半左右比较合适,设太高反而会因为线程切换开销导致变慢。

4.2 数据增强与超参数调整

YOLOv5 默认开启了 mosaic 增强、HSV 色彩空间扰动、随机翻转等策略。烟雾检测场景下,mosaic 增强有时候会带来问题——它把四张图拼成一张,烟雾的形态可能变得不自然,反而影响学习。如果你发现训练后期 loss 震荡厉害,可以试试关掉 mosaic:

# data/hyp.scratch.yaml 中修改 mosaic: 0.0 # 关闭 mosaic 增强 mixup: 0.0 # 关闭 mixup hsv_h: 0.015 # 色调扰动幅度 hsv_s: 0.7 # 饱和度扰动 hsv_v: 0.4 # 亮度扰动 flipud: 0.0 # 上下翻转概率(烟雾通常不会倒着飘,建议关掉) fliplr: 0.5 # 左右翻转概率

flipud这个参数我一般会设成 0,因为烟雾在物理世界里都是往上飘的,上下翻转会生成不存在的样本,干扰模型学习。hsv_h可以适当调大一点,因为不同光照条件下烟雾的颜色差异挺大的,增强色调扰动有助于模型适应各种环境。学习率方面,微调时建议把初始学习率调小,比如从 0.01 降到 0.001,避免把预训练权重学歪了。

4.3 训练过程监控与模型选择

训练启动后,runs/train/smoke_finetune/目录下会生成results.csv和一堆可视化图表。重点看三个指标:train/box_loss、val/box_loss和metrics/mAP_0.5。box_loss 持续下降说明模型在学,如果 train loss 降但 val loss 升,就是过拟合了,需要加数据或者加正则化。mAP_0.5 是衡量检测精度的核心指标,烟雾检测场景下能到 0.7 以上就算不错了。

# 快速查看训练结果 import pandas as pd df = pd.read_csv("runs/train/smoke_finetune/results.csv") # 去掉列名里的空格 df.columns = df.columns.str.strip() # 找 mAP 最高的 epoch best_epoch = df['metrics/mAP_0.5'].idxmax() print(f"最佳 epoch: {best_epoch}") print(f"最佳 mAP@0.5: {df.loc[best_epoch, 'metrics/mAP_0.5']:.4f}") print(f"对应训练损失: {df.loc[best_epoch, 'train/box_loss']:.4f}") print(f"对应验证损失: {df.loc[best_epoch, 'val/box_loss']:.4f}")

这段代码读results.csv,找到 mAP 最高的那一轮。YOLOv5 训练结束后会自动把这一轮的权重保存为best.pt,所以你不需要手动挑。但如果你中途停了训练,想从某个 epoch 继续,可以用--resume参数,它会从last.pt恢复优化器状态和 epoch 计数。

5. 避坑与排查:烟雾检测项目常见的五个翻车点

5.1 推理时检测框乱飞或者一个目标出多个框

现象:图片上同一个烟雾区域被画了好几个重叠的框,或者框的位置明显偏了。

原因:通常是--iou-thres设得太高,NMS 没有把重叠的框合并掉;也可能是--img-size和训练时不一致,导致坐标映射错位。

解决:把--iou-thres降到 0.4 或 0.35 试试;确认推理的--img-size和训练时用的分辨率一致,训练用 640 推理也用 640,不要一个 640 一个 320。

5.2 训练 loss 不下降或者变成 NaN

现象:训练启动后 box_loss 一直在 0.5 以上震荡,或者几个 epoch 后直接变成 nan。

原因:学习率设太大了,或者数据集中有标注框宽高为 0 的脏数据,计算 loss 时除零了。

解决:把初始学习率降到 0.001 甚至 0.0005;写个脚本检查标签文件,把宽高小于 0.001 的行删掉。另外确认smoke.yaml里的nc和模型配置里的nc一致,不一致也会导致 loss 异常。

5.3 模型在测试集上表现很好但实际场景漏检严重

现象:val.py跑出来的 mAP 有 0.8,但拿实际监控画面去测,淡烟、远距离烟雾基本检测不到。

原因:训练集和实际场景的数据分布不一致。公开数据集里的烟雾通常比较浓、距离比较近,而实际监控画面里烟雾往往很淡、很小。

解决:从实际场景截取一些漏检的图片,标注后加入训练集做微调。微调时把--img-size提高到 1280 试试,小目标在更高分辨率下更容易被检测到。另外可以适当降低--conf-thres到 0.15,让模型多输出一些候选框。

5.4 GPU 显存不够导致训练中断

现象:训练跑了几十个 epoch 后突然报 CUDA out of memory。

原因:YOLOv5 在训练过程中会缓存一些中间结果,显存占用会逐渐上升;或者--batch-size设得太大,一开始就爆了。

解决:把--batch-size减半,比如从 16 降到 8;如果还不行就降到 4。另外可以在训练命令里加--accumulate 2,用梯度累积模拟更大的 batch size,显存占用不变但效果接近大 batch。

5.5 推理速度太慢达不到实时要求

现象:在边缘设备上跑,每帧推理要 200 毫秒以上,达不到 30 帧每秒的实时要求。

原因:用了 yolov5l 或 yolov5x 的大模型,或者没有用 GPU 推理,或者输入分辨率设得太高。

解决:换回 yolov5s 的权重;确认--device 0用的是 GPU 而不是 CPU;把--img-size从 640 降到 416 或 320,速度会明显提升,但小目标检测精度会下降,需要权衡。如果还不行,可以考虑用 TensorRT 对模型做量化加速,常见做法是导出 ONNX 再用 trtexec 转成 engine 文件。

6. 二次开发改造:从能跑到好用还差哪几步

拿到这个项目之后,直接跑通推理只是第一步。真正要落地到实际场景,通常需要做三件事:换数据、改逻辑、加后处理。

换数据是最直接的改造方式。把你自己的监控画面截帧,用 labelImg 或者 roboflow 标注成 YOLO 格式,替换掉data/images/train和data/labels/train里的内容,然后跑微调训练。这里有个血泪经验:标注的时候一定要把淡烟也标上,不要只标浓烟。模型学到的边界就是你标注的边界,你只标浓烟,它就只认浓烟。我一般会要求标注人员对同一张图标注两遍,取交集作为最终标签,减少漏标和误标。

改逻辑是指调整推理脚本的输出行为。原版的detect.py只是画框保存图片,实际部署时你需要把它改成一个持续运行的检测服务。常见做法是用 OpenCV 读视频流,逐帧推理,把检测结果推给报警模块:

import cv2 import torch # 加载模型 model = torch.hub.load('.', 'custom', path='weights/best.pt', source='local') model.conf = 0.3 # 置信度阈值 model.iou = 0.45 # NMS 阈值 cap = cv2.VideoCapture("rtsp://your-camera-stream") # 替换成实际视频流地址 alarm_counter = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 推理 results = model(frame) detections = results.pandas().xyxy[0] # 获取检测结果 # 统计置信度大于 0.5 的烟雾目标 high_conf = detections[detections['confidence'] > 0.5] if len(high_conf) > 0: alarm_counter += 1 else: alarm_counter = max(0, alarm_counter - 1) # 衰减 # 连续 5 帧检测到才触发报警,避免单帧误检 if alarm_counter >= 5: print("触发烟雾报警!") # 这里可以接入实际的报警逻辑,比如发 HTTP 请求、写数据库 alarm_counter = 0 # 报警后重置 # 画框显示 for _, det in high_conf.iterrows(): x1, y1, x2, y2 = int(det['xmin']), int(det['ymin']), int(det['xmax']), int(det['ymax']) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(frame, f"smoke {det['confidence']:.2f}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.imshow("Smoke Detection", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

这段代码做了三件事:逐帧推理、连续帧计数报警、可视化输出。alarm_counter的设计是关键——单帧检测到烟雾就报警的话,误报率会高得没法用;连续 5 帧都检测到才触发,能过滤掉大部分瞬时误检。alarm_counter的衰减逻辑也要有,否则一次误检之后计数器一直不归零,后面稍微有点风吹草动就报警了。

加后处理是指对模型的原始输出做进一步过滤。比如用颜色特征排除掉类似烟雾的白色墙壁或云朵,用面积阈值排除掉太小的检测框,用长宽比排除掉明显不是烟雾的细长条目标。这些规则不需要重新训练模型,直接在推理结果上做过滤就行,成本低见效快。

还有一个容易被忽略的点是模型版本管理。你微调了好几个版本,每个版本的best.pt都要用清晰的命名保存,比如smoke_v1_20240101.pt、smoke_v2_20240215.pt,并且在文件名里体现训练数据的变化。我见过太多人把best.pt覆盖来覆盖去,最后发现线上效果变差了,想回滚都找不到旧版本。从那以后我每次训练完都强制走一遍版本归档流程,把权重文件、训练配置、数据集版本号一起打包存好,再也没出现过回滚不了的情况。希望帮到你。

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

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

窗口全屏vi

效果: 使LabVIEW前面板占满整个屏幕

作者头像 李华
网站建设 2026/10/21 2:44:27

GitKraken Ubuntu 深度指南:Electron+libgit2 可视化 Git 协作实战

简介:本资源为 GitKraken v6.5.1 官方 Ubuntu 原生客户端安装包,面向 Linux 开发者、Git 初学者及需图形化操作 Git 的团队协作人员,解决命令行 Git 学习门槛高、分支/合并/冲突处理可视化不足等痛点。压缩包为 tar.gz 格式,共 97…

作者头像 李华
网站建设 2026/10/21 2:44:24

PyTorch多类别语义分割实战:Unet从数据预处理到mIoU评估全链路排雷

简介:本资源是面向深度学习初学者与计算机视觉实践者的PyTorch多类别语义分割实战项目,聚焦Unet模型在自定义数据集上的完整实现,适用于医学影像、遥感解译等需精细像素级分类的场景。压缩包共46个文件,含19个核心Python源码&…

作者头像 李华
网站建设 2026/10/21 2:43:22

ZED+YOLO双目测距实战:标定、对齐与避坑指南

简介:ZED双目相机与YOLO目标检测结合的测距工程,面向计算机视觉开发者和机器人、自动驾驶等应用场景,提供一套可直接运行的双目测距代码,核心脚本为zedceju.py。项目集成ZED SDK深度信息与YOLO实时目标检测,可完成物体…

作者头像 李华
网站建设 2026/10/21 2:42:23

SpringBoot+Vue充电桩系统:多角色协同与强事务保障设计

简介:本资源是一套面向计算机专业本科生的Java毕业设计完整实现方案,聚焦新能源汽车充电桩管理场景,解决传统人工运维效率低、信息难追溯等现实问题。系统采用SpringBootVue前后端分离架构,基于MySQL数据库与Tomcat服务器部署&…

作者头像 李华
网站建设 2026/10/21 2:39:04

Docker命令实战:从容器生命周期到排障的完整速查手册

要说 Docker 最让人头疼的地方,不是它有多少新概念,而是命令行工具里动不动就是几十个参数、几十条子命令。我刚接触那会儿也走了不少弯路:容器跑不起来不知道看哪里,端口映射不通怀疑镜像有问题,后来才发现是网络模式…

作者头像 李华