ARTICLE DETAIL

资讯详情

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

基于YOLOv5的火灾烟雾检测:2059张图像数据集与实战指南

基于YOLOv5的火灾烟雾检测:2059张图像数据集与实战指南 简介本资源面向计算机视觉与深度学习方向的开发者、学生及安防算法研究人员提供一套完整的火灾烟火烟雾检测数据集与YOLOv5训练模型可用于目标检测模型训练、算法验证及课程设计。数据集覆盖大火小火、建筑草原森林起火、车辆起火、昼夜与室内外等多种场景烟雾场景与火焰保持一致标注格式为Pascal VOC含2059张图像及对应XML标签标签类别为fire。压缩包共332个文件约200.15MB包含C/C源码、Python脚本、YAML配置、CUDA内核、Shell脚本及权重文件等并附带使用说明与VOC转YOLO格式的转换脚本便于快速接入YOLOv5训练流程。目前已有838人学习下载适合需要真实烟火数据与可复现训练方案的读者参考使用。1. 火灾烟雾检测数据集与 YOLOv5 模型从 2059 张图像到可复现的检测方案火灾烟雾检测这件事真正卡住大多数人的从来不是模型结构而是数据。你搜 yolov5 烟雾火灾检测能翻出一堆论文和开源仓库但真到自己动手往往发现公开数据集要么只有几百张、要么标签格式对不上、要么全是实验室摆拍的火苗拿到真实监控画面里直接翻车。这个标题指向的是一套相对完整的组合2059 张带标签的火灾烟雾图像配一份 YOLOv5 训练好的检测模型再加一份使用说明。它解决的是从零搭建烟雾检测系统时最耗时的两件事——找数据、标数据。适合谁做安防监控二次开发的、做园区/仓库/森林防火预警原型的、以及想拿一个真实场景数据集练 YOLOv5 全流程的工程师。2059 张不算大但足够跑通训练、验证、部署这条链路也能让你看清烟雾检测和常规目标检测的差别到底在哪。2. 烟雾火灾数据集长什么样标签结构、类别分布与选型判断2.1 2059 张图像的构成与标签格式拿到一个数据集第一件事不是急着训练而是把目录结构和标签格式摸清楚。火灾烟雾检测数据集通常按 YOLO 标准组织图像和标签分开放标签是每张图对应的.txt文件一行一个目标格式为class x_center y_center width height坐标全部归一化到 0 到 1 之间。2059 张这个量级常见做法是训练集、验证集按 8:2 或 9:1 切分也可能已经切好放在images/train、images/val这样的子目录里。先跑一段脚本把数据集的真实情况统计出来别信任何说明文档里的描述自己数一遍最靠谱import os from collections import Counter from pathlib import Path # 数据集根目录按实际路径改 root Path(fire_smoke_dataset) img_dir root / images lbl_dir root / labels class_names [fire, smoke] # 类别名按 data.yaml 里的顺序填 counter Counter() img_count 0 empty_label 0 bad_label 0 for img_path in img_dir.rglob(*): if img_path.suffix.lower() not in (.jpg, .jpeg, .png, .bmp): continue img_count 1 # 标签文件名与图像同名只换后缀 lbl_path lbl_dir / img_path.relative_to(img_dir).with_suffix(.txt) if not lbl_path.exists(): empty_label 1 continue with open(lbl_path, r) as f: lines [ln.strip() for ln in f if ln.strip()] if not lines: empty_label 1 continue for ln in lines: parts ln.split() if len(parts) ! 5: bad_label 1 continue cls_id int(float(parts[0])) counter[cls_id] 1 print(f图像总数: {img_count}) print(f无标签或空标签图像: {empty_label}) print(f格式异常标签行: {bad_label}) for cid, cnt in sorted(counter.items()): name class_names[cid] if cid len(class_names) else f未知类别{cid} print(f类别 {cid} ({name}): {cnt} 个框)这段脚本做三件事统计图像总数、找出没有标签或标签为空的图像、统计每个类别的框数量。参数上class_names必须和data.yaml里的names顺序严格一致否则你看到的类别统计会张冠李戴。rglob(*)会递归所有子目录如果你的数据集已经切好 train/val这个统计会把两边合在一起想看单边就把img_dir指到具体子目录。2.2 火灾和烟雾两类目标的分布陷阱火灾烟雾检测数据集里火灾和烟雾的框数量往往严重不均衡。火焰目标边界清晰、颜色饱和标注起来容易烟雾是半透明、边界模糊、形态随气流变化的东西标注一致性差很多数据集里烟雾框要么偏大要么偏小。2059 张图像如果烟雾框占比明显低于火焰训练出来的模型会偏向火焰检测烟雾召回率上不去。判断是否失衡看上面脚本输出的两类框数量比值。经验上如果某一类框数不到另一类的三分之一就属于明显失衡需要在训练时用类别权重或者过采样来补。另一个隐蔽问题是同一张图里火焰和烟雾重叠标注时容易出现框套框YOLOv5 对这种重叠目标的处理依赖 NMS 的 IoU 阈值后面调参章节会细说。提示先统计再训练。我见过太多人直接开训跑完发现某一类几乎没检出回头查才发现那一类在数据集里只有几十个框。2.3 为什么选 YOLOv5 而不是别的检测器YOLOv5 在这个场景里被反复选中理由很实际。第一它的工程化程度高数据加载、增强、训练、导出 ONNX 一条龙配置文件改几行就能跑不像有些框架要自己写 dataloader。第二烟雾检测对实时性有要求YOLOv5s 在普通 GPU 上能跑到几十 FPS边缘设备上量化后也能用。第三社区里 YOLOv5 的烟雾火灾案例最多遇到问题搜得到答案这对一线落地很重要。选型上如果你追求精度且算力够用 YOLOv5m 或 l如果要在树莓派、Jetson 这类设备上跑YOLOv5n 或 s 更合适。2059 张这个数据量不建议上太大的模型容易过拟合s 或 m 是比较稳的起点。3. 用 YOLOv5 训练烟雾火灾检测模型环境、配置与训练命令3.1 环境配置与依赖安装YOLOv5 的环境配置是新手第一个坎。核心依赖是 PyTorch、torchvision 和一堆工具库。先确认显卡驱动和 CUDA 版本再装对应版本的 PyTorch这一步版本对不上后面全是玄学报错。# 创建独立环境避免污染系统 Python conda create -n fire_smoke python3.8 -y conda activate fire_smoke # 按你的 CUDA 版本装 PyTorch这里以 CUDA 11.3 为例 pip install torch1.12.1cu113 torchvision0.13.1cu113 \ --extra-index-url https://download.pytorch.org/whl/cu113 # 克隆 YOLOv5 源码并安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt参数说明Python 版本建议 3.8 到 3.10太新或太旧都可能碰到依赖冲突。PyTorch 版本要和 CUDA 驱动匹配装完用python -c import torch; print(torch.cuda.is_available())验证输出True才算通。requirements.txt里锁了各库版本别随意升级尤其是 numpy 和 opencv。3.2 data.yaml 与模型配置文件的写法YOLOv5 训练靠两个配置文件数据集描述文件data.yaml和模型结构文件yolov5s.yaml。data.yaml告诉框架去哪找图、有几类、类名叫什么# data.yaml path: ./fire_smoke_dataset # 数据集根目录 train: images/train # 训练集图像相对路径 val: images/val # 验证集图像相对路径 nc: 2 # 类别数 names: [fire, smoke] # 类别名顺序必须和标签里的 class id 对应nc和names是最容易出错的地方。nc写错会导致训练时索引越界names顺序写反会让火焰和烟雾的预测结果对调。模型结构文件一般不用改用yolov5s.yaml就行它里面的nc会被data.yaml覆盖。3.3 训练命令与关键超参数配置齐了就能开训。下面是一条常用的训练命令带上了烟雾检测场景里比较关键的几个参数python train.py \ --img 640 \ --batch 16 \ --epochs 150 \ --data data.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --name fire_smoke_s \ --cache逐个说参数。--img 640是输入分辨率烟雾目标通常占画面比例不小640 够用显存紧张可以降到 512。--batch 16看显存调8G 显存跑 s 模型 640 分辨率大概能到 16。--epochs 150对 2059 张这个量级偏多配合早停一般 80 到 120 轮就收敛设 150 是留余量。--weights yolov5s.pt用预训练权重小数据集上迁移学习比从头训效果好得多。--hyp指定超参文件烟雾检测建议用低增强配置因为烟雾本身形态变化大过强的色彩和几何增强反而干扰学习。--cache把图像缓存到内存2059 张不大开了能明显加快每轮速度。训练过程中重点看三个指标mAP0.5、每一类的precision和recall。烟雾类的 recall 通常比火焰低如果低太多回到 2.2 节检查类别失衡。4. 推理、验证与部署把训练好的模型跑起来4.1 用 detect.py 做单张和批量推理训练完的权重在runs/train/fire_smoke_s/weights/best.pt。先用detect.py验证效果# 单张图像推理 python detect.py \ --weights runs/train/fire_smoke_s/weights/best.pt \ --source test_images/fire_01.jpg \ --img 640 \ --conf-thres 0.35 \ --iou-thres 0.45 \ --save-txt # 批量推理整个目录 python detect.py \ --weights runs/train/fire_smoke_s/weights/best.pt \ --source test_images/ \ --conf-thres 0.35 \ --save-txt --save-conf--conf-thres是置信度阈值烟雾检测里这个值不能设太高烟雾特征弱设 0.5 以上容易漏检0.3 到 0.4 是常见区间。--iou-thres控制 NMS 的重叠阈值火焰和烟雾重叠时这个值设太小会把其中一个框抑制掉设太大又会留下重复框0.45 是折中。--save-txt把检测结果存成 YOLO 格式方便后续做误检分析。4.2 验证集评估与指标解读跑val.py拿到量化指标python val.py \ --weights runs/train/fire_smoke_s/weights/best.pt \ --data data.yaml \ --img 640 \ --task val \ --save-json输出里重点看mAP0.5和mAP0.5:0.95。前者是 IoU 阈值 0.5 时的平均精度后者更严格。烟雾检测里mAP0.5能到 0.7 以上就算可用mAP0.5:0.95通常低不少因为烟雾框的定位精度天然差。如果两个指标差距特别大说明框的位置回归不准可以考虑在损失里加大定位项的权重。4.3 导出 ONNX 与边缘部署要在非 Python 环境部署导出 ONNXpython export.py \ --weights runs/train/fire_smoke_s/weights/best.pt \ --include onnx \ --img 640 \ --batch 1 \ --simplify--simplify会做图优化去掉冗余算子导出的模型更小更快。--batch 1是推理时的批大小边缘设备一般单张推理。导出后在目标平台上用 ONNX Runtime 或 TensorRT 加载注意输入预处理要和训练时一致letterbox 缩放、归一化到 0 到 1、BGR 转 RGB这几步顺序错了检测结果会完全乱掉。5. 烟雾火灾检测的避坑与排查那些让模型失效的细节5.1 现象训练 loss 正常下降但验证 mAP 一直很低原因通常是标签和图像没对齐或者data.yaml里的路径写错导致验证集加载的是空数据。YOLOv5 在路径错误时不一定报错而是静默跳过你看到的低 mAP 其实是模型在瞎猜。解决用 2.1 节的统计脚本确认验证集图像和标签都能被找到再检查data.yaml里val路径是相对path还是绝对路径两种写法混用会出问题。5.2 现象火焰检测很准烟雾几乎检不出原因是烟雾类样本少或标注质量差。烟雾边界模糊标注时框往往偏大模型学到的是大框烟雾这种错误关联。解决先统计两类框数量失衡就用--cls权重或者对烟雾样本过采样再抽查一批烟雾标签看框是否贴合烟雾主体偏太大的重新标。另外可以把hyp里的mosaic增强关掉试试mosaic 拼接会让烟雾形态更碎有时反而有害。5.3 现象模型在测试集上很好接到监控视频里全是误检原因是数据集和真实场景的域差异。2059 张图像大概率来自特定场景而监控画面有逆光、夜间红外、雨雾干扰这些在训练集里没有。解决从目标场景里抽几百帧人工标一部分做微调哪怕只标 200 张也能明显改善。另外推理时把--conf-thres调高到 0.5 以上先压误检再逐步往下找召回和误检的平衡点。5.4 现象导出 ONNX 后检测结果和 PyTorch 不一致原因是预处理没对齐。PyTorch 推理时 YOLOv5 内部做了 letterbox 和归一化导出 ONNX 后这些操作不在图里需要你在外部代码里手动实现。解决对照utils/augmentations.py里的letterbox函数在部署代码里复现同样的缩放和填充逻辑归一化用img / 255.0通道顺序确认是 RGB。5.5 现象训练到一半显存爆了原因是--batch设太大或者--img分辨率太高也可能是--cache把图像全加载进内存后和显存争抢。解决先把--batch减半还不行就降--img到 512--cache改成--cache ram或直接去掉。2059 张图像用 s 模型8G 显存跑 640 分辨率 batch 16 是安全线。6. 让烟雾检测真正可用的两个进阶技巧第一个技巧是分帧投票。监控视频里单帧误检很常见但连续多帧同一位置都检出烟雾可信度就高得多。做法是把检测结果按时间窗口聚合比如 1 秒内 25 帧里有 15 帧在同一区域检出烟雾才触发告警。这个逻辑不复杂但能把误报率压下来一大截。实现上对每帧的检测框做简单的位置聚类统计每个聚类在窗口内的出现次数超过阈值才输出。参数上窗口长度和触发比例要根据场景调仓库这种烟雾扩散慢的场景窗口可以长一点开放空间短一点。第二个技巧是用验证集做阈值扫描而不是拍脑袋定conf-thres。写个脚本把置信度阈值从 0.1 扫到 0.9每个阈值下算一遍 precision 和 recall画出曲线选 F1 最高的那个点。烟雾检测里这个最优点往往在 0.3 到 0.45 之间但具体值取决于你的数据集和场景。我一般会把这个扫描脚本固化下来每次换数据集或微调模型后都跑一遍比凭感觉调靠谱得多。import numpy as np from pathlib import Path # 假设你已经用 val.py --save-json 导出了预测结果 # 这里演示阈值扫描的核心逻辑 def scan_threshold(preds, gts, thresholdsnp.arange(0.1, 0.95, 0.05)): results [] for t in thresholds: tp fp fn 0 for pred, gt in zip(preds, gts): # pred: [[cls, conf, x1, y1, x2, y2], ...] # gt: [[cls, x1, y1, x2, y2], ...] kept [p for p in pred if p[1] t] matched_gt set() for p in kept: best_iou, best_idx 0, -1 for i, g in enumerate(gt): if i in matched_gt or g[0] ! p[0]: continue iou compute_iou(p[2:], g[1:]) if iou best_iou: best_iou, best_idx iou, i if best_iou 0.5: tp 1 matched_gt.add(best_idx) else: fp 1 fn len(gt) - len(matched_gt) precision tp / (tp fp 1e-6) recall tp / (tp fn 1e-6) f1 2 * precision * recall / (precision recall 1e-6) results.append((t, precision, recall, f1)) return results def compute_iou(box_a, box_b): xa max(box_a[0], box_b[0]); ya max(box_a[1], box_b[1]) xb min(box_a[2], box_b[2]); yb min(box_a[3], box_b[3]) inter max(0, xb - xa) * max(0, yb - ya) area_a (box_a[2]-box_a[0]) * (box_a[3]-box_a[1]) area_b (box_b[2]-box_b[0]) * (box_b[3]-box_b[1]) return inter / (area_a area_b - inter 1e-6)这段代码的核心是遍历阈值、对每个阈值算 TP/FP/FN、再算 F1。compute_iou是标准 IoU 计算匹配阈值固定 0.5。实际用的时候把preds和gts换成你从验证集导出的真实数据就行。跑完选 F1 最高的阈值写进部署配置。这两个技巧都不复杂但决定了模型是能跑还是能用。我自己的习惯是任何检测模型上线前先跑一遍阈值扫描再在真实视频上做分帧投票测试两步都过了才敢接告警。烟雾检测尤其如此漏报和误报的代价都不小多花半天调这两个参数比事后救火划算。希望帮到你。本文还有配套的精品资源点击获取
返回列表