火灾烟雾检测实战:2059张图像+YOLOv5全流程解析 简介这份资源面向计算机视觉初学者与烟火检测方向的开发者提供一套可直接上手的火灾烟雾检测方案。数据集覆盖大火小火、建筑草原森林起火、车辆起火、昼夜与室内外等场景烟雾样本与火场景保持一致按Pascal VOC格式组织含2059张图像及对应XML标注标签统一为fire便于训练目标检测模型。压缩包共332个文件约200.15MB以C源码、头文件、Python脚本、YAML配置、Shell脚本和CUDA文件为主另含少量权重、图片与说明文档整体构成YOLOv5训练与推理所需的工程骨架。资源内附使用说明并给出VOC转YOLO格式的脚本调用思路可帮助读者快速完成数据准备、模型训练与验证。目前已有840人学习下载适合需要烟火识别数据集与可复现检测流程的读者参考。1. 火灾烟火烟雾检测数据集与 YOLOv5 模型从 2059 张图像到可复现的检测方案拿到一份标注好的火灾烟雾数据集最怕的不是数据量不够而是不知道标签格式对不对、类别定义是否统一、训练完模型到底能不能在实际场景里跑起来。这份 2059 张图像带标签的火灾烟火烟雾检测数据集配合 YOLOv5 训练流程恰好能覆盖从数据校验、格式转换、模型训练到推理部署的完整链路。它适合两类人一类是想快速验证烟雾检测可行性的算法工程师另一类是需要搭建早期火灾预警原型的嵌入式或边缘计算开发者。数据集规模不算大但类别聚焦、标注完整意味着你可以在单卡甚至消费级显卡上完成训练并且有足够空间做数据增强和调参实验。真正要解决的问题是如何把这份数据变成能稳定输出检测框的模型而不是停留在跑通 demo 的层面。2. 数据集拆解与 YOLOv5 格式对齐2059 张图像怎么用才不浪费2.1 图像数量与类别分布的实际影响2059 张图像在目标检测任务里属于中小规模。如果按 8:1:1 划分训练集、验证集、测试集训练集大约 1647 张验证集和测试集各约 206 张。这个量级下类别不平衡是第一个要面对的问题。火灾烟雾检测通常涉及火焰和烟雾两个大类但实际标注中可能细分为明火、阴燃烟雾、浓烟、薄烟等子类。你需要先统计每个类别的实例数量和图像分布再决定是否合并某些子类或对稀疏类别做过采样。常见做法是写一个统计脚本遍历标签文件输出每个类别的边界框数量和对应图像数。如果某个类别实例数低于总实例数的 5%训练时该类别召回率会明显偏低。这时候可以考虑两种策略一是合并语义相近的类别比如把不同浓度的烟雾统一归为烟雾类二是在数据加载阶段对包含稀疏类别的图像设置更高的采样权重。2.2 标签格式校验与 YOLO 格式转换YOLOv5 要求标签为归一化的class_id x_center y_center width height格式每行一个目标坐标值在 0 到 1 之间。如果你拿到的标签是 VOC 的 XML 或 COCO 的 JSON需要先转换。下面是一个把 VOC 格式转成 YOLO 格式的脚本示例同时做了边界校验。import xml.etree.ElementTree as ET import os from pathlib import Path # 类别映射根据实际数据集调整 CLASS_MAP {fire: 0, smoke: 1} def voc_to_yolo(xml_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text.strip().lower() if cls_name not in CLASS_MAP: continue cls_id CLASS_MAP[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 边界裁剪防止越界导致归一化后超出 [0,1] xmin max(0, min(xmin, img_w)) xmax max(0, min(xmax, img_w)) ymin max(0, min(ymin, img_h)) ymax max(0, min(ymax, img_h)) if xmax xmin or ymax ymin: continue # 跳过无效框 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return lines # 批量转换示例 def batch_convert(xml_dir, img_dir, out_dir): Path(out_dir).mkdir(parentsTrue, exist_okTrue) for xml_file in Path(xml_dir).glob(*.xml): img_file Path(img_dir) / (xml_file.stem .jpg) if not img_file.exists(): continue # 这里需要读取图像宽高可用 PIL 或 OpenCV from PIL import Image with Image.open(img_file) as im: w, h im.size lines voc_to_yolo(xml_file, w, h) with open(Path(out_dir) / (xml_file.stem .txt), w) as f: f.write(\n.join(lines))这段代码的关键点在于边界裁剪和无效框过滤。实际标注中经常出现边界框超出图像范围的情况如果不做裁剪归一化后的坐标可能小于 0 或大于 1YOLOv5 在数据加载时会直接报错或静默丢弃。另外类别名称映射要跟数据集实际标注一致大小写和空格都要处理干净。2.3 数据集目录结构与 YOLOv5 配置文件YOLOv5 对目录结构有约定。推荐按以下方式组织dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml是训练入口配置文件内容如下path: ./dataset train: images/train val: images/val test: images/test nc: 2 names: [fire, smoke]nc是类别数names顺序必须跟标签里的class_id对应。如果类别数或名称写错训练时损失会异常震荡验证集指标上不去。建议在训练前用脚本抽查一批标签文件确认类别 ID 没有越界。2.4 数据增强策略与参数设置YOLOv5 内置了 Mosaic、MixUp、随机缩放、随机裁剪等增强方式。对于火灾烟雾检测Mosaic 增强能显著提升小目标烟雾的检测效果因为烟雾在远距离场景下往往只占几十个像素。但 Mosaic 会引入大量拼接边界如果数据集本身背景单一可能导致模型学到拼接伪影。建议在hyp.scratch-low.yaml基础上调整mosaic: 1.0保持开启但训练后期最后 10 个 epoch 关闭让模型适应真实分布。mixup: 0.1左右过高会让烟雾和火焰的边界变得模糊。hsv_h: 0.015、hsv_s: 0.7、hsv_v: 0.4模拟不同光照和烟雾浓度。flipud: 0.0火灾场景上下翻转不符合物理规律不建议开启。fliplr: 0.5水平翻转可以保留。这些参数不是固定的需要根据验证集 mAP 做消融。如果发现验证集损失比训练集高很多优先降低 Mosaic 和 MixUp 的强度。3. YOLOv5 训练全流程从环境搭建到模型收敛3.1 环境依赖与版本选择YOLOv5 对 PyTorch 和 CUDA 版本有一定要求。常见做法是使用 Python 3.8 到 3.10PyTorch 1.8 到 2.0 之间的版本。如果使用较新的显卡建议 PyTorch 2.0 以上配合 CUDA 11.8。安装步骤# 创建虚拟环境 conda create -n fire_detect python3.9 -y conda activate fire_detect # 安装 PyTorch根据 CUDA 版本调整 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 仓库并安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt这里不指定具体版本号因为 YOLOv5 仓库更新频繁直接拉取主分支通常能兼容大多数环境。如果遇到torch和torchvision版本不匹配优先按 PyTorch 官方安装命令重新装。3.2 训练命令与关键参数解读启动训练的命令如下python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data ./dataset/data.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --name fire_smoke_exp \ --project runs/train \ --cache逐项说明--img 640输入图像尺寸。烟雾目标通常较大640 足够如果小目标多可以提到 1280但显存占用翻倍。--batch 16批大小。显存 8GB 以下建议 8 或 16显存 12GB 以上可以 32。--epochs 100火灾烟雾数据集 2059 张100 个 epoch 通常能收敛。如果验证集 mAP 在 50 个 epoch 后不再提升可以提前停止。--weights yolov5s.pt预训练权重。从 COCO 预训练模型微调比从头训练收敛快很多尤其在小数据集上。--cfg models/yolov5s.yaml模型结构配置。yolov5s 是最小版本推理速度快适合边缘设备如果追求精度可以换 yolov5m 或 yolov5l。--cache把图像缓存到内存加快训练速度。数据集小的时候效果明显但会占用几 GB 内存。训练过程中重点关注mAP0.5和mAP0.5:0.95两个指标。如果mAP0.5在 0.6 以下说明模型欠拟合或数据标注有问题如果训练集 mAP 很高但验证集很低说明过拟合需要增加增强或减少模型复杂度。3.3 训练过程监控与早停策略YOLOv5 默认在每个 epoch 结束后输出验证指标并保存最佳模型和最后模型。建议开启 TensorBoard 或 WandB 监控损失曲线tensorboard --logdir runs/train如果发现box_loss和obj_loss下降但cls_loss不降通常是类别不平衡或类别标签错误。这时候要回头检查data.yaml的names和标签文件里的class_id是否一致。早停可以通过--patience参数设置比如--patience 20表示验证集指标 20 个 epoch 不提升就停止。对于 2059 张图像的数据集建议 patience 设在 15 到 25 之间避免训练资源浪费。3.4 模型验证与指标解读训练完成后用val.py在测试集上评估python val.py \ --data ./dataset/data.yaml \ --weights runs/train/fire_smoke_exp/weights/best.pt \ --img 640 \ --task test输出会包含每个类别的 Precision、Recall、mAP0.5、mAP0.5:0.95。对于火灾检测Recall 比 Precision 更重要因为漏检的代价远大于误检。如果 Recall 偏低可以降低置信度阈值或者增加包含小目标烟雾的训练样本。4. 推理部署与效果验证模型能不能在实际场景跑起来4.1 单张图像和视频流推理YOLOv5 提供了detect.py做推理python detect.py \ --weights runs/train/fire_smoke_exp/weights/best.pt \ --source ./test_images \ --img 640 \ --conf 0.25 \ --iou 0.45 \ --save-txt \ --save-conf参数说明--source可以是单张图像、图像目录、视频文件或摄像头索引。--conf 0.25置信度阈值。火灾场景建议设低一点比如 0.2减少漏检。--iou 0.45NMS 的 IoU 阈值。烟雾区域重叠多的时候可以适当提高。--save-txt保存检测框坐标到 txt方便后续分析。如果要在视频流上做实时检测可以把--source设为0摄像头或 RTSP 流地址。但要注意YOLOv5s 在 640 分辨率下单张 GPU 推理速度大约 5 到 10 毫秒CPU 上可能到 100 毫秒以上。边缘设备建议用 TensorRT 或 ONNX Runtime 加速。4.2 模型导出与边缘端部署YOLOv5 支持导出 ONNX、TensorRT、CoreML 等格式python export.py \ --weights runs/train/fire_smoke_exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1 \ --simplify导出 ONNX 后可以用 ONNX Runtime 在 Python 或 C 里加载。如果部署到 Jetson 等边缘设备建议导出 TensorRT engine推理速度能提升 2 到 3 倍。导出时注意--img要和训练时一致否则精度会下降。4.3 误检与漏检的排查方法实际场景中火灾烟雾检测模型容易把云、雾、蒸汽、橙色灯光误判为烟雾或火焰。排查方法收集误检图像看是否集中在某些背景。如果是把这些背景加入训练集作为负样本。检查标注质量。有些烟雾边界模糊标注框可能过大或过小导致模型学到错误的特征。调整置信度阈值和 NMS 参数。误检多就提高--conf漏检多就降低--conf。用 Grad-CAM 可视化模型关注区域确认模型是否真的在看烟雾区域而不是背景纹理。5. 避坑与常见问题血泪经验换来的 5 条排查清单5.1 标签类别 ID 从 1 开始导致训练崩溃现象训练启动后报AssertionError或IndexError提示类别 ID 超出范围。原因VOC 或 COCO 转换时类别 ID 可能从 1 开始而 YOLOv5 要求从 0 开始。解决在转换脚本里统一减 1或者检查data.yaml的nc是否等于最大类别 ID 加 1。5.2 图像和标签文件名不匹配导致大量样本被丢弃现象训练时提示No labels found或ignoring corrupted image实际参与训练的样本远少于 2059。原因图像是.jpg标签是.txt但文件名前缀不一致比如图像叫fire_001.jpg标签叫fire_001_voc.txt。解决写脚本批量重命名标签文件去掉多余后缀确保stem完全一致。5.3 验证集 mAP 震荡不收敛现象训练损失正常下降但验证集 mAP 在 0.3 到 0.5 之间反复跳动。原因验证集太小或者验证集和训练集分布差异大。2059 张图像如果验证集只有 100 张指标波动会很明显。解决增大验证集比例到 15% 到 20%或者用 K 折交叉验证。同时检查验证集是否包含训练集里没有的场景。5.4 推理时检测框大量重叠现象同一团烟雾被检测出多个框NMS 没有有效合并。原因烟雾区域边界模糊模型对同一目标产生多个高置信度预测。NMS 的 IoU 阈值设得太高。解决降低--iou到 0.3 到 0.4或者改用 Soft-NMS。如果烟雾本身面积大可以适当增大 NMS 阈值但不要超过 0.6。5.5 模型在夜间或低光照场景下失效现象白天检测正常夜间图像几乎检测不到烟雾。原因训练集里夜间样本太少模型没有学到低光照下的烟雾特征。解决收集夜间火灾烟雾图像加入训练集或者在数据增强里加入亮度、对比度扰动。如果无法补充数据可以在推理前做图像增强比如直方图均衡化或 Gamma 校正。6. 进阶技巧用 TTA 和模型集成把 mAP 再提几个点训练完一个 YOLOv5s 模型后如果 mAP 卡在某个数值上不去可以试试测试时增强TTA和模型集成。TTA 的做法是在推理时对同一张图像做多种变换水平翻转、多尺度缩放分别推理后再合并结果。YOLOv5 的detect.py和val.py都支持--augment参数开启 TTApython val.py \ --data ./dataset/data.yaml \ --weights runs/train/fire_smoke_exp/weights/best.pt \ --img 640 \ --augment \ --task test开启 TTA 后mAP0.5 通常能提升 1 到 3 个百分点但推理时间会增加 2 到 3 倍。如果部署环境对延迟不敏感比如离线视频分析TTA 是性价比很高的选择。模型集成则是训练多个不同配置的模型比如 yolov5s、yolov5m 和不同随机种子的 yolov5s然后在推理时对检测框做加权融合。常见做法是用 WBFWeighted Boxes Fusion替代 NMS把多个模型的预测框按置信度加权合并。WBF 对烟雾这种边界模糊的目标效果尤其好因为不同模型可能关注烟雾的不同区域融合后框更完整。我一般会先跑一个 yolov5s 基线记录 mAP 和推理速度然后根据部署设备的算力决定是否上 TTA 或集成。如果设备是 Jetson Nano 这类低功耗平台TTA 基本不用考虑优先把模型量化到 INT8。如果设备是服务器 GPUTTA 加 WBF 能把 mAP 再推高 3 到 5 个点但要注意融合后的框数量会变多后处理逻辑要相应调整。还有一个容易被忽略的点验证集和测试集的划分要固定随机种子。我吃过亏有一次重新划分数据集后测试集 mAP 突然掉了 5 个点排查半天才发现是随机划分导致测试集里多了很多困难样本。后来我习惯把划分脚本和随机种子一起保存确保每次实验可比。希望帮到你。本文还有配套的精品资源点击获取