无人机航拍烟雾识别与森林防火:数据集构建到YOLO部署实战

发布时间:2026/10/16 2:35:48
无人机航拍烟雾识别与森林防火:数据集构建到YOLO部署实战
写这个项目是因为在实际林业巡检和乡村安防场景里大家已经默认了一件事火情发现越早损失越小。而“早”靠人盯着监控墙是不够的靠卫星遥感也不够及时真正能快速响应的是贴近现场的无人机航拍巡检以及部署在关键点位的安防摄像头。但图像数据一多算法就得跟上。这个项目的核心就是围绕无人机航拍和监控图像构建一套能识别森林火灾烟雾、农田及农村区域烟雾的数据集并用它训练出能用于预警系统的模型。这篇文章会完整拆解数据集从采集、标注到训练、部署的整个链路把我在实操中踩过、填平过的坑都写出来适合正在做森林防火、秸秆焚烧监控、智慧安防这类项目的工程师参考。1. 项目概述与核心需求拆解1.1 这不是一个简单的目标检测项目很多第一次接触这个需求的朋友会觉得烟雾识别不就是找个目标框出来吗实际完全不是。烟雾和普通物体最大的区别在于它的形态是半透明、非刚性、边界模糊的而且颜色会随光照、背景、燃烧物变化。我在做无人机航拍巡检图像数据集时特意把烟雾、火焰、干扰物三类样本做了独立建库就是为了强迫模型去学“烟雾到底是什么”而不是仅仅去学“烟雾大概长什么样”。这个项目的全称我写在标签里无人机航拍巡检图像数据集 森林火灾烟雾图像识别 田间及农村烟雾图像识别 森林防火数据集 安防监控与火灾预警图像识别第10358期。这个“期”没有任何特殊含义就是我们内部按批次归档数据的编号。每期原始图像大概在2000到7000张之间经过抽帧、清洗、标注之后真正能进入训练集的约八成。第10358期这批数据的特点是场景跨度大既有高海拔林区的航拍俯视角也有平地农田的地面监控视角还有农村房前屋后的低角度画面。这对模型的泛化能力要求一下子就上来了。1.2 烟雾识别要解决的三个实际问题现实项目里用户不会关心你用的是YOLO还是什么他们只关心三件事误报多不多、漏报多不多、报警快不快。第一是误报。清晨的山谷雾气、村庄里的炊烟、水面的水汽反光这些在图像上都非常容易跟火灾烟雾混淆。我项目里最初版本的模型在雾天误报率一度高到20%值班员都懒得看报警提示了。第二是漏报。无人机在高空巡检时烟雾在画面里可能只占几十个像素人眼都要仔细看才找得到模型很容易直接忽略。第三是响应速度。森林防火讲究“打早打小打了”从识别到告警推送管道全链路延迟不能超过3秒否则无人机已经在空中转过去了报警信息才到意义就大打折扣了。所以这个项目表面上是做一个图像识别数据集本质上是解决一个复杂场景下的高召回、低误报实时检测问题。下面我按数据构建、模型训练、工程部署、问题排查四个层面展开讲整个实操过程。2. 核心数据集的构建逻辑与实操2.1 数据从哪里来怎么组织在项目启动阶段我最先做的不是找模型而是花了两周时间审定数据采集清单。因为模型效果的天花板由数据决定这句话在烟雾识别领域格外真实。我按照无人机航拍、杆塔监控、布控球三路来源分别录制约8小时、4小时、2小时的视频素材再统一做抽帧处理统一按每秒1帧到5帧抽取保证同一烟团在连续帧里有形态变化而不是静止图片堆砌。为了数据集的专业性我把图像整理成了三类目录raw/ # 原始抽帧图像 forest_air/ # 森林无人机航拍图像 field_ground/ # 田间地头地面摄像头图像 rural_monitor/ # 农村安防监控图像 annotations/ # 标注文件VOC格式XML forest_air/ # 对应森林航拍的所有标注 field_ground/ # 对应田间地面的所有标注 rural_monitor/ # 对应农村监控的所有标注 labels/ # 训练标签YOLO格式TXT train/ # 训练集标签 val/ # 验证集标签 test/ # 测试集标签 images/ # 切分好并重命名后的图像 train/ # 训练图像 val/ # 验证图像 test/ # 测试图像数据存储规范是后面一切工作的基础。我建议在项目一开始就固定这套目录不要后面改来改去。我有个朋友做的项目就是目录结构来回调整最后脚本全部重写白白浪费两周时间。2.2 标注规范比标注数量更重要标注环节是整个数据集构建里最枯燥但最关键的步骤。我们用LabelImg做标注内置包含四类标签smoke烟雾、fire明火、mist雾或水汽干扰、chimney炊烟。很多人会觉得奇怪为什么要专门把mist和chimney标出来呢这两类本身就是模型误报的主要来源把它们单独标成负样本类别让模型在训练时看到它们的形态特征比纯粹把所有非烟雾的区域都当背景要有效得多。标注时我定了一个硬规矩半透明烟雾用主要烟团轮廓框不把整片淡薄区域全框进去。举个例子一阵山风吹来烟团被拉成细长的丝带状视觉上很清楚但AI其实很难学。如果标注框把整条烟带都囊括进去正方形框附近几乎全是背景反而会让模型决策紊乱。所以我要求标注员只框住烟团密度较高、肉眼能明确辨别的核心区域。明火一定是可见火焰的至于炊烟识别关键看烟柱是否集中、颜色偏青灰、且形态是小范围聚集。这套标注规则执行下来平均一张图需要45秒到3分钟不等。12000多张有效图像前后投入5个人力连续忙了接近两周。期间我每天抽检50张发现有框偏了就退回返工。数据质量检查必须有人来做不能完全依赖标注器输出。我自己的经验是标注规范里提前定好“边界怎么框、遮挡怎么处理、极小目标怎么定义”否则后期清洗时的返工量会大到怀疑人生。2.3 数据清洗与切分技巧原始抽帧图像里有大量连拍重复帧无人机悬停时画面几乎不动这种情况必须去重否则训练集里相似度太高的样本会让模型过拟合到特定背景上。我用的策略是感知哈希去重加人工二次抽检。程序算一遍图像相似度丢掉超过阈值的相似帧再让标注员快速过一眼把仍然相似的去掉。清洗完的有效数据按照6:2:2的比例切分为训练集、验证集、测试集。切分有个硬约束同一个场景的连续帧不能跨集。比如无人机围绕同一片林区飞行时连续抽帧的画面要么全部在训练集要么全部在验证集。如果不这么做模型会在验证集上偷看到高度相似的图像指标虚高到真实场景就露馅。我拿第10358期的实际数据做个说明原始图像约18000张去重清洗后得到13200张有效图像。切分后训练集7920张验证集2640张测试集2640张。其中森林场景约占55%田间场景约30%农村监控场景约15%。在类别数量上烟雾目标的出现频次超出了我的预期占到了全部标注框的约七成可见项目中烟雾的形态比明火多得多。火焰往往在烟雾出现之后的某几帧才出现所以训练集里天然存在大量“有烟无火”的样本这正是现实应用里最常见的早期火情状态。3. 模型选型与训练实战3.1 为什么选YOLO以及分支选择在烟雾识别项目里我首选YOLOv8和YOLOv8因为它有几点和这个场景非常匹配推理速度快、显存占用可控、易于部署到边缘设备。我也试过更早的YOLOv5它在检测速度上很不错但小目标召回率不及v8而R-CNN系列检测精度虽然高但是实时性差单帧推理动辄几百毫秒完全不适合无人机巡检。在无人机边缘端模型推理最好控制在30ms以内否则飞机飞行的轨迹和云台视角配合不上烟雾区域可能已经飘出画面。具体到YOLO的几个版本里我实际使用的是YOLOv8m中规模网络在精度和速度之间比较平衡。如果让我给新手一个建议第一次跑通用n尺寸项目落地用m尺寸追求最高精度再考虑x尺寸。l和x先不用想因为在森林防火这种需要长时间续航的场景里功耗带来的续航焦虑比那两三个点的mAP更让人头疼。3.2 训练前需要准备的配置文件项目训练选用Ultralytics框架这是一套完整的训练推理工具链不需要自己再手写前向反向逻辑。首先是安装依赖和准备数据集pip install ultralytics然后看数据配置YAML文件。这份文件治理了整个数据集的读取路径和类别名称path: /data/smoke_detection/smoke_10358/ train: images/train val: images/val test: images/test nc: 4 names: 0: smoke 1: fire 2: mist 3: chimney注意path这里是绝对路径。我踩过坑相对路径在服务器上跑没问题但一换机器就全乱后面全靠猜所以统一用绝对路径最省心。3.3 训练超参数的调整心得训练命令我用的是yolo detect train \ data/data/smoke_detection/smoke_10358/dataset.yaml \ modelyolov8m.pt \ epochs300 \ imgsz1280 \ batch16 \ device0 \ patience40 \ augmenttrue \ cachetrue几个关键超参数展开说imgsz1280。这可能是整个训练里最重要的一步。无人机航拍画面是高空视角远处烟雾往往很小用640输入识别小目标会有明显漏检。加大到1280后小目标召回率提升非常明显但训练显存和耗时也随之上升。如果你的设备只能跑640那也没关系但不要指望小目标效果多好。patience40。这是早停机制如果连续40个epoch验证集指标没有提升就自动停止。森林烟雾数据变化幅度大训练后期loss曲线可能来回震荡给40个epoch的容忍空间比较合理。augmenttrue。使用Ultralytics自带的增强策略包括随机翻转、色彩空间抖动、针对烟雾场景很有用的MixUp和Mosaic等。烟雾在真实环境里本身就受到光照影响增强能提高模型在不同时间段的适应性。训练过程中我最关注的验证指标是mAP50-95因为这类数据集的自建测试集和实际应用场景最接近。训到后期mAP50-95稳定在0.51到0.58之间mAP50在0.72到0.78之间。如果你是头一次接触这类项目不用被数值迷惑关键要看亲测视频里烟雾到底检出没有。指标是参考实战是标准。3.4 训练不收敛的排查方向如果你的模型训练曲线一直上不去我建议按以下顺序排查先确认数据集路径对不对再去检查标签文件是否有空文件。然后看类别数nc是否和names一一对应names顺序错乱会让模型学疯。接着试降低imgsz到640或416排除目标和显存问题。最后检查数据集中负样本比例是否过大如果标注的烟雾目标数量实在太少模型只能学到“背景”输出自然差。我遇到过最离奇的问题是训练loss已经很低但验证集对一帧有明显烟雾的图像始终不出框。后来反复看数据才发现这一帧图像里烟雾被树枝半遮挡标注人员把框画得很小模型确实没有见过类似的正样本所以学不出来。解决办法是在数据增强里增加随机遮挡和局部裁剪的配置因为真实火灾场景里烟雾经常会被树冠遮挡被建筑遮蔽不是每次都是完整的烟团。4. 从模型到预警落地的工程化部署4.1 端侧部署与推理性能优化训练好的模型不能只活在一台训练机上。这个项目里的无人机巡检用的是边缘计算盒子。我部署推理时最关注的是延迟检测模型从摄像头输入画面到输出结果必须控制在100ms以内最好在30ms上下。我用TensorRT把模型导出为engine格式yolo export model/data/smoke_detection/weights/best.pt \ formatengine \ device0 \ imgsz1280 \ halfTrue导出为engine格式后在Orin NX级别的边缘设备上单帧1280推理约30msGPU利用率控制在百分之六七十左右同时可以并发处理4路摄像头画面。如果算力紧张可以把推理图缩到960或768输入速度会更快但小目标召回率有一定下降。核心原则是算力不够不要硬上大分辨率先用降低帧率或分段巡检来兜底保证告警链路不断。4.2 预警联动逻辑设计检测到烟雾之后系统要做的不是“画个框”而是形成一条完整的信息流。我设计的预警联动流程是这样的边缘端识别到烟雾置信度高于0.55触发时间窗口确认机制在连续5秒内至少2次检测到烟雾目标才判定为有效告警将告警截图、GPS定位针对无人机、检测框信息、置信度值推送到后端服务后端根据位置信息查询三维地图标注所属林班、小班号或田块信息推送到值班人员的移动端和管理后台。值班员复核之后系统转发到应急响应群同时附上路线建议。这套流程的关键前提是不要把置信度调得太高。我见过为了压低误报把阈值提到0.85的结果真发生火情时烟雾特征被云层干扰置信度只有0.7直接漏过去。阈值定在0.5到0.6之间同时用连续帧判断过滤偶然误报是最稳妥的做法。4.3 误报抑制的工程技巧工程层面抑制误报有几个低级但有效的做法我在项目里全用上了不可见光时段强制切换夜间监测无意义烟雾在夜视红外图像里的对比度很低我干脆在凌晨1点到4点这个时段把检测告警关闭而是在能见度较好的清晨和上午、午后站点重点巡检。动态ROI去干扰水上雾气通常出现在特定区域农田烧荒则通常在秋冬季节。我在配置后台增加一个可绘制的屏蔽区功能任何出现在屏蔽区内的检测结果直接丢弃这从根本上解决了烟气和无关雾气混淆的问题。比如某些河道上空水汽反射特别频繁我在后台直接把河道区域划成忽略区误报率直接下降一半。模型“双通道”参考对同一帧图像同时启用烟检测和为另一个轻量级目标检测。第二次检测只输出smoke和fire两次都确认才告警因为纯背景干扰两次同时误报的概率要小得多。5. 常见问题与排查技巧实录5.1 本地测试pipeline跑出来的效果和训练指标不一致这是最常见的问题。训练指标看mAP但真跑一版视频感觉什么都框不到。出现这种情况通常是因为测试视频的分辨率、色彩空间与训练数据差异过大。比如我用的是1280训练拍视频的相机是1920幅面软件在推流时做了缩放导致目标变小。解决办法很简单在pipeline里加入zero-padding等比缩放不要直接拉伸填满不然图像变形会让检测结果乱飘。5.2 无人机抖动导致目标闪烁告警时有时无无人机航拍时从一个角度飞到另一个角度视角变化会导致同一烟团不同帧之间形态差异大。解决思路是加一个损失函数损失函数中引入时序一致性约束或者用跟踪器配合。我实际选了另一种更贴近部署的方式调整云台策略在发现疑似烟雾后悬停5秒让推理侧连续多帧判断。虽然反应时间多了一点但把闪烁误报彻底压下来了。对于固定点位监控我直接加了简单的IOU跟踪同一检测目标在下一帧的位置预测结果与当前帧重叠度高于阈值才继续跟踪连续三帧未丢失就确认告警。5.3 错误框大量框住天空、云层和光线这类问题多发生在模型训练时过于关注“白色半透明的区域”因为烟雾很多场景里确实很白。我的复盘是训练集里负样本数量不足或者说富含有“无烟但背景复杂”的负样本太少了。我的补救方法是从实际监控视频里剪一段无烟片段抽帧后复制为负样本单独加入训练集。初级负样本可以当背景但一定要有“看似烟雾却不是烟雾”的近负样本模型才能学会区分。云端和岩壁的反光和白色物体全部作为近负样本重点标注后错误框的问题大幅减轻。5.4 数据增强能弥补数据量不足吗一定可以补但有上限。单独用Mosaic增强白嫖小目标样本效果远不如真实增加一批不同场景下的烟雾图像。第10358期数据正常训练mAP50大概在0.72左右。后来我把数据增强打开mAP50提升到0.76。但再往上走靠增强就不够了。想要在雾天、黄昏、光线很差的环境上提升最直接的办法就是单独采集特定时段的图像重新标注后加入训练集。模型没见过黄昏的烟雾就不可能在黄昏阶段识别出来这跟增强无关。5.5 常见问题速查表我整理了一份在实际项目里最常查的排查表分享给同行直接用现象原因排查方法漏检远处小烟雾训练分辨率太低或标注框太小imgsz提到1280检查小目标占比必要时单独采集小目标样本误报清晨雾气负样本不足增加真实无火雾气、反光水面、云层的近负样本检测结果闪烁单帧置信度波动加连续帧确认或轻量级目标跟踪无人机移动时识别全乱视角变化过大对相同烟团保持两到三秒连续悬停巡检夜间误报频繁红外下烟雾特征和模拟场景差异大关闭低可见度时段告警或单独做红外训练分支高分辨率图像检测慢模型推理耗时长TensorRT导出engine格式或降低输入分辨率一个烟团被分成多个小框标注框重叠过多后处理开启NMS调低IoU去重阈值到0.56. 实操中的一点个人体会做这类烟雾识别数据集和预警项目我感觉最大的难点从来不是模型的精度卷到多少而是把数据组织好、把误报漏报压到能用的水平、把链路跑通。在真实火灾预警场景里模型不需要每棵树都认得它只需要在烟刚冒头的那几十秒给值班员打一个电话、弹一个框这就算成功了。用第10358期这批数据集训出来的模型我在多个场景做过实测。森林上空俯视视角大范围烟气扩散时检测效果很好农田秸秆焚烧产生的烟柱因为形态集中且与背景对比明显检测也很稳最难处理的还是农村房前屋后的小范围烟雾经常有炊烟混杂这时除了靠模型还得靠连续帧判断和人工复核协同。项目做完后我最大的建议是先把数据规范和标注规则做到位再谈算法优化这两个环节做好了后面几乎是一路顺风。