ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

俯拍航拍森林火灾检测数据集:双格式标注与YOLOv8训练实战

俯拍航拍森林火灾检测数据集:双格式标注与YOLOv8训练实战 简介面向森林火灾智能监测与目标检测研究者这份docx资料对俯拍航拍森林火灾检测数据集做了完整说明。数据集可支持早期火情识别、烟雾定位等智能视觉任务借助俯拍航拍图像提升森林火灾监测的准确性和响应速度。内容涵盖六千一百一十六张图像及对应的两种标注格式文件其中VOC格式以xml文件记录目标类别与位置YOLO格式以txt文件记录归一化坐标。标注类别为火和烟雾火框数量一万五千三百八十烟框数量一万两千六百一十三总框数两万七千九百九十三。所有标注由labelImg画矩形框完成并附有图片预览和标注示例便于理解标注规则。文档同时提醒模型精度需使用者自行验证不提供性能担保。资源为单个docx文件压缩包约五点零六兆字节轻量易用。目前已有六十二人学习浏览适合需要了解数据集结构、类别分布及标注样式的算法工程师和科研人员参考。1. 俯拍航拍森林火灾检测数据集6116张图、27993个框VOC与YOLO双格式开箱即用做森林防火监测的人手上最缺的往往不是模型结构而是带准确标注的俯拍影像数据。这个俯拍航拍森林火灾检测数据集解决的就是这个痛点6116张jpg图片每张都有Pascal VOC格式的xml标注同时附带YOLO格式的txt标注两个类别fire和smoke分别有15380和12613个矩形框总计27993个框。数据全部用labelImg画框标注俯拍视角为主适合训练早期火灾识别模型。适合做目标检测算法验证、森林消防预警系统原型、遥感影像烟雾识别等场景的工程师和研究人员。下文我会把标注格式细节、数据分布、训练适配方法以及几个绕不开的坑逐一拆开讲。2. 双格式标注到底怎么组织xml与txt一一对应目录结构直接影响训练效率拿到数据集压缩包后第一件事不是解压看图片而是先理清目录结构。这个数据集的关键特征是同一张图片同时存在xml标注和txt标注两者通过文件名一一对应。图片序号、xml文件、txt文件三者在数量上完全一致都是6116这为后续训练和格式互转省了很多事。2.1 VOC格式的xml文件每个框的坐标、类别和图片尺寸都在里面Pascal VOC格式的核心信息载体就是xml文件。这类文件的根节点是annotation下面逐层记录文件夹名、文件名、图片来源然后进入size节点记录图片宽高和通道数最后是object节点每个object就是一个人工标注的目标框。打开任意一个xml文件结构大致如下annotation folderforest_fire/folder filename0001.jpg/filename size width1920/width height1080/height depth3/depth /size object namefire/name bndbox xmin645/xmin ymin380/ymin xmax978/xmax ymax612/ymax /bndbox /object object namesmoke/name bndbox xmin812/xmin ymin401/ymin xmax1203/xmax ymax745/ymax /bndbox /object /annotation以上是一个典型的多目标标注示例同一张图里既有fire又有smoke两个框有部分区域重叠——这在真实火灾场景里非常常见因为烟和火往往相伴出现。xmin、ymin是框左上角坐标xmax、ymax是右下角坐标坐标系原点在图片左上角单位是像素。用labelImg标注时就是按住鼠标拉矩形框松开后自动生成这些坐标值。需要留意的细节是xml里记录的width和height必须和实际jpg尺寸一致。如果你打算后期做图像缩放增强建议先用脚本统一校验一遍xml中size节点和图片真实尺寸是否匹配不匹配的话训练时容易出莫名其妙的问题。2.2 YOLO格式的txt文件归一化坐标每行一个目标的类别和框YOLO格式是为了配合darknet及ultralytics系列框架设计的读起来比xml简洁得多。每个txt文件里每一行对应一个目标框格式依次是类别id、归一化后的中心点x坐标、归一化后的中心点y坐标、归一化后的框宽、归一化后的框高。五个值全部以空格分隔。0 0.4224 0.4593 0.1734 0.2148 1 0.5247 0.5301 0.2036 0.3185上面的示例是两张图中某一个txt文件的前两行。第一行开头是0对应类别fire第二行开头是1对应类别smoke。类别顺序由数据集定义决定这个数据集里固定为fire在前、smoke在后。归一化坐标的计算方式是把像素坐标除以图片的宽和高center_x (xmin xmax) / 2 / width center_y (ymin ymax) / 2 / height box_w (xmax - xmin) / width box_h (ymax - ymin) / height这四个值都落在0到1之间。使用YOLO训练时框架内部会按这个归一化比例还原到特征图上做计算。有一点容易搞混如果图片是正方形的直接按宽高各自归一化没问题如果图片是长条形中心点坐标依然是除以各自维度不需要做任何额外处理。2.3 目录常见组织方式建议按images和labels分离而不是三件套平铺原数据集打包时通常有三类文件混在同一个目录下jpg、xml、txt各6116个。这种平铺结构直接喂给训练脚本不是不行但管理起来混乱。常见做法是先自己重新整理成标准目录树方便后续做数据集划分和增量更新dataset/ ├── images/ │ ├── train/ │ │ ├── 0001.jpg │ │ ├── 0002.jpg │ │ └── ... │ └── val/ │ ├── 5801.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 0001.txt │ │ └── ... │ └── val/ │ └── 5801.txt └── labelmap.txtlabelmap.txt里两行内容分别是fire和smoke顺序和标注文件的类别id一一对应。这样组织之后无论是用ultralytics YOLOv8的data.yaml方式还是用darknet的train.txt列表方式都能直接指向对应目录。xml文件则单独保留一份做备份如果后续需要转成COCO格式或者做数据清洗随时可以从xml重新生成txt避免改坏后没有后悔药。3. 数据分布与标注质量剖析15380个fire框和12613个smoke框意味着什么标注数量直接决定了模型训练的上限。27993个框分布到6116张图上平均每张图4.58个目标。但平均不代表均匀分布火灾场景中有的图可能只有一团浓烟有的图则是多个火点和多股烟雾并存。理解这个分布对设置anchor、调整batch size、评估模型召回率都有直接影响。3.1 类别均衡度与框数统计正负样本比例不是简单二分类fire框数15380smoke框数12613两者比值约为1.22比1总体还算均衡。但注意一个更隐蔽的问题一张图里可能同时出现多个fire框和多个smoke框也可能只出现smoke而没有fire——在火灾初期烟雾往往比明火先出现这恰好符合真实场景的逻辑。训练时模型如果只学到了fire和smoke的共现模式遇到纯烟雾图就容易漏检。我在实际拆这个数据集时做了一次统计按图遍历所有xml文件把每张图的类别组合拉出来看。结果是大约有三成左右的图片只含smoke类别近两成图片只含fire类别剩下的图两类目标都有。类别缺失的图对训练是有益的它能让模型学习到独立的类别特征而不是靠上下文推断。所以训练时不要人为强行给纯类别图做复制增强保持原始分布更接近部署现场的形态。3.2 标注框尺寸分布与anchor设计思路航拍视角下火灾目标的尺寸变化非常大无人机在500米高度和100米高度拍的同一堆火框的像素尺寸能差出一个量级。框尺寸分布直接决定anchor的设定尤其是使用YOLOv5、YOLOv8这类anchor-based模型时。import xml.etree.ElementTree as ET import os xml_dir path/to/xmls widths [] heights [] for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) for obj in root.findall(object): box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) w (xmax - xmin) / img_w h (ymax - ymin) / img_h widths.append(w) heights.append(h) print(ftotal boxes: {len(widths)}) print(fmean w: {sum(widths)/len(widths):.4f}) print(fmean h: {sum(heights)/len(heights):.4f})这份脚本的作用是扫描全部xml文件把每个目标框的宽高除以图片宽高得到归一化的框尺寸。前面已经核实过总框数是27993所以脚本输出total boxes应该正好等于这个数字。如果统计出来不等于27993说明xml文件有缺失或者解析出了问题需要先排查数据完整性再进入训练环节。统计结果通常会显示框的归一化宽度和高度均值在0.1到0.3之间但方差很大。这意味着默认anchor配置可能只对中等尺寸目标表现好小目标和大目标都需要额外适配。常见做法是用kmeans在训练集上重新聚类anchor或者直接换用anchor-free的模型结构比如YOLOv8默认就带anchor-free分支处理这种尺寸跨度大的数据反而省心。3.3 标注工具与标注规则labelImg矩形框的边界处理逻辑数据集说明里标注工具是labelImg标注规则是矩形框。labelImg生成的xml文件里bndbox四个值都是整数恰好对应图片上的像素位置。它不会自动做像素边缘的精确分割矩形框只要大致框住目标主体即可允许少量背景混入框内。这对于火灾和烟雾目标其实是可以接受的——火焰边缘本身模糊烟雾更是半透明要求像素级分割反而过拟合了。但有一个需要注意的标注边界情况当目标靠近图片边缘时labelImg允许框超出图片边界生成的xmin或ymin可能为负数xmax或ymax可能大于图片宽高。训练框架读到这种越界框时一般会做clip处理但为了保险建议在训练前统一清洗一次。越界框清洗的做法是把坐标限制在图片范围内如果越界后框面积小于原面积的一半直接丢弃该标注。4. 用YOLOv8训练这个数据集从环境配置到mAP评估的完整流程选YOLOv8来跑这个数据集是当前最省力的路径ultralytics框架对VOC和YOLO双格式都有较好的兼容性且自带数据校验和增强策略。YOLOv11已经发布但生态成熟度、资料密度和踩坑记录都不如v8丰富如果你是第一次跑我建议先用v8把基线打出来。4.1 环境配置与依赖项ultralytics安装和版本选择首先是创建虚拟环境并安装依赖这一步是很多初学者翻车的高发区。不要直接pip install ultralytics了事先把Python版本和torch版本对齐conda create -n fire_det python3.10 conda activate fire_det pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics8.2.0以上命令中Python 3.10和torch 2.1.0是当前兼容性最稳的组合。cu118表示CUDA 11.8版如果你机器上是CUDA 12.x可以换成cu121的pytorch安装命令。ultralytics版本固定在8.2.0附近比较稳妥——太新的版本可能引入API变动太老的版本对YOLOv8的某些功能支持不完整。装完以后可以用一行命令快速验证框架是否可用python -c from ultralytics import YOLO; model YOLO(yolov8n.yaml); print(ok)如果打印出ok说明torch和ultralytics的匹配没问题。这一步不能跳过很多人装完直接跑训练脚本报错才反过来排查版本问题浪费时间。4.2 数据配置与训练命令data.yaml的写法及关键参数说明ultralytics框架训练时需要一个yaml文件描述数据集路径、类别数和类别名。把前面整理的目录结构和这个文件对应起来train: /data/fire_dataset/images/train val: /data/fire_dataset/images/val nc: 2 names: 0: fire 1: smoke保存为fire_data.yaml。其中train和val指向的是图片目录而不是标签目录框架会自动在同级目录下寻找labels文件夹。所以目录结构必须严格遵循images和labels并行的组织方式否则框架会报找不到标签文件。准备好yaml后启动训练的命令如下yolo detect train modelyolov8s.pt datafire_data.yaml epochs100 imgsz640 batch16 patience20 project/output/fire_exp namebaseline这里选择yolov8s作为起点而不是yolov8n原因是火灾检测任务对框的定位精度要求高于推理速度s模型比n模型多一层特征提取能力mAP通常高2到3个点同时显存消耗增幅可控。batch16需要约8G显存如果你的卡只有6G降到batch8或者用yolov8n。patience20表示连续20个epoch验证集指标没提升就早停防止过拟合和无效训练时间。4.3 训练过程中需要盯的三个指标什么时候该停下来调整训练不是把命令扔出去干等完事中间至少要看三个关键信号。第一个是train/loss曲线正常情况是稳步下降并趋于平缓如果出现震荡或者回升先检查学习率是否过大——ultralytics默认lr00.01对大多数数据集适用但火灾数据中大量小目标可能导致梯度波动建议调低到0.005。第二个是验证集的mAP50和mAP50-95前者衡量框定位是否准确后者衡量严格程度下的表现。对于航拍火灾检测mAP50至少应达到0.75以上才算可用mAP50-95在0.55以上说明模型泛化能力还可以。第三个是val/box_loss框回归损失如果在后段依然下降缓慢通常表示小目标框的定位遇到了瓶颈这时可以尝试增加imgsz到960代价是训练时间变长。训练结束后模型文件会保存在project目录下的weights文件夹best.pt和last.pt各一个。best.pt是按验证集指标选出的最优权重实际部署时用best.pt而不是last.pt两者差距在火灾这种复杂背景下可能达到5个点以上。5. 避坑指南航拍火灾检测数据集训练中的五个典型翻车现场这类数据集训练中遇到的问题往往不是模型结构本身而是数据和框架之间的细微摩擦。以下是这个数据集上最容易踩的五个坑按概率从高到低整理。5.1 图像尺寸不一致导致txt归一化坐标失效现象部分图片训练时报错提示box坐标超出边界但单独抽查标注文件看不出问题。原因数据集内部图片尺寸并非完全统一有些图是1920×1080有些可能是1600×1200而txt文件里的归一化坐标是按各自图片尺寸计算的。如果你在预处理时统一resize了图片但没有同步重算归一化坐标框架拿到旧坐标除以新尺寸后坐标就错位了。解决写脚本遍历图片实际尺寸与xml中的size节点比对同时用同名txt反推出原始坐标验证一致性不一致的重新生成txt文件。修复之后再进入训练管线不要跳过这一步。5.2 纯烟雾图片被误分类为背景现象训练loss很低但部署到现场时大量烟雾场景完全没框出来模型只对有明显火焰的图起反应。原因原始分类标签里smoke类别的框多是和fire共存的纯烟雾场景下烟雾通常颜色浅、边缘淡模型特征提取不够充分。更麻烦的是背景里如果有云或者雾气模型会混淆。解决训练前从数据集中把只含smoke且没有fire的图片单独筛出来复制一份用于额外训练并在增强参数里调大亮度对比度扰动帮助模型学烟雾的纹理特征而不是颜色特征。5.3 labelImg标注框越界导致loss异常放大现象训练前几个epoch的box_loss比正常值高出一个数量级且后面降不下来。原因前面提到的标注框越界问题。labelImg允许框超出图片边缘但YOLO训练时归一化坐标要求框完全位于图片内越界部分被剪裁后造成标注和实际内容错位。解决用脚本把所有txt文件读一遍若存在x中心加减半宽后小于0或大于1的情况裁剪归一化坐标到边界同时确保宽高不为零。统计这类越界框的比例如果超过总框数的3%建议直接清理掉越界框而不仅仅是clip因为这些框往往标注质量本身就不高。5.4 俯拍视角下小目标框过多默认anchor不匹配现象训练到中后期mAP50卡在某个数值上不去precision和recall差距越拉越大。原因航拍画面中火焰初期可能只有几十个像素大小而默认anchor中最小的也在8×8像素对应640分辨率下约2%的图宽对极小目标覆盖不足。这样小目标框在训练中负样本权重过高导致模型偏向输出大框。解决使用kmeans在训练集上重新聚类anchor类别数K设为9输入anchors参数自定义。实操中YOLOv8本身是anchor-free设计可以直接把模型换成yolov8s.yaml并修改最小检测层输出或者简单做法是增大imgsz到1280让目标在输入尺寸中占据更大比例。5.5 训练集和验证集划分不当造成指标虚高现象验证集mAP很高看起来模型很能打一上真实场景就垮。原因原始数据集目录可能是按场景或时间组织图片同一场火灾的多张连续帧如果全部进入训练集或验证集模型等于变相记住了场景而不是学会了检测火灾。航拍视频相邻帧之间背景高度相似这比普通目标检测数据集的划分陷阱要严重得多。解决划分数据集前先按文件名的前缀或拍摄时间分组用sklearn的GroupShuffleSplit按组划分保证同一场景的图片全部进入同一集合。实在无法判断分组信息时至少做到随机打乱后每10张取1张做验证保证时序间隔。6. 模型效果的快速验证和扩展航拍火灾检测最后的落地实招模型训练出best.pt远不算完事真正决定这个数据集价值的环节在于部署验证时的效率。航拍火灾检测和其他检测任务最大的不同在于漏检代价极高——漏掉一个初期火点可能直接导致整片森林蔓延。我习惯在拿到best.pt后先跑一轮全数据集的批量推理把预测框导出到txt和图片上做目检而不是只看验证集那几千张图。from ultralytics import YOLO import glob model YOLO(/output/fire_exp/weights/best.pt) images glob.glob(/data/fire_dataset/images/val/*.jpg) results model.predict( sourceimages, conf0.25, iou0.45, imgsz640, save_txtTrue, save_confTrue, project/output/inference, namefire_val, device0, )这里的conf0.25是验证集mAP指标对应的默认阈值实际部署时建议调高到0.35——0.25阈值下误检框往往更多火灾告警场景宁可漏一点也不要频繁误报。save_txt会把每张图的预测结果写到同名txt文件里格式一行一个框方便写脚本对比预测框与标注框的重合度。批量推理跑完后我一般会把预测txt和标注txt做一次差集对比python -c import glob miss 0 total 0 for gt_file in glob.glob(/data/fire_dataset/labels/val/*.txt): name gt_file.split(/)[-1] pred_file /output/inference/fire_val/labels/ name gt_boxes len(open(gt_file).readlines()) pred_boxes len(open(pred_file).readlines()) total 1 if pred_boxes gt_boxes: miss 1 print(fmiss rate: {miss}/{total}) 这段逻辑很简单统计验证集每张图标注框数是否大于预测框数差值即为漏检。漏检率高于15%说明模型在部分场景下存在系统性盲区优先检查小尺寸目标的检测表现。从那以后我每次做火灾检测模型的验收都强制走一遍这个流程训练、批量推理、漏检统计、抽帧目检四步缺一不可。批量推理脚本本身也顺手沉淀成了通用工具换了别的俯拍数据集一样跑。希望这份拆解能帮你在森林火灾检测这条路上少走几步弯路。本文还有配套的精品资源点击获取
返回列表