ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

火焰烟雾检测数据集构建与YOLOv8训练实战

火焰烟雾检测数据集构建与YOLOv8训练实战 简介目标检测是计算机视觉的核心任务之一其实际效果高度依赖训练数据的质量与分布。在火灾预警、安防监控等场景中模型往往因缺乏针对性的高质量标注样本而误报频出。如何构建一份覆盖多场景、标注规范统一的火焰烟雾检测数据集并基于YOLOv8等主流框架高效训练是工程落地的关键。数据增强、负样本设计、小目标处理等策略对模型泛化能力影响显著。本文围绕火焰烟雾检测数据集构建展开聚焦标注边界、数据清洗与训练调参实践为开发者提供一套可复用的技术路径。 早两年做消防预警项目的时候我面临的最大问题不是模型选型而是缺数据。市面上的公开数据集要么是通用目标检测要么是烟雾检测的专用集但混在一起能用的、带高质量标注的真不多。后来我花了几周时间整理出一份火焰烟雾已标注数据集共1000张图覆盖白天、夜间、室内、室外、远景、近景等不同场景标注类别只有两个fire 和 smoke格式上同时输出YOLO格式和COCO格式拿到手就能直接开训。这份数据集我自己用下来YOLOv8s在验证集上的mAP50能做到0.78左右效果稳定足够支撑消防预警、安防监控、无人机巡检这类项目的前期验证。这篇文章主要写给下面几类人想用现成数据集快速跑通火焰烟雾检测流程的开发者正在自建数据集、不知道标注规范怎么定的人做边缘端部署需要了解如何用1000张图训练一个可用模型的工程师。我会把数据集的构建思路、标注边界、验证方法、训练实测结果以及踩过的一些坑都交代清楚。1. 为什么要折腾一个火焰烟雾检测数据集背景与需求定位1.1 通用数据集在这个任务上的尴尬很多人一开始会想直接用COCO数据集不行吗COCO里确实有fire分类但问题是火焰烟雾检测和普通物体检测不一样它有很强的场景属性。火灾场景里的火焰往往形态多变、颜色跨度大烟雾更是半透明、无固定轮廓COCO那种以物体为中心的标注方式对火焰烟雾这种边缘模糊、遮挡严重的目标并不友好。实际测试下来直接用COCO预训练权重去识别火灾画面经常把红色灯光、晚霞、甚至橙色广告牌当成火焰误报率高得没法用。还有一个更实际的问题COCO里火焰烟雾相关的图片数量非常少十几个类别共享一个数据集火焰类可能就一两千张而且很多是新闻报道里那种大火场面场景单一。对于做安防或者无人机巡检的开发者来说需要的恰恰是那种“小目标、远距离、背景杂”的真实场景图这些在通用数据集里很难找到。1.2 这份数据集的定位快速验证与场景适配所以我做这份1000张火焰烟雾已标注数据集的时候定位非常明确不是要做一个刷榜用的学术数据集而是做一份覆盖常见误报场景、标注统一、格式干净、开箱即用的工程数据集。1000张图听起来不多但对于火焰烟雾检测这个具体任务来说它是足够的起点。一张图里可以同时出现多个火焰和烟雾目标实际标注出来的目标数量通常在1200到1500个左右。这个数量级有两个好处。第一训练速度快入门级显卡就能在几小时内完成训练和调参方便快速迭代数据增强策略和模型结构第二容易发现问题1000张图如果标注质量不过关模型会在训练时明显暴露错误倒逼你去检查标注规范和数据清洗这个过程中积累的经验比单纯堆数据量更有价值。1.3 适合谁在什么阶段用根据我自己的使用体验这份数据集最适合下面几个阶段刚接触火焰烟雾检测需要一份干净数据跑通YOLO训练全流程做消防预警项目的前期验证用这份数据评估不同模型的精度和速度作为自建数据集的基础先用这份数据训练初版模型再用模型辅助标注自己的业务数据。如果你已经有一两万张业务数据那这份1000张的数据集对你来说可能偏小更适合当预训练数据或者做模型验证直接做最终训练数据会不够用。2. 数据来源与采集思路不只是凑数量还要覆盖场景维度2.1 数据来源的四种途径这份数据集的来源我最终用了四种途径来凑齐1000张每种途径都有它的作用而且缺一不可。第一种是自有拍摄和模拟场景实验。我搭建了一个简易的燃烧实验平台用不同燃料纸张、木材、液体燃料在室外空地拍摄真实的火焰燃烧过程。这部分大约占15%价值在于火焰形态真实、光照变化丰富尤其是夜间场景火焰在暗背景下的轮廓和日间完全不同。第二种是从公开数据集中筛选。市面上有一些开放的目标检测数据集、火灾相关的研究数据集我从中筛选出符合标注规范的图片。筛选时非常严格只保留清晰度高、画面没有严重遮挡的火焰烟雾图片。这里要特别说明筛选的目的不是图方便而是保证数据质量统一避免不同来源的图片分辨率、色偏、压缩噪声差异太大干扰模型训练。第三种是网络公开图片。通过一些素材库下载CC协议授权的火灾、火焰、烟雾相关图片这部分是最大的来源大约占40%。但网络图片有个大问题就是画质参差不齐很多是从新闻视频里截出来的帧本身就带模糊和压缩痕迹。我处理的办法是在预处理阶段做统一缩放和清晰度筛选太模糊的直接丢掉宁缺毋滥。第四种是合成数据补充。我用3D渲染引擎模拟了几种典型场景比如室内垃圾桶起火、园区室外烟雾、夜晚建筑火情等渲染后再标注。这部分占的比例很小5%左右但它有一个独特的作用——解决真实图片里某些极端角度、极端天气条件下数据不足的问题。2.2 负样本设计模型告警准确率的关键这个设计是数据集的灵魂值得单独拿出来讲。做火焰烟雾检测最让开发头疼的往往不是漏报而是误报。太阳光下的红色车漆、晚霞、路灯、橙色施工围挡、红色消防栓、烟囱冒出的白烟——它们在视觉上跟火焰或烟雾都有相似之处模型如果没见过这些必然产生误报。所以我在采集数据时特意加入了超过200张的不含火焰烟雾但容易混淆的负样本图。这些负样本在训练时不会专门标记目标而是作为背景图参与训练模型在样本中反复看到这些易混淆目标并被标注为背景后会逐渐学会区分真正的火焰和相似物。负样本的比例需要控制。我最初试过负样本比例过高导致模型非常保守真正的火焰也漏报后来我把负样本控制在20%左右同时保证正样本和负样本在场景上有一定重叠效果就比较稳了。具体的对比效果在后面训练实测部分会提到。2.3 场景维度拆解怎么让1000张图覆盖足够广为了让1000张图发挥更大的场景覆盖效果我按几个维度对数据做了分布约束维度覆盖情况光照条件白天50%夜间/弱光30%黄昏/背景复杂20%距离尺度近景大目标30%中景40%远景小目标30%场景类型室内15%室外园区40%山林/野外15%城市道路15%工业场景15%干扰项含烟囱、路灯、红色物体等易混淆背景30%天气条件晴天50%阴天30%雾霾/雨天20%目标形态初期小火苗20%稳定燃烧40%浓烟伴随火焰25%纯烟雾15%这样做的好处很明显模型在训练时不会只见过某一类场景后面的泛化能力会好很多。我实测下来用这份数据训练的模型去跑另一个园区监控视频误报率比只用单一来源数据训练的模型低了三成左右。3. 标注边界与类别定义火焰和烟雾最容易标错的地方3.1 两个类别还是三个类别这是一个问题很多人上来就问要不要把火焰细分成“明火”、“暗火”或者“初期火焰”我的建议是别分。1000张图的数据集类别分得越细每个类别的样本量就越少模型反而学不好。火焰烟雾检测的场景里最终部署时要的是“这个画面里有没有火灾迹象”这个二元判断模型内部再怎么细分最终输出也是两个检测框类别fire 和 smoke。但这不代表标注时不需要内部规范。我在标注时额外用了一组标签来记录“火焰阶段”比如初起火苗、稳定火焰、火焰燃烧伴随烟雾这组标签只用作文档记录不参与训练。这样做的好处是模型训练时不会被过细的类别划分干扰但我在分析模型漏报原因时可以按阶段拆分统计定位是哪类火焰最容易被漏掉。3.2 火焰的标注边界怎么框住一团没有固定形状的东西火焰标注最麻烦的问题就是边界。火焰不像人、车那样有清晰轮廓它的外焰是抖动的边缘是半透明的颜色从中心的白黄色渐变到外缘的橙色红色怎么框才算准确我的做法是以火焰不透明核心区域为主体外焰延伸出去的颜色区域如果清晰可见一并纳入边界框。如果外焰部分太淡、几乎透明就不强行纳入宁可稍微框小一点也不要框得过大把背景包含进来。实际测试中发现标注范围稍微保守一点模型学到的是火焰核心特征抗干扰性反而更好。如果标注时把半透明的外焰全部包进去模型就可能把同样颜色偏暖的背景也识别成火焰。还有一点容易忽略一个连贯的火焰区域中间如果有分割但只要视觉上是同一个火源就只打一个框。比如一根木棍上同时烧着好几处火苗如果火苗之间距离很近、边缘相接就合并成一个目标。如果两个火苗颜色、位置上都明显分裂才分开标注。3.3 烟雾的标注边界半透明目标怎么处理烟雾的标注比火焰更头疼。烟雾是半透明的边界完全不可见经常和背景融合在一起。如果照着画面里烟雾的视觉范围去框会把大量背景蓝天、楼房都框进去模型会学到一堆错误特征。我定的规范是只标注烟雾视觉浓度较高、和背景有明显区分度的区域。浓度低、像一层薄纱一样的部分不标注。这样的标注虽然看起来“不完整”但对模型训练更友好因为模型只需要学会识别最重要的烟雾区域不需要处理那些连人都看不清边界的目标。纯烟雾图片画面里没有火焰只有烟雾在数据集中占了15%这些图对于训练模型区分“有烟无火”的场景特别重要。很多火灾初期就是先冒烟后起火模型如果在烟雾阶段就能报警能为人员疏散争取很多时间。3.4 目标太小和严重遮挡怎么标宁可漏标不可错标这是标注过程中最需要克制的地方。1000张图里总会有很多远景小目标比如几十米外的一团火苗在画面里可能只有15x20像素。我的标注下限是目标的最短边在原始图上至少10个像素小于这个尺寸的一律不标。原因是目标太小标注框的偏差本身就会带来很大的IoU误差模型训练时反而会被这些低质量标注干扰。严重遮挡的目标同理。如果火焰被遮挡了大半只能看到一小片颜色边缘我会选择不标。因为标注这种目标得到的训练信号太弱模型学了也学不好。但如果烟雾是主要目标即使火焰被遮挡烟雾本身还是会正常标注因为烟雾在视觉上占了很大面积它有独立的信息价值。我建议所有自建火焰烟雾数据集的开发者在标注规范里必须写明这两条下限规则并且每张图片都经过二次审核。因为标注员如果外包的话或标注工具自动生成的结果往往倾向于把所有看起来像目标的东西都框进去这在火焰烟雾任务里会变成灾难。4. 标注格式、数据整理与自动化检查流程4.1 格式选择为什么同时提供两种主流格式打开数据集你会看到images和labels两个主目录labels下又按YOLO格式和COCO格式分了两个子目录还有一份JSON格式的COCO标注文件和一份label_map.yaml类名映射文件。之所以同时提供YOLO和COCO两种格式是因为实际使用中两种格式各有应用场景。YOLO格式最直接训练YOLO系列模型时不用做任何转换拉下来就能跑COCO格式则适合用mmdetection、Detectron2这类框架也方便做数据增广工具链的对接。两份标注是同一批标注结果通过脚本自动转换的不存在同一张图两种标注不一致的问题。目录结构是这样的flame_smoke_dataset/ ├── images/ │ ├── train/ # 800张 │ ├── val/ # 100张 │ └── test/ # 100张 ├── labels/ │ ├── yolo/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── coco/ │ ├── train.json │ ├── val.json │ └── test.json ├── label_map.yaml └── README.md图片全部统一为JPG格式分辨率统一缩放到1280x720既保留足够的细节又不至于让文件太大。训练时直接按需要resize到640或1280即可。4.2 数据处理流水线从原始图片到清洗过的训练集整个数据整理过程我分成了五个步骤每个步骤都有实际作用第一步是去重。网络图片和公开数据集可能有交叉重复的图片我用感知哈希算法做过一次相似度去重确保1000张图没有内容几乎一样的重复图。这一步很多人会忽略但它对数据有效性的影响很大。第二步是清晰度筛选。用拉普拉斯算子计算图片的方差低于阈值的模糊图直接剔除。火焰烟雾场景里夜间拍摄的图片通常偏暗偏模糊如果不去严格筛选模型会对夜间真实场景的清晰度估计错误。第三步是统一分辨率。原始图片有横有竖有大有小直接训练会带来很多batch层面的padding问题。我做了等比例缩放加灰色填充统一成1280x720。第四步是标注。标注工具我用的是LabelImg和X-AnyLabeling火焰烟雾这类目标更推荐X-AnyLabeling因为它支持半自动分割辅助标烟雾这类边界模糊目标时效率高不少。标注完导出YOLO格式再转成COCO格式。第五步是数据划分。划分时特别注意一个原则同一个连续视频片段的不同帧一定要全部放进同一个集合里不能一部分在训练集一部分在验证集。不然模型在验证时相当于看到了训练过的同一场景指标虚高一旦换到真实场景能力立刻露馅。4.3 用脚本检查标注质量的三个坑标注完成后再仔细做一轮自动化检查我是用Python脚本实现的发现了好几个容易踩的坑第一个坑是边界框坐标越界。YOLO格式的坐标是归一化到0到1之间的偶尔会有框的中心点或宽高超出范围比如1.02。这种问题如果不检查训练时会直接报错更隐蔽的是有些框架不会报错但会默默截断导致标注框和真实目标对不上。检查代码很简单import os invalid [] for f in os.listdir(labels/yolo/train): if not f.endswith(.txt): continue with open(os.path.join(labels/yolo/train, f)) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: invalid.append((f, invalid line)) continue cls, x, y, w, h parts for v in [x, y, w, h]: if not (0 float(v) 1): invalid.append((f, bbox out of range)) break print(invalid)第二个坑是空标签文件。有些图片里目标太小被标掉了结果留下了label文件但没有任何标注行这类文件在训练时会导致warning但不会报错。问题是如果空标签文件太多模型会倾向于把所有区域都判断为背景直接拉低召回率。我处理的办法是删除没有任何标注行的图片把它们从训练集里清理出去。第三个坑是类别平衡问题。通过统计每个类别出现的次数用脚本输出训练集里fire和smoke的目标数量差异。如果smoke的目标数量远少于fire训练时就要考虑类别权重或增加smoke类别的数据增强倍数。4.4 一个实用的数据集概览统计整理完后可以用脚本生成一份数据集概览方便随时检查总图片数1000张总标注目标数fire 类 713 个smoke 类 689 个正样本图片含至少一个目标812 张负样本图片188 张平均每张正样本图目标数1.7 个目标尺寸分布小目标32x32约18%中目标32x32~96x96约56%大目标96x96约26%有了这份统计数据我在训练后分析模型在哪些目标尺寸上表现不好时能快速定位问题。5. 用这份数据跑通YOLOv8训练实测过程和参数选择5.1 环境准备与数据适配训练我用的是YOLOv8框架Ultralytics官方版本。安装没什么好说的pip install ultralytics 一行搞定。关键是数据配置文件需要写一个yaml指向数据集的路径和类别信息path: /path/to/flame_smoke_dataset train: images/train val: images/val test: images/test names: 0: fire 1: smoke这里有个小陷阱path路径最好写绝对路径相对路径在换机器或换目录结构时特别容易出问题。我一开始用相对路径训练了好几次都没报错但val的指标一直不对后来发现是训练时yaml里的相对路径解析到了错误目录模型在验证时根本没找到对应的labels。5.2 训练参数和训练结果我用YOLOv8s作为基线模型训练时的参数设置如下参数设置值modelyolov8s.ptimgsz640batch16epochs120optimizerSGDlr00.01augmentmosaic 1.0 flipud 0.5 hsv_h 0.015patience20device单卡 RTX 3060 12GB120轮看起来多但因为只有800张训练图实际训练时间大约1小时10分钟。最终在100张val图上的指标mAP500.782mAP50-950.486precision0.81recall0.73fire 类 mAP500.812smoke 类 mAP500.704从指标上看fire类比smoke类高出不少这个差距主要来源就是烟雾目标的边界模糊和半透明特性。如果你也要做火焰烟雾检测对smoke类的预期要比fire类低5-10个点这是比较正常的现象。5.3 训练中出现的意外情况和排查过程这里分享一个我在训练中踩到的坑值得每一个训练YOLO类模型的开发者注意。我用YOLOv8s训练到大概第60轮的时候发现val loss开始出现周期性波动每隔几个epoch就有一个尖峰但train loss平滑下降。一开始以为是学习率策略的问题把SGD换成AdamW之后尖峰依然存在又怀疑是数据加载顺序问题。排查过程比较折腾最后确认是数据增强里的mosaic导致的问题。当mosaic把多张图和它们的label拼在一起时如果某张图的火焰目标正好在拼接边界上YOLO的框坐标归一化计算会变得不稳尤其是烟雾这种边界模糊的目标拼接后边界错位更明显。我把mosaic参数从1.0降到0.5并加了close_mosaic10的设置让最后10轮训练不使用mosaic尖峰就消失了mAP还略微提升了一点。经验是mosaic参数不要一上来就拉满火焰烟雾这类目标边界天然模糊mosaic带来的干扰比普通物体检测更大。5.4 用模型排查数据标注错误的反向检查法训练过程中我发现了一个反向检查标注质量的方法实测很有效。用训练好的模型去跑训练集自身而不是验证集同时记录每张图的confidence和IoU。如果一个训练图片里的目标模型预测的confidence特别低比如低于0.35通常说明这个标注本身有问题要么框得不准要么目标被遮挡太严重要么标注类别搞错了。我用这个办法从800张训练图里找出7张明显标注有问题的图片比如火焰框把旁边的红色灭火器框进去了一半或者烟雾框把薄雾背景当成了目标。修正这些标注重新训练后mAP50提升了2个点。这个方法的本质是让模型充当一个交叉检查员用模型的“偏见”去反推标注的“偏见”效率比纯人工复核高不少。6. 数据增强的度与过拟合的实战心得训练迭代中的几个关键发现6.1 默认增强策略和火焰烟雾任务的冲突YOLOv8默认的数据增强对普通物体检测效果很好但在火焰烟雾任务上不能无脑照搬。最大的问题是颜色增强。火焰的颜色本身就是核心特征如果HSV增强里hue的扰动范围太大火焰可能被增强成绿色或蓝色模型就会学到错误颜色特征。我实测把hsv_h从默认的0.015调大到0.05后模型在夜间火焰上的表现明显下降因为夜里火焰的颜色本来就比较关键颜色一扰动模型就分不清了。我的建议是火焰烟雾数据集的HSV增强范围要比通用检测更保守hsv_h保持在0.01左右hsv_s和hsv_v可以相对大一点因为亮度和饱和度的扰动有助于模型适应不同光线条件但色相的扰动要小心。6.2 过拟合的判断和应对从val loss变化曲线定位问题1000张图的数据集过拟合是训练中一定会遇到的现象。我在训练过程中观察到两个典型信号第一个信号是train loss持续下降但val loss在某个epoch后开始反弹。我在第80轮左右就遇到了这个情况当时val mAP50不再提升但train mAP50还在往上走。这说明模型开始“背题”了把训练集里的背景纹理、色彩分布过度编码进特征导致在没见过的图上泛化失败。第二个信号是对难例的预测开始变得极端自信但错误。比如模型会对某几个固定的背景区域产生高confidence的误报这些背景区域往往在训练集里反复出现。我通过打印误报图片的原始文件名定位到模型把训练数据里一张经常出现的红色砖墙当成了火焰背景因为砖墙的砖红色和火焰外焰颜色确实接近但砖墙在训练集里出现频率太高模型就把这个特定纹理和fire类关联起来了。针对过拟合我用了三个组合拳第一个是早停。patience设置为20val指标连续20轮不提升就停止训练避免后期浪费算力且进一步过拟合。第二个是降低学习率。在最初学习率0.01的基础上把最后的epoch数拉长配合cosine学习率调度让模型在后期用更小的步长逼近最优值实测比固定学习率收敛得更稳。第三个是增加Dropout和权重衰减。YOLOv8里没有直接的Dropout参数但可以通过换用更大模型的预训练权重来获得一个隐含的正则化效果。比如用yolov8m的权重来训练参数量更大但初始化特征更丰富实际过拟合反而比直接从头训练yolov8s更少。6.3 小目标增强切图训练策略值得一试远景小目标占了整个数据集目标的18%如果不做特殊处理模型对小目标的检测能力会明显不足。我试过两种方案一种是把imgsz从640增加到1280通过提升输入分辨率来保留更多小目标细节另一种是切图训练把1280x720的原图切成两块或四块每块作为一个训练样本。实测下来imgsz1280对mAP50的提升非常明显从0.782提升到0.814但训练时间和显存占用也翻了不止一倍。切图训练相对更省资源但需要注意图片切分后边界目标会被截断需要加上overlap策略我试了10%的overlap效果还不错。如果你只是前期验证先用imgsz640跑通流程就可以了如果你要做真实场景部署建议直接上imgsz1280因为火灾检测里小目标漏报的代价是很高的。6.4 负样本过强的副作用和平衡策略之前提过我在数据集里放了不少负样本这是把双刃剑。我做过一个对比实验把负样本比例从0%提高到20%、30%和40%结果很有意思负样本比例mAP50误报率验证视频实测0%0.821较高频繁把红色灯光当火焰20%0.782中等偶发误报30%0.756较低40%0.713低但漏报明显增多负样本比例上去之后误报率确实下来了但代价是漏报上升。因为模型见过太多“看起来像火焰但不是火焰”的图会变得保守真正的小火苗也被过滤掉了。平衡点在我的场景里是20%-25%这个区间再高就牺牲太多召回率。如果你使用这份数据时场景里的误报特别严重可以适当增加自己的负样本但要留意召回率的变化。7. 从这些实验里沉淀下来的几点经验数据量不是目标数据的信息密度才是。1000张图放到火焰烟雾检测里其实不算多但如果每张图都覆盖了不同的光照条件、场景类型、目标形态模型能学到的特征就足够了。我在实验里发现真正提升模型泛化能力的关键因素不是那多出来的几百张图而是负样本设计、标注边界规范和数据增强度的控制。这三件事如果做不好数据集再大模型也会在各种真实场景边缘反复试探。标注不是一次性的工作它需要反复校准。训练过程中用模型反向检查标注质量是我觉得最有效的一步。一套标注规范定下来并不难难的是在训练过程中发现标注和模型预期不一致时有没有耐心回头去修正。我修了那7张图之后模型的表现进步比加训练轮数明显得多。如果你准备把火焰烟雾检测落到具体项目里不要急着堆数据先用这份1000张的数据集把流程跑通把误报率和漏报率的基线测出来。然后再根据你的真实场景补充数据每次补充100到200张验证模型是否改善有节奏地迭代比一次投入大量数据更可控。数据增强要克制尤其是颜色扰动火焰烟雾这类颜色敏感任务增强过头了就是在给模型制造噪音。最后分享一个部署阶段的小技巧训练时把输入分辨率定到和部署设备支持的分辨率一致不要训练用大分辨率、部署用小分辨率那会让模型精度白白损失。我遇到过项目里训练时用1280部署到盒子时被缩到640精度直接掉了8个点后面统一分辨率后就稳定下来了。这个细节踩坑之前不会意识到意识到之后只能说一句——真希望当年第一次训练时就知道。本文还有配套的精品资源点击获取
返回列表