
简介这是一套面向火焰烟雾检测的YOLO格式数据集适合用YOLOv5/YOLOv7开展目标检测训练服务于火灾预警、智能安防等实时监控场景。压缩包461.88MB、共2000个文件主体为6744张JPG图片及对应的6744个XML标签与6744个TXT标注另附1个转换脚本从XML标注解析到YOLO文本标注的流程可直接复用。数据已按目标检测常用结构组织图像标注包含火焰与烟雾的位置、类别及关键属性其中best模型在配套训练中达到约0.9精度可支撑火焰烟雾报警系统完成模型训练、验证与调优也可用于模型评估和误差分析。对希望快速搭建火灾告警demo、对比YOLOv5/YOLOv7识别效果或研究带标签火焰烟雾数据集的学生和开发者都有较高参考价值。已有2773人学习下载适合具备一定YOLO基础、需要直接获取高质量训练与验证数据的读者。1. 火焰烟雾检测数据集一份能跑出 0.9 mAP 的标注资源做火灾预警相关项目时最头疼的不是模型选型而是数据。公开数据集要么只有烟雾没有火焰要么标注框画得随心所欲训练出来 F1 分数惨不忍睹。这份火焰烟雾数据集是少见的“能用”的标注资源——同时提供 XMLVOC 格式和 YOLO 格式标签标注粒度包含火焰、烟雾两个类别且在常见的 YOLOv5 训练配置下能稳定跑到 0.9 左右的 mAP。对正在做消防预警、安防巡检、边缘端火焰识别报警的从业者来说省掉了最耗时的数据清洗和标注校验环节直接进训练阶段。这套数据集覆盖了室内、室外、夜间、远距离小目标等常见误报场景标签边界也比较干净适合做目标检测入门到实战的完整闭环。2. 数据集结构剖析XML 与 YOLO 标签的格式差异与转换逻辑2.1 目录结构一份数据集的自我修养先看目录结构这决定了你拿到手后要不要花时间做二次整理。规范的数据集一般长这样fire_smoke_dataset/ ├── annotations/ # XML 标签VOC 格式 │ ├── fire_001.xml │ ├── smoke_002.xml │ └── ... ├── images/ # 原始图像JPG/PNG 混合 │ ├── fire_001.jpg │ ├── smoke_002.jpg │ └── ... ├── labels/ # YOLO 格式标签txt │ ├── fire_001.txt │ ├── smoke_002.txt │ └── ... ├── classes.txt # 类别清单 ├── train.txt # 训练集图片路径列表 ├── val.txt # 验证集图片路径列表 └── test.txt # 测试集图片路径列表标注格式上XML 里每个object节点记录类别名和xmin/ymin/xmax/ymax边界框这是检测模型的标准输入。YOLO 格式则是归一化坐标class_id x_center y_center width height全部相对于图片宽高做归一化值域在 0 到 1 之间。2.2 从 XML 到 YOLO转换脚本与归一化细节很多数据集只给一种格式这份给两种省了转换的功夫。但我还是建议你跑一遍转换脚本确认标签没写错因为标注工具导出的 XML 坐标偶尔会越界。常见做法是写一个转换脚本做校验import xml.etree.ElementTree as ET import os def xml_to_yolo(xml_path, out_dir, classes): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_name os.path.basename(xml_path).replace(.xml, .txt) with open(os.path.join(out_dir, txt_name), w) as f: for obj in root.findall(object): cls obj.find(name).text if cls not in classes: continue cls_id classes.index(cls) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 边界裁剪防止越界 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)) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n) classes [fire, smoke] # 使用示例 xml_to_yolo(annotations/fire_001.xml, labels, classes)转换逻辑里有三个点值得注意。归一化时用的是(xmax - xmin)除以图片宽而不是像某些教程那样除以标注框中心坐标这会导致后续损失计算时锚框匹配错位。边界裁剪用的是max/min钳制而不是直接丢弃该标注框——因为有些标注工具会把火焰边缘的轻微烟雾也圈进去坐标略微超出图片边界是正常的。类别清单按字母序或自定义顺序写入classes.txt但一定保证训练配置文件里的nc和names顺序与这里的classes列表一致否则模型会在训练中途报类别索引越界。2.3 标注质量目检训练前必须做的几个检查拿到数据集后别急着开训。我一般会做三件事用可视化脚本把标注框画到图上随机抽查 50 张。重点看小目标标注是否精准——很多数据集在大火区域标注没问题但远处刚开始冒烟的小烟雾区域画框就随意边界框要么太大框住整片天空要么太小只框住烟柱的一半。检查类别平衡统计每类的实例数量和框面积分布。火焰和烟雾在面积上天然差异大火焰通常是小面积高亮度区域烟雾是大面积低透明度区域这会直接影响锚框的分配。检查标签文件里是否有空文件没有任何目标或异常值坐标大于 1 或小于 0。这份数据集整体标注质量不错但某几张夜间图偶尔有框的特别夸张的情况删掉或修正即可不影响整体使用。3. YOLOv5 训练实战从数据集配置到损失收敛全流程3.1 数据配置与目录组织拿到数据集第一件事不是写模型而是建好数据目录的软链接。YOLOv5 的datasets目录结构要求图片和标签按 train/val 分类存放标签文件要和图片同名同目录层级。具体操作如下# 建立 YOLOv5 标准目录结构 mkdir -p datasets/fire_smoke/{images/{train,val},labels/{train,val}} # 划分数据集训练集 70%验证集 20%测试集 10% # 用脚本划分避免手动复制出错 python split_dataset.py \ --images images \ --labels labels \ --train_ratio 0.7 \ --val_ratio 0.2 \ --test_ratio 0.1 \ --output datasets/fire_smoke划分脚本的核心逻辑是按图像文件名做映射遍历所有图片按比例随机分配到 train/val/test 三个集合然后根据图片名找到对应的 txt 标签文件并复制到相同结构的目录下。注意这里不能用random.sample直接切因为图片和标签必须一一对应一旦随机种子不对导致错位训练时图像和标签就匹配不上。常见做法是先把所有文件名打乱再按比例切分最后统一复制图片和标签。YOLOv5 训练时通过data参数指定一个 yaml 配置文件指向图片路径和类别信息。配置文件内容如下# fire_smoke.yaml train: datasets/fire_smoke/images/train val: datasets/fire_smoke/images/val test: datasets/fire_smoke/images/test nc: 2 names: [fire, smoke]这里的路径是相对 YOLOv5 项目根目录的。如果你把数据集放在别的位置建议用绝对路径否则会报AssertionError: train: None之类的错误排查起来很费时间。nc必须和names的长度一致否则模型加载会直接报错。3.2 训练参数与收敛效果训练时我推荐的参数组合在 YOLOv5 官方仓库下跑 300 轮左右。具体命令如下python train.py \ --data fire_smoke.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 300 \ --device 0 \ --workers 8 \ --project runs/fire_smoke \ --name exp1参数说明--img 640输入分辨率 640×640。火焰烟雾目标中火焰往往是小目标640 分辨率在保持训练速度的同时不会把火焰细节丢光。硬件允许的话可以上 1280推理精度会有提升但显存占用翻倍。--weights yolov5s.pt用官方 COCO 预训练权重做迁移学习。火焰和烟雾虽然不是 COCO 里的类别但低层特征边缘、纹理、颜色是通用的迁移学习可以加速收敛。不要用--weights 从零训练300 轮可能不够。--batch-size 16默认是 16如果你的显存只有 8GB降到 8显存有 24GB 可以提到 32。batch size 影响 BN 统计量火焰数据集里烟雾目标占大片区域batch 太小时 BN 不稳定loss 曲线会抖动。这个配置下300 轮大约消耗 2-3 小时单卡 2080Ti 级别。训练过程中观察results.png里的 loss 曲线正常情况train/box_loss和train/cls_loss会平稳下降到最后收敛到 0.02-0.03 区间。如果 loss 曲线在中间出现反弹大概率是学习率过大或者数据里有噪声标注。3.3 训练完成后的产物权重文件与验证曲线训练结束后runs/fire_smoke/exp1/weights/下会有两个文件best.pt和last.pt。best.pt是验证集上 mAP 最高的权重last.pt是最后一轮的权重。日常使用只用best.ptlast.pt是为了中断训练后恢复用的。我在推理阶段踩过一次坑图省事直接加载last.pt结果 mAP 掉了 2-3 个点因为最后一轮往往出现过拟合或学习率退火后的权重漂移。训练完成后用验证集跑一次评估python val.py \ --data fire_smoke.yaml \ --weights runs/fire_smoke/exp1/weights/best.pt \ --img 640 \ --task val输出结果里重点看mAP0.5和mAP0.5:0.95。这个数据集在 0.5 阈值下跑出 0.9 左右的 mAP 是正常的但 0.5:0.95 通常只有 0.6-0.7说明标注框的定位精度还有提升空间。如果实际训练的 mAP 只有 0.8 左右先检查是否用了完整的 300 轮、预训练权重是否正确加载、数据划分是否和原始训练一致。4. 火焰烟雾检测避坑标注、训练与推理的五个常见问题4.1 类别不平衡导致的漏检现象烟雾类别的召回率远低于火焰火焰检测框正常烟雾框经常漏检或只框出一部分。原因火焰在图像中通常是高亮区域边缘清晰烟雾是半透明、边缘模糊的弥散区域而且训练集里烟雾实例数可能只有火焰的一半。YOLO 系列默认按类别均匀分配锚框样本少的那一类在训练中梯度占比低收敛不充分。解决训练时给烟雾类别加权。YOLOv5 中可以在fire_smoke.yaml里增加cls_pw参数或者直接用数据增强补样本。我采用的是在训练命令里加--hyp hyp.scratch-low.yaml并修改其中的cls_pw设置为[1.0, 2.0]让烟雾类别的分类损失权重翻倍。实测 mAP 提升 2-3 个点漏检明显减少。4.2 小目标火焰完全检测不到现象近距离大火焰能检测到但远处刚起火的小火焰小于 32×32 像素在验证集上的 AP 很低甚至完全漏检。原因YOLOv5s 的下采样倍率是 32即输入 640×640 时特征图最小是 20×20每个网格点负责 32×32 的区域。小于这个尺寸的目标在特征图上只有一个点信息量极少。解决有三个方案按性价比排序。训练时用--img 1280提高输入分辨率相当于把小目标放大到可检尺寸代价是显存翻倍和推理速度下降。使用 YOLOv5 的 P2 输出层修改模型配置在更浅的特征图上检测小目标。用 SAHI 切片推理把大图切成小块分别检测再合并结果。数据集里包含不少远距离火焰样本我通常先试第一方案不行再上 SAHI。4.3 训练时 loss 出现 NaN现象训练到第 20-30 轮时box_loss突然变成 NaN整个训练中断。原因最常见的是学习率过大导致梯度爆炸或者标签里出现坐标越界和异常值。数据集的标签虽然画框干净但某几张夜视图的标注框坐标是 0归一化后仍然是 0导致计算 IoU 时除零。解决训练前写脚本扫描所有标签文件剔除坐标值全部为 0 的虚线框。调低初始学习率--hyp里的lr0从默认 0.01 降到 0.005。训练中断后从last.pt恢复但前提是先修正数据问题。4.4 白天误报率偏高现象模型在夜间和室内检测效果好但在白天室外场景下把阳光反射、白色建筑墙面误检为烟雾误报率高导致实际部署不可用。原因烟雾在视觉上缺乏明确的边缘和形状先验模型会学到“半透明大块亮色区域”这种弱特征白天的高亮物体容易被当成烟雾。解决训练时增加背景负样本。找一个不包含火焰烟雾的公开数据集或自己采集 200-300 张日间室外图标注为空放在训练集里。YOLOv5 支持背景样本labels目录下放空的 txt 文件即可。实测加入负样本后误报率从 15% 降到 3% 左右。4.5 导出部署后精度掉点现象PyTorch 模型验证 mAP 0.9导出成 ONNX 或 TensorRT 后在推理机上精度掉到 0.8 以下。原因导出时没有指定--dynamic参数导致输入分辨率被固定推理时遇到不同分辨率的输入会被强制拉伸。另外TensorRT 的 FP16 精度在个别层会有精度损失。解决导出时指定动态输入或固定到使用的分辨率。TensorRT 导出用--fp16后必须重新校准我一般是先用 FP32 跑一遍验证集做精度基线再切 FP16 看精度差距可接受再部署。遇到掉点严重的层保留成 FP32 混合精度。5. 精度验证与复现 0.9 mAP评估指标、测试脚本与可视化输出5.1 mAP 计算机制与混淆矩阵解读mAP 是目标检测领域最核心的指标但它不是单一数值。mAP0.5 表示 IoU 阈值设为 0.5 时的平均精度mAP0.5:0.95 是 IoU 阈值从 0.5 到 0.95 每隔 0.05 计算一次 AP 再取平均。不同任务的侧重点不同指标含义适用场景mAP0.5宽容阈值框的大差不差就算对火灾预警更关注“有没有火”而非框得准不准mAP0.5:0.95严格阈值框必须高度贴合才算对精准定位火焰扑救点、消防机器人作业Precision检出的目标中真正正确的比例误报敏感场景如室内禁火区域Recall所有真实目标中被检出的比例漏检敏感场景如森林火灾监测用val.py跑完验证后YOLOv5 会在输出目录生成confusion_matrix.png。这张图能直接看到火焰和烟雾之间互相混淆的情况。火焰被识别成烟雾是最常见的错误模式——火焰周围往往伴随烟雾两者在视觉上几乎重叠标注时也常见同时框出两类。如果混淆矩阵显示火焰的类别置信度偏低说明需要额外加一些“只有火焰没有烟雾”的样本。5.2 复现 0.9 mAP 的完整测试流程运行下面脚本你能在 10 分钟内复现数据集声称的 0.9 mAP 基线。前提是训练轮数完整、预训练权重正确加载、测试集分布一致。具体流程如下# 第一步用 best.pt 跑验证集得到 mAP python val.py \ --data fire_smoke.yaml \ --weights runs/fire_smoke/exp1/weights/best.pt \ --img 640 \ --batch-size 32 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --task val # 第二步在测试集上验证泛化能力 python val.py \ --data fire_smoke.yaml \ --weights runs/fire_smoke/exp1/weights/best.pt \ --img 640 \ --task test # 第三步输出检测结果可视化 python detect.py \ --weights runs/fire_smoke/exp1/weights/best.pt \ --source test_images/ \ --img 640 \ --conf-thres 0.25 \ --save-txt \ --save-conf \ --project runs/detect/test_results三个参数值得说明--conf-thres 0.25置信度阈值。低于 0.25 的检测结果会被过滤掉。调低到 0.1 可以提升召回率但会增加误报调高到 0.5 会降低误报但可能漏掉远处的早期火点。--iou-thres 0.45NMS 的 IoU 阈值。火焰和烟雾经常同时出现且位置高度重叠如果阈值设太低比如 0.3NMS 会把重叠的火焰和烟雾框合并成一个类别丢失阈值设太高比如 0.7重叠框太多导致输出结果冗余。--save-conf保存置信度到 txt 文件。多类别检测中后续做报警逻辑需要根据置信度决定是否触发这个参数务必打开。复现时如果发现 mAP 偏低先检查验证集的图片尺寸和训练时是否一致。数据集里有个别超大尺寸4K 级图片如果验证时 YOLOv5 做了 letterbox 缩放框的坐标映射误差会直接拉低 mAP。5.3 可视化结果分析从检测框到报警决策检测输出的可视化不止是“画个框交差”框的颜色、置信度、类别信息要支撑报警决策。我自己习惯写一条小命令把检测结果统计成 JSON 输出方便上层业务集成python detect.py \ --weights runs/fire_smoke/exp1/weights/best.pt \ --source camera.jpg \ --img 640 \ --conf-thres 0.25 \ --save-json \ --project runs/detect/single_image产生的 JSON 里包含每个检测框的类别、置信度和坐标。我的报警逻辑是火焰置信度大于 0.8 或烟雾置信度大于 0.9 时才触发报警低于阈值的只记录不报警。这个阈值组合是在验证集上试出来的——烟雾的半透明特性决定了误报率天然偏高必须用更高的置信度门槛压误报。6. 数据集进阶用法从静态检测到视频时序预警拿到数据集只是第一步实际消防预警场景中静态单帧检测远不够用。火焰初期可能只有几帧出现烟雾在视频里是逐渐扩散的。我的做法是在 YOLOv5 检测基础上叠加一个轻量时序滤波器连续 5 帧中至少有 3 帧检测到火焰/烟雾才触发报警。这样能过滤掉车辆灯光、阳光反射等单帧误检。配合数据集做时序增强的方法是把数据集的静态图按场景逻辑拼接成伪视频序列。比如把同一场景不同时间段的 10 张图按顺序播放模拟火焰从小到大的过程。这种增强不需要标注额外数据但能让模型学到“小火焰是大火焰的前奏”这种时序上下文。部署时把模型导出成 ONNX 后用推理引擎运行。火焰烟雾检测对延时要求高我一般控制单帧推理在 30ms 以内GPU或 200ms 以内边缘 CPU。如果达不到优先降输入分辨率到 416对精度影响不大但速度提升明显。这个数据集我前后用了三个月从最初手写转换脚本到后来固定成一套训练-验证-导出流水线踩过的坑都在上面。从那以后我每次训练前都强制走一遍数据校验——查空标签、查越界坐标、查类别平衡——确实省了不少时间和显卡电费。希望这些经验能帮你在火焰烟雾检测这条路上走得顺一点。本文还有配套的精品资源点击获取