
从去年开始我就在陆续整理目标检测相关的数据集森林火灾这块算是我踩坑最多的一个方向。先说结论火灾检测和普通的目标检测完全不是一个难度等级火焰边缘模糊、烟雾半透明、目标尺度变化大这三座大山摆在面前任何一个都足以让模型崩溃。第5期这个森林火灾目标检测数据集是我在之前几版基础上重构而成的重点解决了小目标漏检和烟雾误检两个老大难问题。这篇文章把整个数据集的构建思路、标注规范、训练复盘和部署经验一次性说清楚希望对正在做类似项目的朋友有点帮助。1. 项目背景与设计思路1.1 为什么单独做森林火灾检测数据集市面上公开的火灾数据集其实不少比如常见的火灾图片分类数据集、室内火焰检测数据集但直接拿来做森林火灾检测效果往往一言难尽。原因很简单森林场景太复杂了。室内火灾背景干净火焰区域大而集中森林火灾恰恰相反火焰可能被树干遮挡、烟雾弥漫导致可见度骤降、远距离的火点只有几十个像素。这些差异意味着模型的训练分布和推理分布严重不匹配。所以我做这个数据集的出发点很明确不追求图像数量有多惊人而是追求场景覆盖的广度和标注的精细度。第5期是系列迭代的结果前几期要么小目标标注不完整要么烟雾类目噪声太大这次干脆推倒重来按工业级标准重新清洗了一遍。数据集定位是面向森林防火监控场景的专用检测数据集服务的目标是林区视频监控、无人机巡检和卫星遥感初判。1.2 森林火灾检测的三大技术难点搞明白难点才能明白数据集为什么要这么设计。第一是火焰形态的不规则性。火焰没有固定形状颜色从橙红到亮黄渐变边缘与背景融合度高这导致传统的矩形框标注本身就存在很大歧义。标注员面对一张火焰图框大一点把烟雾带进去了框小一点漏掉了外焰标注一致性极难保证。第二是烟雾的物理特性。烟雾是半透明的能看到背后的树木轮廓这意味着一部分目标边界不是靠像素差异来界定的而是靠亮度衰减趋势。深度学习模型对这类弱边界目标极其敏感训练数据不足的情况下模型很容易把灰白色的树干、云层、雾气误判为烟雾。第三是尺度极端不均衡。森林火灾监控的视场范围广一个1080P的帧里近处的火焰可能占几百乘几百像素远处的火点只有8-12像素。目标检测模型对中等尺度目标最友好小目标天然存在特征不足的问题。如果数据集里小目标占比不高训练出来的模型在实际部署时基本等于半残。1.3 数据集版本更新逻辑第5期主要做了三个方向的更新。一是扩充了远距离火点样本加入大量无人机高空视角和监控塔远视角图像二是重新标注了烟雾类别去掉了大量因雾气、逆光产生的干扰样本三是统一了标注规范所有火焰框必须紧贴可见焰体不允许把热辐射区框进去。整个数据集的核心指标如下总计4052张标注图像火焰实例数超过8600个烟雾实例约3400个平均每张图像包含2.1个目标实例。训练集、验证集、测试集按8:1:1划分。图像分辨率全部统一到1920x1080或等效比例不同来源的数据做了色调统一预处理。2. 数据集的构成与标注规范2.1 数据来源与场景分层数据来源主要分为三块公开视频监控截图、无人机航拍素材、模拟仿真环境渲染图。这三类来源各有优劣组合使用才能覆盖实际部署中的大部分场景。监控截图是最接近真实部署场景的数据视角固定、背景复杂、火焰可能被遮挡但缺点是分辨率参差不齐老旧监控设备拍摄的画面噪声大。无人机航拍素材提供的是高空视角火焰和烟雾在画面里占比小是训练小目标检测的关键数据。仿真环境渲染图解决了极端场景样本不足的问题比如夜间火灾、暴雨后火灾等渲染图可以在光照条件、烟雾浓度上做精细控制但需要做域适应处理避免模型学到过多的渲染痕迹。场景分层上我按天气、光照、植被类型、地形四个维度做了标签管理。晴天、阴天、雾天、夜间四类光照条件各占约25%植被类型覆盖针叶林、阔叶林、混交林和灌木丛四种地形包含平地、坡地、山谷三类。这么做的好处是训练时可以针对性做采样均衡避免模型在某一类场景上过拟合。2.2 目标类别设计与标注规则类别只设置了两类fire和smoke。有人会问为什么不加burned_area过火区域或person人员原因很简单类别越多标注一致性越差。过火区域通常是大片不规则连通区域强行用矩形框标注价值不大人员检测在森林火灾场景下多用于逃生识别属于另一个任务方向混在一起反而干扰主检测目标。第5期只保留fire和smoke做细做精。标注规则的细节值得多说几句火焰框必须紧贴可见焰体的外缘包含从焰心到外焰的完整区域。如果火焰被树干遮挡成多个可见块分别标注不强行合并成一个框。烟雾框只标注浓度足够形成明显视觉遮挡的区域。淡淡的、仅对背景产生轻微颜色影响的薄雾不算目标这一条是清洗阶段砍掉最多数据的地方。小目标标准小于32x32像素的目标一律标注。很多数据集为了省事直接忽略小目标这恰恰是森林火灾检测最致命的伤。遮挡处理目标遮挡超过80%的不标注但在图片级标签里记录“含遮挡目标”标记供训练时做cutout数据增强的参考。标注工具用的是CVAT团队多人并行标注时CVAT的任务分配和标签审查流程最成熟。如果个人使用LabelImg也够用但LabelImg对多边形标注支持太弱火焰这种不规则目标建议至少用矩形框精修模式。2.3 标注格式转换与数据清洗原始标注从CVAT导出是VOC格式XML但训练YOLO系列模型需要YOLO格式的txt文件。转换脚本实现起来不复杂VOC的bbox是左上角坐标加宽高YOLO需要归一化到[0,1]区间的cx,cy,w,h转换时重点注意坐标系和归一化的坑。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_path, class_dict): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size).find(width).text) img_h int(root.find(size).find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_dict: continue 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) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{class_dict[cls_name]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))转换脚本写好后我额外做了一轮自动化清洗删除标注框超出图像边界的样本、删除面积小于15像素的疑似误标样本这类样本即使真目标对训练贡献也极小且容易变成噪声、用脚本检查同类目标的框之间是否出现大面积重叠排除重复标注。清洗完还保留了约400幅标注边界存在争议的图像放到独立的“待人工复核”目录这一步很笨但确实有效。3. 模型训练与调优实践3.1 基线与数据划分为了验证数据集质量我先后跑了YOLOv8和YOLO11作为基线对比。之所以选YOLO系列一是森林防火边缘设备比如Jetson系列盒子资源有限YOLO系列轻量且推理性能好二是Ultralytics生态配套完善从训练到导出再到TensoRT部署是一条龙对工程落地来说效率最高。数据划分我特意做了场景层面的人工控制。纯随机划分会造成同一视频连续帧的相似图像同时出现在训练集和验证集评估结果虚高。划分逻辑是按“场景会话”划分即同一个视频来源的连续帧必须分配在同一集合这样验证集的泛化表现更接近真实部署。path: ./forest_fire_dataset train: ./images/train val: ./images/val test: ./images/test names: 0: fire 1: smoke3.2 训练参数与增强配置这里给出我最终使用的训练配置按这个参数训练了200轮效果比较稳定。模型选择YOLO11m输入分辨率640x640batch size 16优化器SGD初始学习率0.01warmup 3轮最终余弦学习率衰减到0.0001。比较关键的几个增强项mosaic增强在火灾场景下其实很容易产生假目标因为拼接图像时火焰区域可能被硬生生切到图像边缘形成半截目标。我用mosaic 0.8的概率在最后50轮关闭mosaic让模型在真实分布上精调。copy_paste增强对火灾检测非常有用可以把小目标的火焰区块粘贴到无火图像上扩展小目标样本数量。实测下来copy_paste对小目标AP的提升达到4到6个百分点效果显著。mixup增强也开着但强度控制在0.3火焰目标在mixup下变成半透明叠加模型学习的其实是模糊特征过头了反而会对烟雾这类本来就低对比度的目标造成混淆。自动化增强策略AutoAugment我没有用原因在于火灾目标本身存在高亮和暗光两种极端分布自动策略很容易把暗光下的火焰增强到几乎不可见造成标注与内容脱节。3.3 训练过程复盘与关键评估训练过程要盯两个指标验证集mAP50和mAP50-95。前者只看框的定位和类别对了多少后者对框的精确度更敏感。森林火灾检测的实际部署对误报率极其敏感所以我更关注mAP50-95的变化曲线。迭代到第60轮左右mAP50-95的增长开始变缓火焰类目的AP在0.78附近徘徊。我排查后发现大部分漏检发生在远距离火点也就是小目标上。于是针对性做了三件事第一把输入分辨率从640x640提到800x800。小目标在原图里可能只有10像素放大后特征区域扩大检测器能提取到更丰富的纹理信息。代价是训练速度下降约30%但效果值得小目标AP提高了6个百分点。第二增加小目标过采样。训练时按目标面积对图像分组当一幅图的小目标数量超过3个时采样权重翻倍。这一点在Ultralytics里需要自定义dataset类才能实现代码不复杂但比较繁琐具体做的时候可以参考官方文档中关于自定义数据集加载器的方法。第三关闭了分类损失中的大量背景样本挖掘。默认配置下训练前期大量容易区分的纯背景块会主导损失函数模型还没学到火焰特征就先学会了“什么都别检测”。把负样本比例调低后模型学习火焰特征的注意力明显增强。训练结束后最优权重在测试集上的成绩为火焰AP50达到0.921烟雾AP50达到0.833混合mAP50为0.887小目标面积小于32x32单独评估AP50为0.764。相比上一版数据集训练出的模型小目标AP提升了9.7个百分点烟雾误检率下降了接近40%。这个结果说明数据集重构的方向是有效的。4. 部署落地与工程化经验4.1 模型压缩与推理加速模型训练完只是第一步真正部署到边缘设备才是考验。森林防火监控塔和无人机搭载的算力平台通常有限像Jetson Orin Nano这类设备理论算力有20到40TOPS但实际跑浮点模型帧率往往只有10到15FPS无法满足多路视频流实时分析的需求。我的处理流程是先做通道剪枝再用INT8量化。通道剪枝可以直接在训练时通过稀疏训练实现在loss中加入BN层缩放因子的L1正则让一部分通道的缩放系数趋近于0然后剪掉这些低贡献通道。稀疏训练权重设0.0001从第80轮开始直到训练结束剪枝后模型参数量从YOLO11m的约2000万降到约1300万mAP50-95只掉了0.9个百分点可以接受。量化用的是TensorRT的INT8量化校准数据集从训练集里挑选400幅覆盖不同光照条件的图像。注意校准集一定不能只用简单场景否则量化后模型对复杂场景的适应力会断崖式下跌。INT8量化后推理速度从18FPS提升到42FPS实测单路1080P视频流完全够用。4.2 视频流的滑窗推理策略森林防火监控有一个特殊性视野范围固定场景变化缓慢但火灾一旦出现就要求极低的响应延迟。直接用逐帧检测会有两个问题算力浪费和短期抖动。我采用的是一个双阶段策略抽帧检测 变化触发。平时每5秒抽一帧做检测一旦某帧出现fire或smoke目标且置信度超过阈值立刻切换为连续帧检测模式直到连续30帧无目标才恢复抽帧模式。这个策略在部署现场实测里表现很稳定既能保证正常监控的算力占用又能在火情发生时快速响应。辅助后处理方面我做了一个NDT邻近帧跟踪模块用简单的IoU匹配做短时目标关联。同一目标连续3帧稳定存在的才上报单帧偶发的高分目标直接丢弃。这个模块大幅压低了误报率林区监控里的飞鸟、飘动树叶、光影变化造成的闪烁误检基本都被过滤掉了。4.3 误报抑制与置信度动态调节实际部署中误报比漏报更难缠。漏报可以靠多角度监控弥补误报过多则会让人工值守的巡检员产生“狼来了”效应最终不再关注系统告警。所以我花了不少时间做误报抑制。比较有效的三条经验一是对fire和smoke分别设置独立置信度阈值火焰阈值可以低到0.35因为火焰特征强、误检概率低烟雾阈值至少0.5起步烟雾和云、雾气、逆光区域的混淆太严重阈值定得太低告警会爆炸。二是利用场景语义做约束。部署的每个监控点位会有自己的地理语义比如朝东的监控塔下午逆光严重东侧山谷区域烟雾误检率高这时候可以根据监控点位的方向配置光学特异性阈值。这一层规则逻辑在上层业务系统中实现不写在模型推理代码里便于灵活调整。三是加入“目标最小持续时间”过滤。上报逻辑里要求目标至少持续出现2秒以上才推送告警配合滑窗策略里的连续检测模式误报率能再降低一半。5. 常见问题与排查技巧实录5.1 标注质量相关的坑Q1火焰框紧贴焰体后训练时发现模型预测框偏小几乎只框住焰心。原因是对火焰这类边界模糊目标标注框“内缩”一个像素还是“外扩”一个像素对IoU的影响远大于一般物体。模型通常会学一个折中归一化策略如果训练集里存在系统性的内缩偏差预测框就会偏小。处理办法是统一标注规则宁可外扩2像素不要内缩1像素。Q2烟雾标注的不一致性比火焰更严重。同一幅图像两个标注员可能一个框整团烟雾一个只框浓烟核心区域。我的经验是做两轮标注加一轮专家复核第一轮粗标第二轮对照参考图精修专家只处理边界争议框。虽然人力成本增加但数据集可用性提升明显。5.2 训练效果相关的坑Q3训练初期火焰和烟雾的loss都降得不错到后期烟雾AP突然暴跌。这通常是验证集里混入了一些高难度烟雾样本模型过拟合训练集中特定烟雾形态后对这些样本表现骤降。缓解办法是加强训练集的烟雾形态多样性这个多样性不是指数量而是指透明度梯度、背景遮蔽率、光照条件三个维度的分布。我补充了一批背景明亮的薄雾样本后这个现象基本消失。Q4小目标AP始终上不去。除了前面提到的分辨率提升和过采样还要检查NMS策略。小目标密集环境下默认的NMS IoU阈值0.5会抑制掉大量相邻的火焰框。森林火灾中近距离的火焰常常被树干分裂成多个相邻块这些块的真实语义可能是同一个火焰区域也可能不是。我实测的折中方案是把NMS阈值调到0.45同时开启class-agnostic NMS效果比默认配置好一些。5.3 部署部署相关的坑Q5TensorRT量化后模型在夜间场景的检测能力大幅下降。原因是夜间图像的动态范围极大火焰高亮区和背景暗部同时存在INT8量化在校准时容易把暗部的量化步长压得太粗。解决方案是在校准集里强制加入30%的夜间图像并且对夜间图像做直方图均衡化后再参与校准。Q6边缘设备掉电后模型推理结果不稳定。排查后发现问题出在CUDA的随机数生成器状态没有固定导致部分操作如NMS的随机排序在不同运行时产生不同结果。解决办法是在推理前固定随机种子并在导出引擎时锁定运算顺序。6. 数据集使用建议与后续规划做了几期数据集之后我的一个核心体会是数据集的价值不在于绝对数量而在于它能在多大程度上逼近目标部署场景的分布。如果你的模型训练基于通用数据集但部署环境是林区监控效果不好是必然的。第5期这个数据集的价值恰恰在于围绕森林火灾场景做了精细的分布控制把小目标、烟雾形态、光照变化这些真正影响部署效果的维度做到了可量化、可复现。对想直接使用这份数据集的开发者几个小建议供参考训练前先按场景分层做一次可视化检查确认自己的部署场景和数据集的场景分布在哪些维度上有差异差异大的话优先做域适应增强。不要照搬我的训练参数输入分辨率和增强策略要跟你的算力平台匹配。算力不够的时候宁可用更小的模型配更高的分辨率也别用大模型配低分辨率。数据集的验证集划分是按场景会话隔离的评估结果比随机划分更保守如果你发现模型在验证集上AP偏低不一定是数据或代码有问题很可能是评测基准变严格了。后续我计划在这个数据集上做两个方向的延伸一是加入时序模块利用连续帧间的光流信息来辅助烟雾检测烟雾在静态单帧里是弱特征但在时间维度上有明显的扩散趋势这个时序信号值得挖二是做多光谱融合结合红外热成像数据训练多模态检测模型红外通道对火焰的响应远优于可见光尤其适合夜间场景。做数据集是个持续投入的活每一次迭代都是在跟模型短板较劲。第5期解决的是小目标和烟雾误检下一期要解决的是复杂地形下的目标连续跟踪和遮挡鲁棒性。路还长但方向是清楚的。希望这篇内容能给正在做火灾检测、目标检测数据集或者林区监控系统的朋友一些参考。