火焰数据集从标注到训练:格式转换、质量清洗与避坑指南

发布时间:2026/10/17 2:58:03
火焰数据集从标注到训练:格式转换、质量清洗与避坑指南 简介这份火焰数据集面向计算机视觉目标检测开发者专为火焰识别与检测场景打造可直接用于YOLOv5等深度学习模型的训练与验证。数据集包含1553张精选火焰图片每张均配有标注好的txt与xml文件涵盖火焰位置、形状、尺寸等信息并提供明确的标签体系方便研究者快速开展模型训练与评估。包内共5260个文件以jpg图像、txt标签、xml标注三大类型为主整体约194MB文件结构清晰适合作为火灾预警、视频监控等场景的算法训练基础数据。在YOLOv5上的实测结果显示mAP.5达到0.953mAP.5:.95为0.679验证了数据质量与标注精度。目前已有4901人学习下载无论是入门目标检测还是优化火焰识别精度这份数据集都能提供可靠支撑帮助开发者省去采集与标注时间聚焦模型调优与实际部署。1. 火焰数据集带标签的数据才是检测模型能用的燃料做火焰检测的人迟早会撞上同一个现实模型结构是开源里最不缺的东西缺的是能直接喂进去练的火焰数据集。火焰不像猫狗那样轮廓清晰它半透明、边缘模糊、形态每秒钟都在变同一个火苗在不同光照下拍出来完全是两回事。如果你手里拿到的标注是把烟雾也框进火焰框里的那种训练出来的模型一到现场就会错得离谱。这篇文章就是围绕火焰数据集含标注好的标签展开的讲清楚这类数据到底是什么格式、怎么整理、怎么训练、以及最容易在哪里翻车。适合正在做火灾预警、安防监控、边缘端火焰识别想用现成标注数据快速跑通但又怕被数据坑一把的开发者。2. 火焰数据集里有什么标注格式、类别定义与标签质量2.1 先认识三种主流标注格式拿到任何火焰数据集含标注好的标签第一步不是急着训练而是先搞清楚标注文件是什么格式。目标检测领域常见的标注格式就三种VOC格式、YOLO格式、COCO格式。火焰数据集在市面上大多以VOC或YOLO格式存在COCO格式也不少尤其当数据是从通用目标检测数据集里筛出来的子集时。三种格式的区别主要在标签存储方式格式标签文件坐标表示常见配套工具VOC每张图一个XML左上角x、y和右下角x、y像素绝对值LabelImgYOLO每张图一个TXT归一化中心点x、y和宽高各类训练框架原生支持COCO整个数据集一个JSON左上角x、y和宽高像素绝对值labelme、CVAT导出我一般拿到数据会先随便抽三张图分别看它的XML或TXT内容。YOLO格式的TXT每一行是一个目标五个数字依次是类别id、归一化中心点x、归一化中心点y、归一化宽度、归一化高度。这种归一化坐标对训练框架最友好因为不需要在数据加载时再做一次像素到比例的换算。火焰数据集的标签类别通常比较单调最常见的是单类fire多一点的会带上smoke。有些数据集会把fire和flame分成两类但实际训练里这两类在视觉上几乎没有边界强行分开只会让模型学得混乱。我的习惯是拿到这种数据先看一眼类别分布如果flame和fire的样本量差距不大直接合并成一个大类反而省事。2.2 火焰标注的质量问题边界、半透明与烟雾火焰标注最大的难题是边界定义。火焰本身是发光的气体边缘是渐变的不像人、车、猫有清晰的轮廓线。不同的人标注同一张火焰图片框的大小可能差出30%这直接决定训练出来的模型定位准不准。目前行业内比较能被接受的标注标准是标注框紧紧包住火焰的发光核心区域也就是火苗亮度明显高于背景的那部分不要把外围半透明的余晖框进来。如果数据里把整个火团周围一圈暗红色区域都框进去了模型学到的特征就会偏向大面积颜色区域而不是火焰结构。烟雾是另一个大坑。很多火焰数据集的标注人员会把烟雾也算进fire类因为烟雾确实是火灾的重要特征。但从检测模型的角度看烟雾和火焰是两种完全不同的视觉纹理火焰是高频变化的亮斑烟雾是低频的灰白色块。如果把烟雾框进火焰标签模型会同时学「亮斑火」和「白块火」部署后对着蒸汽、雾气、云朵一顿乱报。所以拿到数据集的第一件事不是看数量而是抽一百张图出来做标注质量复盘。看两类问题框是否紧贴火焰发光核心、框内是否混入了烟雾或大面积反光。如果数据量大没法全部人工看可以画一个框尺寸分布直方图火焰目标通常呈现小尺寸居多一旦发现大量超大框占比就要警惕是标注人员把周围环境一起框进去了。3. 从原始标注到训练集目录划分与VOC/COCO格式转换脚本3.1 标准的目录结构与数据划分不管原始数据集是哪种格式进训练之前我都建议先整理成一套统一的目录结构。这套结构后续接任何训练框架都不用再改无非是框架读取时多写几行解析代码。fire_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── annotations/ │ ├── train.json │ └── val.json └── data.yamlimages和labels按train、val、test三个子目录平行存放这是YOLO系列常见的目录约定annotations目录放COCO格式的JSON方便后续做可视化或调框架时不至于找不到标签。data.yaml是训练时的数据描述文件指定了类别名、类别数和图片路径。数据划分这里有一个火焰场景特有的原则一定要按视频源划分不能按帧随机划分。火焰数据集大量来自监控视频抽帧同一段视频里相邻帧之间高度相似如果随机切分训练集和验证集里会出现同一场火灾的连续帧验证指标会虚高到没有参考价值。正确做法是先看数据集的图片命名或目录结构把同源视频的帧归到同一组再整组划分。3.2 VOC转YOLO格式脚本与参数VOC格式的XML转换为YOLO格式的TXT是整理火焰数据集时最常写的一段脚本。转换逻辑本身不复杂但有几个细节容易错XML里的坐标是绝对像素值转到YOLO必须除以图片宽高做归一化多个标注框要逐个处理类别id要和训练配置里的顺序保持一致。import os import xml.etree.ElementTree as ET from pathlib import Path def voc_to_yolo(xml_path, img_width, img_height, out_path, class_map): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_map: continue # 跳过不关心的类别 box obj.find(bndbox) x_min float(box.find(xmin).text) y_min float(box.find(ymin).text) x_max float(box.find(xmax).text) y_max float(box.find(ymax).text) # 裁剪到图片边界防止越界标签 x_min max(0, x_min) y_min max(0, y_min) x_max min(img_width, x_max) y_max min(img_height, y_max) # 转为YOLO归一化格式 dw 1.0 / img_width dh 1.0 / img_height cx (x_min x_max) / 2.0 * dw cy (y_min y_max) / 2.0 * dh w (x_max - x_min) * dw h (y_max - y_min) * dh cls_id class_map[cls_name] lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) return len(lines)代码的关键点有两个一个是边界裁剪火焰数据里经常出现标注框略微超出图片范围的情况尤其在火焰很大、占满画面时标注人员可能直接把框拖到画布边缘不做裁剪训练时容易报错另一个是class_map过滤如果一个数据集里除了fire还有大量无关类别可以直接在转换阶段把它们丢掉避免污染训练。我用的class_map通常是{fire: 0}或{fire: 0, smoke: 1}具体看训练任务。如果做的是纯火焰检测单类就够了如果做火灾预警需要把烟也识别出来那就双类。注意类别顺序一旦定了就别在中途改否则之前训出来的模型权重再用就要重新映射输出头。转换完成后一定要抽查结果。我会把一张图片和它转换出的TXT标签用OpenCV画框回显看框的位置是不是和原图匹配。这一步虽然土但能一次性检查出坐标换算错误、宽高颠倒、类别id错位三类问题。3.3 COCO格式的检查与修复COCO格式的JSON比VOC更灵活但灵活性带来的是更容易出隐形问题。火焰数据集里COCO格式常见的坑有bbox面积出现负数、宽高为零、类别id在JSON和训练配置之间对不上、图片文件名和JSON里的file_name不一致。直接拿这种数据训练轻则loss震荡重则训练直接崩掉。import json from collections import Counter with open(fire_annotations.json) as f: coco json.load(f) id_to_name {c[id]: c[name] for c in coco[categories]} img_id_to_name {img[id]: img[file_name] for img in coco[images]} category_count Counter() bad_bbox 0 area_count Counter() for ann in coco[annotations]: category_count[id_to_name[ann[category_id]]] 1 x, y, w, h ann[bbox] if w 0 or h 0 or x 0 or y 0: bad_bbox 1 area w * h bucket small if area 32 * 32 else (mid if area 96 * 96 else large) area_count[bucket] 1 print(类别分布:, category_count) print(非法框数量:, bad_bbox) print(目标尺寸分桶:, area_count)这段脚本输出三个关键信息类别分布能看出数据是否均衡非法框数量能快速定位JSON里是否混入了错误标注目标尺寸分桶能告诉你这个数据集的火焰目标整体偏大还是偏小。如果small占比超过70%后续训练必须把输入分辨率提上去或者对原图做切块处理。尺寸分桶这个统计对火焰检测尤其重要。火焰在监控画面里常常是远处一个小亮点小目标占绝对多数如果数据里large占比高说明样本大多来自近景火焰训练出来的模型对远距离小火焰基本无感。提示COCO里的bbox坐标是左上角x、y和宽高和VOC的右下角坐标不同。转格式时最容易错的就是忘记这个区别把VOC的x_max直接当宽高写进JSON。4. 用火焰数据集把训练跑通最小配置、输入尺寸与增强策略4.1 数据配置与训练命令目录整理好了、标签格式也统一了接下来就能进入训练环节。火焰检测最常见的落地场景是监控视频里的实时预警训练框架选YOLO系列最省事生态成熟、部署资料多、对边缘设备也友好。我一般会先跑通一个最小配置确认数据链路通畅再去调精度。yolo detect train \ datafire_dataset/data.yaml \ modelyolov8s.pt \ imgsz640 \ epochs50 \ batch16 \ projectruns/fire \ namebaselinedata.yaml是训练的数据描述文件里面必须包含三条信息训练集图片路径、验证集图片路径、类别定义。常见写法是train: /data/fire_dataset/images/train val: /data/fire_dataset/images/val nc: 1 names: [fire]注意train和val指向的是images目录而不是labels目录框架会默认在相同路径下找labels文件夹。如果目录结构对不上训练时报错说找不到标签九成是这里配错了。第一次训练建议只跑50个epoch目的是验证数据加载没有问题看loss能不能正常下降。如果前几个batch就出现loss为nan或剧烈震荡先别急着调参数回头查标签文件是否出现空文件、越界坐标、类别id超出nc范围。4.2 针对火焰的输入尺寸与增强策略imgsz是最值得花时间调的一个参数。火焰目标在监控画面里普遍偏小640分辨率下一个小火苗可能只占十几个像素模型很难学到有效特征。我的经验是如果训练集里small占比高把imgsz提到960甚至1280一般在同配置下能把小目标mAP提升8到12个点。代价是显存占用变大、训练变慢但对火焰检测这种对误报敏感的场景划算。数据增强方面火焰数据集有一个容易被忽略的特殊性增强手段不能破坏火焰的视觉特征。color augmentation方面色调、饱和度的小幅调整是安全的但大幅度改变色调会把火焰的橙色特征抹掉模型就不知道该学什么了。翻转方面左右翻转在大多数场景可用上下翻转要慎用因为火灾检测里火焰的形态和重力有关倒着的火焰不符合现实分布。mosaic增强需要单独讨论。mosaic把四张图拼成一张对丰富背景多样性很有帮助但它同时也会把火焰切碎如果拼图切在火焰中间标签区域里就只有半个火苗。火焰不像物体有完整的结构先验半个火苗样本反而会误导模型。我习惯把mosaic概率调到0.3以下或者在前10个epoch关闭后期再开启做细调。4.3 验证集的选法按场景分而不是乱序分验证集的划分直接决定你看到的指标可信不可信。火焰数据集的验证集不能简单地随机抽10%那样几乎必然出现同视频相邻帧同时落在训练集和验证集的情况。正确做法是先按场景维度分组室内厨房、室外开阔地、夜间、森林、工业厂区等场景各归各的再从每个场景组里按比例抽帧做验证。这样验证集里的样本分布和真实部署场景更接近指标才可信模型过拟合在某个特定场景时也更容易暴露出来。我在实际项目里会额外保留一批完全不进训练流程的留出集专门用来做最后的验收。这批数据可以是另一个完全不相干的摄像头拍的画面甚至是从网上的公开火焰视频里抽的图。留出集的作用是防止你在调参过程中无意中对着验证集过拟合每次改完参数跑完验证集觉得不错再用留出集打一次分分数明显下降就说明模型开始记忆验证集了。5. 火焰检测训练中的五个翻车点与排查方法5.1 烟雾被标成火焰模型变成「烟雾报警器」最典型的翻车现象训练时loss降得很漂亮验证集mAP也不错部署到现场后对着一股白蒸汽疯狂报警。查下来根子往往在数据集标注标注人员把火灾里的烟雾也框进了fire类。模型学到的不是火焰亮斑而是灰白色半透明团块所以蒸汽、云朵、雾霾全会触发预判。排查方法是做一次误检样本收集把所有假阳性图片单独拉出来看。如果假阳性图片里灰白色团块占比高基本就是标签混入了烟雾。解决分两步第一步是清洗数据集把fire类别标注重新过一遍只保留火焰发光核心区域第二步是给数据集增加smoke类让烟雾成为可识别的独立对象而不是被硬塞进fire里。5.2 全屏晚霞、红色灯光误报火焰的颜色特征太强了强到模型很容易走捷径看到大面积的橙红色就报火警。晚霞下的天空、红色霓虹灯、暗红色墙面在模型眼里都是高响应区域。这个翻车在外场监控里极其常见。根子是训练数据里缺乏难负样本。如果你的验证集里恰好没有晚霞和红色灯光模型就会觉得「橙色火焰」这个规律是成立的。解决方法是做负样本挖掘从误报现场收集一批红色但不含火焰的图片标成背景类放进训练集里重新训练。这些负样本不需要多几百张就能显著压低误报率关键是场景要贴近部署环境。5.3 视频相邻帧泄漏导致指标虚高现象是训练和验证都显示mAP达到0.8以上很高模型一到新的监控点就原形毕露。原因几乎总是数据划分时没有按视频源隔离训练集和验证集里混着同一段视频的相邻帧验证分数本质上是闭卷考试变开卷考试。排查方法是按图片文件名里的视频来源字段做一次分组统计看验证集和训练集是否有同源视频。如果数据集的命名是连续帧号直接用文件名前缀做groupby就能看出来。解决就是把按帧划分改成按视频源划分整段视频要么进训练要么进验证不允许串场。5.4 目标尺寸失衡小火焰目标全漏训练样本里如果有大量近景火焰、少量远景小火焰模型参数会偏向大目标拟合对画面角落那个十几像素的小火苗完全没有响应。表现为验证集mAP尚可但在实际监控画面中远距离小目标几乎全部漏检。原因不只是样本数量还有小目标样本在resize时被压缩成了几乎看不见的噪点。解决有三板斧一是把远端火焰样本单独抽出来做过采样二是把imgsz提到960或1280三是对训练图片做滑窗切块把大图切成带重叠的patch再训练这样小火焰在patch里变成中等大小的目标模型学起来轻松得多。5.5 标签框「离火三分」定位精度上不去模型检测出来了但框和真实火焰总有一圈偏移交并比上不去跟踪模块也跟着抖。这个现象在火焰检测里尤其常见因为前面说过火焰边界是渐变的不同标注人员对「火焰边界」的理解偏差很大。翻车根源是标注标准不统一有人框核心亮区有人框外围光晕。解决是定一个硬性标注规范对着截图框必须紧贴亮度最高的核心区域外圈半透明部分宁可不框也不能多框。然后全量检查一遍标注把明显松垮的框删掉重标。这个工作虽然费时但做完之后模型定位精度的提升是肉眼可见的。6. 验证模型别只看mAP场景分桶、硬样本挖掘与负样本回灌训练结束后验证工作比训练本身更考验工程能力。火焰检测模型最重要的是在真实场景里不漏报、不误报单看一个mAP数字根本反映不了这两点。我现在的习惯是把验证拆成三个动作每次训练完都走一遍。第一个动作是场景分桶统计。把验证集按场景分成室内近景、室外开阔、夜间远距、工业烟雾干扰四组分别计算每一组的召回率和误报率。如果室外开阔组召回率明显低于其他组说明模型缺少该类场景样本如果夜间组误报率偏高说明模型对灯光和火焰的区分没有学好。分桶统计可以做成一个简单的脚本读预测结果按图片名匹配场景标签输出每个桶的指标五分钟就能跑完。第二个动作是硬样本挖掘。把推理结果里置信度在0.3到0.7之间、预测正确的样本挑出来这些虽然不是错题但也没学扎实它们共同特征是特征不够鲜明。把这些硬样本回灌到训练集里适当提高采样权重是成本最低的精度提升手段。火焰检测里这类样本通常是远距离小火焰、被遮挡的火焰、强光下的暗火。第三个动作是负样本回灌把误检的图片收集起来按场景聚类挑出最有代表性的几十张标空标签放回训练集。负样本回灌时要注意控制比例一般不超过训练集总量的10%否则模型会变得过于保守误报低了召回也跟着掉。我有个习惯是给这些负样本单独建一个目录每次训练都带上但不混进主数据集的统计里方便单独评估它们对指标的影响。最后说一个我自己的习惯每次拿到新的火焰数据集含标注好的标签第一件事永远是做标签可视化画类别分布直方图和框尺寸分布这两张图的结论决定后面所有流程如果小目标占比过半就先规划切块方案再去碰网络和参数顺序反了往往白跑一轮实验。这个习惯帮我避开了很多次「看起来指标不错、现场一测就崩」的尴尬希望也能帮到你。本文还有配套的精品资源点击获取