
简介这份俯拍航拍森林火灾检测数据集面向从事目标检测算法研发的科研人员与工程师用于训练和测试火灾与烟雾的智能识别模型可服务于森林火灾早期预警与应急响应等场景。资源包共1个docx文件约5.06MB文档内整理了数据集说明、标注规则、图片预览与标注示例便于快速了解数据构成与使用方式。数据集包含6116张jpg图像同时提供Pascal VOC格式的xml标注与YOLO格式的txt标注标注类别为fire和smoke两类其中火标注框15380个、烟雾标注框12613个总框数达27993均通过labelImg以矩形框方式完成标注。目前已有62人学习关注。读者可据此直接开展模型训练与评估借助预览示例核对标注细节并需注意数据集不对训练所得模型或权重的精度作保证最终性能仍取决于预处理、模型结构与调参等环节。1. 俯拍航拍森林火灾检测数据集6116 张 VOCYOLO 双格式到底能训出什么林火检测这个方向真正卡住大多数人的从来不是模型结构而是数据。你拿 COCO 里那点火焰图去训 YOLOmAP 能看一上真实航拍画面就集体翻车——因为俯拍视角下的火场和地面平视完全是两个分布。这份 6116 张、2 类别的俯拍航拍森林火灾检测数据集价值就在于它把视角、光照、烟雾干扰这些真实变量固定下来了VOC 和 YOLO 双格式并存省掉了你自己写转换脚本的功夫。它适合三类人想快速跑通目标检测全流程的新手、要做林火预警落地的工程团队、以及拿它当遥感目标检测 baseline 的研究者。2 类别通常对应火焰和烟雾或火焰与非火焰干扰具体类别名以你拿到的classes.txt为准别照搬我的假设。下面从数据怎么读、格式怎么转、参数怎么调、坑在哪一路讲透。2. 先搞懂 VOC 与 YOLO 双格式同一批图两套坐标逻辑2.1 VOC 的 XML 结构与你必须核对的四个字段VOC 格式每张图配一个同名.xml核心信息全在object节点里。拿到数据集第一件事不是急着训而是抽 5 到 10 个 XML 打开看确认字段没被上游改坏。一个标准的林火标注长这样annotation folderimages/folder filenamefire_0001.jpg/filename size width1920/width height1080/height depth3/depth /size object namefire/name !-- 类别名必须和 classes.txt 完全一致 -- poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin820/xmin !-- 左上角 x绝对像素 -- ymin410/ymin !-- 左上角 y -- xmax1105/xmax !-- 右下角 x -- ymax690/ymax !-- 右下角 y -- /bndbox /object /annotation四个字段必须核对size里的宽高要和真实图片一致不一致说明图片被缩放但 XML 没同步坐标会整体偏移name要和你的类别表严格对应大小写、空格都算xmin/ymin必须小于xmax/ymax反了就是标注工具导出 bugdifficult为 1 的框在评估时通常要忽略训练时看你的框架怎么处理。俯拍林火里烟雾边界极其模糊标注员很容易把大片稀薄烟雾框得过大这类框会拉低定位精度建议训练前用可视化脚本过一遍。2.2 YOLO 的 txt 格式归一化坐标的五个数字YOLO 格式每张图配一个.txt每行一个目标格式是类别索引 cx cy w h全部归一化到 0 到 1 之间。注意这里的cx cy是框中心点不是左上角这是新手最容易搞混的地方。一行示例0 0.5013 0.5093 0.1484 0.2593含义是类别索引 0中心点横坐标占图宽 50.13%中心点纵坐标占图高 50.93%框宽占图宽 14.84%框高占图高 25.93%。类别索引从 0 开始对应classes.txt里的行号。如果你的数据集里 YOLO 标签的类别索引和 VOC 的name对不上训练出来的模型会把火焰认成烟雾这种错误在 loss 曲线上看不出来只有推理可视化才暴露。2.3 两套格式的换算关系与自检脚本换算公式很直接cx (xmin xmax) / 2 / widthcy (ymin ymax) / 2 / heightw (xmax - xmin) / widthh (ymax - ymin) / height。反过来乘回去就行。但公式对不代表数据对我一般会写个自检脚本把 VOC 转成 YOLO 后再转回来比对坐标误差是否在 1 像素内import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, classes): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in classes: print(f[警告] 未知类别 {name} in {xml_path}) continue cls_id classes.index(name) 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) # 边界裁剪防止标注越界导致归一化后超出 [0,1] xmin, xmax max(0, xmin), min(w, xmax) ymin, ymax max(0, ymin), min(h, ymax) cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) return lines classes [fire, smoke] # 以你的 classes.txt 为准 xml_dir annotations for f in os.listdir(xml_dir): if f.endswith(.xml): res voc_to_yolo(os.path.join(xml_dir, f), classes) print(f, len(res), 个目标)这段脚本的关键在边界裁剪那两行。俯拍数据里经常有目标贴着图像边缘标注员手一抖xmax就超过图宽归一化后cx会大于 1YOLO 训练时这类框会被静默丢弃或产生异常梯度。裁剪后再归一化能救回一批边缘目标。classes列表的顺序决定类别索引务必和数据集自带的classes.txt逐行对齐不要自己重排。3. 用 YOLO 在本地跑通林火检测的最小闭环3.1 目录组织与 data.yaml 的五个必填项YOLO 系列v5/v8/v11 都适用对目录结构有约定最省事的组织方式是这样fire_dataset/ ├── images/ │ ├── train/ # 训练图 │ └── val/ # 验证图 ├── labels/ │ ├── train/ # 对应 txt │ └── val/ └── data.yamldata.yaml是训练入口五个字段一个都不能少path: /home/user/fire_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图目录 val: images/val # 相对 path 的验证图目录 nc: 2 # 类别数必须和 classes 长度一致 names: [fire, smoke] # 类别名顺序即索引nc写错是最隐蔽的坑写成 1 但标签里有索引 1训练直接报 index out of range写成 3 但只有 2 类最后一类永远学不到mAP 里那一行是 0。path用绝对路径相对路径在不同工作目录下启动训练会找不到数据这个坑我踩过不止一次。3.2 划分训练验证集别用随机划分糊弄俯拍数据6116 张如果随机 8:2 划分会出现同一片火场的相邻帧同时进训练集和验证集验证 mAP 虚高上线就露馅。俯拍航拍数据往往来自连续拍摄帧间高度相似正确做法是按场景或按拍摄批次划分。常见做法是先按文件名前缀或采集日期分组再整组划分import os, random, shutil random.seed(42) img_dir all_images groups {} for f in os.listdir(img_dir): # 假设文件名形如 fire_20230512_0001.jpg取日期作为分组键 key _.join(f.split(_)[:2]) groups.setdefault(key, []).append(f) keys list(groups.keys()) random.shuffle(keys) split int(len(keys) * 0.8) train_keys, val_keys keys[:split], keys[split:] for phase, ks in [(train, train_keys), (val, val_keys)]: os.makedirs(fimages/{phase}, exist_okTrue) os.makedirs(flabels/{phase}, exist_okTrue) for k in ks: for f in groups[k]: shutil.copy(os.path.join(img_dir, f), fimages/{phase}/{f}) txt f.rsplit(., 1)[0] .txt shutil.copy(os.path.join(all_labels, txt), flabels/{phase}/{txt})分组键的取法要看你的实际文件名规律核心原则是让同一场景的图只出现在一个集合里。random.seed(42)固定随机种子保证划分可复现团队协作时别人能拿到和你一样的验证集指标才可比。3.3 训练命令与三个必调参数环境装好后一条命令就能起训yolo detect train \ datafire_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/fire \ nameexp1三个参数决定成败。imgsz是输入分辨率俯拍林火里烟雾目标往往占画面比例很小640 可能把远处小火点缩没建议先跑 640 看 mAP不理想就上 960 或 1280代价是显存和速度。batch受显存限制16 是 8G 显存的稳妥值爆显存就降到 8 并配合accumulate补梯度。lr0初始学习率0.01 是默认但小数据集上容易震荡可以降到 0.001 观察 loss 是否更平滑。patience20表示 20 轮没提升就早停防止过拟合林火数据里烟雾标注噪声大早停能省不少时间。3.4 训练过程看什么loss 曲线与 mAP 的读法起训后重点盯三样box_loss、cls_loss和验证集mAP50。box_loss持续下降说明定位在收敛cls_loss不降反升通常是类别不平衡或标注错误2 类别里如果火焰样本远少于烟雾cls_loss 会卡住可以用cls权重或过采样缓解。mAP50是 IoU 阈值 0.5 下的平均精度林火检测里火焰目标清晰mAP50 通常能到 0.8 以上烟雾因为边界模糊能到 0.6 就算不错。如果训练集 mAP 高、验证集低八成是划分泄漏或过拟合回去检查 3.2 的分组。4. 俯拍林火数据的避坑与排查清单4.1 现象训练 loss 正常但推理全是背景原因通常是标签路径没对上。YOLO 找标签的规则是images/train/xxx.jpg对应labels/train/xxx.txt只替换最后一级目录名和扩展名。如果你把图放在images/train而标签放在labels根目录YOLO 找不到标签会把所有图当负样本训loss 照样降但模型学的是「什么都不框」。解决严格按 3.1 的目录结构摆放训练启动时看日志里train: Scanning ... images, ... backgrounds这行backgrounds 数量等于图片总数就是标签全没找到。4.2 现象mAP 高得离谱上线一塌糊涂这是划分泄漏的典型症状。俯拍航拍数据连续帧多随机划分让相似帧跨集验证集等于在考训练集原题。解决按 3.2 的场景分组划分划分后抽几张验证集图确认和训练集没有肉眼可辨的同一场景。另一个隐蔽来源是数据增强如果你的增强里用了 mosaic它会把 4 张图拼一起跨集拼接也会造成泄漏验证阶段记得关掉 mosaic。4.3 现象小目标火焰检测不到俯拍视角下远处火点可能只有十几个像素640 输入下缩到几个像素卷积特征直接消失。解决有三条路提高imgsz到 960 或 1280在数据里对小目标过采样换用带 P2 小目标检测层的模型结构。先试提分辨率成本最低。如果显存不够用imgsz960配batch8速度慢但能救回小目标。4.4 现象烟雾框抖动大同一片烟时有时无烟雾没有硬边界标注一致性差模型学到的框位置方差大。解决训练前用可视化脚本把标注框画到图上人工筛掉明显过大或过小的烟雾框训练时适当降低烟雾类的损失权重或者把烟雾和火焰分开评估别让烟雾拖累火焰指标。推理阶段对烟雾用更低的置信度阈值配合 NMS 的 IoU 阈值调高到 0.6减少同一片烟被重复框。4.5 现象训练到一半显存爆了多半是imgsz或batch设大了也可能是 dataloader 的workers开太多导致内存碎片。解决先把batch减半还爆就降imgszworkers在 Linux 上设 8 够用Windows 上设 0 或 2多了反而卡。另外检查有没有开cacheTrue把整个数据集缓存进内存6116 张 1920 分辨率的图能吃掉几十 G 内存小内存机器别开。5. 把 6116 张用到极致进阶技巧与验证习惯数据量固定时提升空间在增强策略和评估方式上。增强别只开默认的翻转和缩放俯拍林火可以加随机旋转90 度倍数因为俯拍视角旋转后语义不变、HSV 的 V 通道扰动模拟不同时段光照、以及轻度高斯噪声模拟传感器噪声。但别加垂直翻转火焰有明确的重力方向翻转后烟雾朝上飘语义就错了这种增强是负收益。验证阶段我有个固定习惯除了看 mAP一定导出混淆矩阵和 PR 曲线。混淆矩阵能告诉你火焰和烟雾有没有互相误判PR 曲线能看出在哪个置信度阈值下召回和精度平衡最好。林火预警场景宁可误报也别漏报所以我会把置信度阈值压到 0.25 左右牺牲一点精度换召回这个取舍要在部署前和业务方对齐别自己拍脑袋。再进一步是跨数据集验证。拿这份数据训完找另一批不同季节或不同机型的航拍图做测试如果 mAP 掉超过 20 个点说明模型过拟合到本数据集的成像风格了需要加更强的颜色和尺度增强。这个习惯能帮你在真正上线前发现泛化问题比在验证集上刷高分管用得多。最后说个我自己的教训早期做林火检测我图省事直接用随机划分验证 mAP 0.85兴冲冲部署到无人机上实际漏检率超过一半。回头查才发现训练集和验证集里有大量同一火场的连续帧。从那以后任何时序或航拍数据我第一件事就是按场景分组划分宁可训练集小一点也要保证验证集干净。数据这关偷的懒上线都会加倍还回来。希望帮到你。本文还有配套的精品资源点击获取