
简介面向目标检测与安全监控开发者的火焰烟雾数据集标注包内含2000个XML文件压缩包765.03MB其标注信息对应18800张真实场景下的火焰烟雾图片。文件采用YOLO/VOC通用格式每个XML均记录目标的边界框与类别信息可直接用于YOLOv5、Faster R-CNN等主流模型训练。数据覆盖不同距离与光照条件下的火焰、烟雾样本可提升火灾预警、森林防火等场景的模型泛化能力同时省去自行采集和标注的繁琐工作。目前已有1917人学习下载适合计算机视觉学习者、科研人员及算法工程师快速获取高质量标注数据。 做安防和消防相关项目的人应该都有体会火焰烟雾检测跟普通的目标检测还不太一样——它不仅要求模型认得准还要求尽快报警而且烟雾和火焰在画面上经常是模糊的、半透明的、形态不定的。我自己在做边缘智能盒子项目时就有这个需求花了不少时间整理数据、调模型。今天要聊的就是我手上这套用于YOLO训练的火焰烟雾数据集18800张图片同时给了YOLO和VOC两种标注格式对应TXT和XML文件是目前公开渠道里比较省心的一套数据。这篇文章我打算从数据集本身讲起把格式差异、转换逻辑、训练参数、排坑经验一次说清楚希望给正在做消防预警、明火识别、烟雾报警这类项目的朋友一些实际参考。1. 数据集整体解析18800张图背后的门道1.1 规模与类别设计怎么理解18800张图片这个量级在垂直场景的数据集里算是比较厚道的。一般做火焰烟雾检测最头疼的问题就是数据少且难标注因为火焰边缘不清晰、烟雾没有固定形状标注员如果经验不足画出来的框可能一个比一个离谱。这套数据把图片和标注都整理好了可以直接进训练流程省掉一大半前期时间。从类别设计上来讲火焰和烟雾是两个独立的类别这一点很重要。在标注实践中很多人会把着火点周围的热浪和烟雾中的浓烟区混在一起导致两个类别的特征互相污染。正确做法是火焰框尽量贴着明亮燃烧区域烟雾框覆盖视觉上明显的烟团或烟带。如果数据集的类别划分合理训练出来的模型才可能在告警逻辑上做区分——比如只出烟不出火时可以先预警不直接触发喷淋或断电这类强动作。1.2 TXT和XML两种标注格式的适用场景分析拿到这套数据第一眼会看到每个图片文件名对应两个标注文件一个TXT一个XML。先说YOLO格式的TXT。它的每行结构是 class_id x_center y_center width height所有坐标都归一化到0到1之间。优点非常明显文件体积小、读取快、不需要额外的解析库YOLOv5、YOLOv8这些框架直接就能吃进去。VOC格式的XML则是另一种思路它把标注信息完整地藏在树状结构里图片文件名、来源、图片尺寸、每个目标的类别和绝对像素坐标xmin、ymin、xmax、ymax全都有。相比TXTXML更像一份完整的档案阅读起来直观也方便人眼检查很多老牌的检测项目比如Faster R-CNN的经典实现都依赖这种格式。这两种格式本质上是描述同一批目标框的两种语言。实际使用中不是所有框架都原生支持两种格式比如老版本YOLOv3的代码里就默认读取TXT而有些基于VOC协议做评测的工具又必须吃XML。数据集同时提供两份省去了用户自己转换的环节这算是比较良心的设计。2. 环境准备与格式转换实战2.1 训练环境与显卡选型重点说AMD显卡能不能跑YOLO在讨论格式转换之前先聊一下训练环境因为这个问题几乎每个新手都会问。如果你手头是NVIDIA的卡CUDA和cuDNN装好之后YOLO生态基本畅通无阻。但如果你是AMD的RX 580这类显卡情况会有点微妙——RX 580本身支持DirectML和ROCm但YOLOv5/v8官方默认训练脚本依赖CUDA想在AMD卡上跑起来通常要切换到DirectML分支或者用CPU硬扛。实测下来RX 580在Windows下用DirectML跑YOLOv8s推理能用效率也还行但训练速度会明显比同价位的NVIDIA卡慢而且有些算子在AMD上支持不完整容易出现莫名报错。所以我给的建议是如果是入门学习AMD卡先用CPU训练一小批数据验证流程真正大规模训练还是建议租一台带NVIDIA卡的云主机或者用本地的N卡机器。2.2 从XML到TXTPython转换脚本实现虽然数据集两种格式都给了但实际训练时你可能需要调整类别顺序、剔除部分错误标注或者补充自己额外标注的数据这时候格式转换就是基本功。从XML转TXT核心就是用Python标准库解析XML。import xml.etree.ElementTree as ET import os def xml_to_txt(xml_path, txt_path, class_names): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue cls_id class_names.index(name) bndbox obj.find(bndbox) xmin int(float(bndbox.find(xmin).text)) ymin int(float(bndbox.find(ymin).text)) xmax int(float(bndbox.find(xmax).text)) ymax int(float(bndbox.find(ymax).text)) 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}) with open(txt_path, w) as f: f.write(\n.join(lines)) class_names [fire, smoke] xml_to_txt(000001.xml, 000001.txt, class_names)这个脚本有几个点要注意。第一解析XML前最好先确认根节点结构有些标注工具的size节点可能缺失而YOLO格式的归一化依赖图片宽高一旦缺失就要从图片文件本身去读取否则坐标会算错。第二类别顺序要跟训练配置里的data.yaml保持一致一旦顺序变了之前训练出来的权重就全废了这是最容易踩的坑。2.3 自己补充标注labelme标注后如何转换很多时候公开数据集覆盖不了现场的极端情况比如某个厂房的光线特别暗、或者特定角度的俯视摄像头。这时候就需要自己补数据。用labelme标注时保存的是JSON文件里面是polygon多边形而不是矩形框。转换思路很简单取多边形所有点的外接矩形再按YOLO格式归一化即可要生成VOC XML的话把矩形转成绝对像素坐标按XML结构组织写文件。有一个细节值得提醒labelme画的多边形如果点在图像边缘外接矩形可能超出图像范围YOLO格式的归一化坐标就会大于1或者小于0训练时有些框架会直接报错。所以转换脚本里最好做一次边界裁剪x_center max(0, min(1.0, x_center)) y_center max(0, min(1.0, y_center)) width max(0, min(1.0 - x_center, width)) height max(0, min(1.0 - y_center, height))别小看这个处理没有它我当初训练到第30个epoch时突然报出坐标越界的错误排查了一整天才发现是几条标注数据超界导致的。3. 基于该数据集训练火焰烟雾检测模型3.1 数据集目录组织与配置文件开始训练前先把目录结构理清楚。推荐的做法是datasets/ ├── fire_smoke/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/images放图片labels放对应的TXT标注文件文件名一一对应。YOLOv5/v8的data.yaml配置写法如下path: datasets/fire_smoke train: images/train val: images/val names: 0: fire 1: smoke这里要特别提醒目录层级问题。path指向数据集根目录train和val是相对路径框架会自动拼接。如果你把train和val路径写成了绝对路径换一台机器跑的时候又忘了改报错会非常莫名其妙。3.2 训练参数与关键设置火焰烟雾这个场景跟通用目标检测有些差别主要体现在目标尺度上。大部分监控画面里远距离的火焰只占几十个像素典型的远小目标近距离的火焰可能突然占满半个屏幕。所以我通常不建议直接把分辨率设成416或者512至少用640起步条件允许用1280做高分辨率训练对小目标的召回率提升非常明显。batch size的选择取决于显存大小。24GB显存跑YOLOv8sbatch size可以设在32到64之间8GB显存建议16到244GB显存尽量用8再低的话BN层统计就不稳了。有一个容易被忽视的参数是mosaic增强它能显著提升模型对遮挡、小目标的鲁棒性但在最后20个epoch建议关闭mosaic否则训练收敛会不稳定。损失函数这块YOLOv8默认的组合其实已经够用它内置了分类损失和回归损失CIoU的处理也做得不错。如果你用的是自定义改进版的YOLO也建议优先保留CIoU作为框回归损失它在重叠框、小目标上的梯度表现更稳定。3.3 训练过程监控与评估训练过程不是丢进去就不管了。我最关心的三个指标是box_loss、cls_loss、以及验证集上的mAP50和mAP50-95。火焰烟雾检测属于二分类场景mAP50比mAP50-95更有参考价值因为它主要考核框准不准以及目标有没有被漏掉对轻微定位偏移没那么敏感。我自己训练这套数据时到第80个epoch左右mAP50基本能稳定在0.88到0.93之间。如果发现loss持续下降但mAP不涨十有八九是过拟合或数据分布不均优先检查训练集和验证集有没有重复图片、某一类目标占比是否失衡。火焰和烟雾的数量比例如果悬殊可以考虑给少的那一类增加采样权重这个在YOLOv8里可以通过调整每张图的类别概率间接实现。4. 常见问题与排查技巧实录4.1 XML解析报错怎么处理标签文件用得多难免遇到解析报错。有一种典型的报错是XML Parse Error比如在解析第三方标注工具导出的XML时节点缺失或者非法字符导致解析失败。排查思路分两步先用浏览器或编辑器打开XML文件确认结构是否完整然后检查编码有些工具导出的XML是GBK编码而Python的xml.etree默认按UTF-8解析读进去直接乱码甚至报错。解决方式是在读取文件时指定encodinggbk或者统一转换成UTF-8后再解析。4.2 标签编号与类别映射错乱这是另一个高频问题。当你把多个来源的数据合并进一个训练集时如果来源A的0号类别是fire来源B的0号类别是smoke合并后模型的表现会变得非常诡异典型症状是loss降不下去、验证集mAP忽高忽低。解决办法只有一个任何数据进入训练集之前必须统一做一次类别映射和清洗把TXT中的第一列全部重映射到全局统一的类别ID。4.3 显存不足与训练中断显存不足报错会直接中断训练。除了降低batch size之外有两个实用技巧。一是开启梯度累积让优化器每积累若干步再更新一次等效于单卡跑大batch二是把训练图的缓存方式改成RAM缓存减少数据加载时的临时显存占用。实际在我8GB显存的机器上用梯度累积跑YOLOv8s的1280分辨率训练batch size设成4一样能稳定跑完整个流程。4.4 小目标和密集烟雾的漏检问题密集场景下烟雾目标之间互相重叠模型很容易漏检或把多个目标合并成一个框。我在部署现场经常遇到的是排烟管道附近的一团烟雾被模型识别成一个大框覆盖了旁边的小火苗导致告警延迟。针对这个问题除了提高输入分辨率还可以在训练时适当降低NMS的IoU阈值从默认的0.45调到0.35让重叠目标更容易被保留下来。不过阈值调低后误检框也会变多需要在验证集上反复折中。5. 模型导出与部署建议5.1 导出ONNX与推理优化训练完成后导出模型是落地部署的关键一步。YOLOv8官方支持直接导出ONNX格式命令很简单yolo export modelbest.pt formatonnx opset12导出后建议用onnxruntime或者TensorRT做推理加速。如果是边缘设备优先考虑TensorRT的FP16量化在保持精度几乎不变的前提下推理速度能翻倍。我实测同一个模型NVIDIA Jetson Orin上用FP16的TensorRT引擎跑推理时间从15毫秒降到7毫秒左右完全满足实时视频流的检测需求。5.2 部署时的推理细节调优部署层面容易被忽视的是输入预处理和输出后处理的一致性。训练时如果做了归一化、减均值之类的操作部署端必须写成完全一致的步骤。另外视频流检测场景里建议做帧间隔检测而不是逐帧检测因为火焰烟雾变化相对连续每隔3到5帧检测一次既能降低算力消耗又能避免画面抖动造成的误报。报警逻辑上可以设置连续2到3帧都检测到目标才触发告警这个机制能过滤掉绝大多数瞬时误检。我个人在实际项目中的体会是这套18800张的火焰烟雾数据集在同类公开数据里已经是相当能打的了。只要别急着改结构先把训练流程跑通、把验证指标摸清楚之后再根据自己的场景慢慢补数据和调参效率会高很多。最后再分享一个小技巧如果现场相机拍摄角度是固定的建议在训练集里加入一部分背景帧也就是不含火焰烟雾的纯场景图让模型学会什么都不检测也是正常状态。这个操作能明显减少固定摄像头下因光影变化产生的误报实测效果比我调任何NMS参数都来得直接。本文还有配套的精品资源点击获取