☰
无人机航拍烟雾识别实战:从数据集构建到森林防火部署
2026/10/17 7:30:16 网站建设 项目流程

1. 从一张俯拍图聊起:无人机巡检到底想解决什么问题

无人机飞在200米高度上,云和烟的界限到底在哪里?这个看着像论坛提问一样的问题,其实是森林防火巡检项目里最核心的矛盾。做无人机航拍巡检图像数据集、森林火灾烟雾识别、田间及农村烟雾识别,绕来绕去都绕不开一件事:你必须在几百米高空,把一小缕灰色的烟从云层、雾气和地表的炊烟里分出来。我这次刚好把手头编号10358的这一期数据集整理完,趁热记录一下从数据整理到模型上线的全过程。

先说场景背景。过去几年做安防监控与火灾预警图像识别应用的团队越来越多,固定点位摄像头在瞭望塔、园区、高速公路两侧的部署已经比较成熟。但固定监控有一个天生短板:它只能看到安装位置能看到的那一片区域。森林山区的视线被遮挡严重,一棵树挡住另一棵树,一个山头挡住另一个山沟,等监控画面里出现明确火焰时,往往已经烧了一段时间。无人机航拍巡检不一样,它在空中飞行,视角是俯视的、移动的、广覆盖的,一次航线就能扫过几条山沟,这在火灾早发现场景里有不可替代的优势。

但“俯视移动视角”也给图像识别出了难题。固定监控里你习惯了水平视角的烟雾形态,换到无人机画面里,烟是从地面往镜头方向“顶”上来的,远处看是小小一团,近处看是一大片,不同高度拍摄同一股烟差别巨大。而且无人机本身在动,画面有果冻效应、运动模糊,光照还会随着航线方向和太阳角度剧烈变化。这些变量都不是靠加大训练集数量就能简单解决的,需要在数据准备阶段就认真设计覆盖策略。

这篇文章不打算写成教科书式的算法综述,而是围绕一个真实项目场景展开:怎么理解这份数据集里不同场景的含义,怎么标注烟雾和干扰物,怎么选模型和训练参数,以及最后部署上线时会遇到哪些意料之外的情况。如果你在做森林防火、农村烟雾监测、无人机巡检这类视觉应用,或者只是好奇“烟雾识别到底难在哪”,这篇应该能给你一些参考。

1.1 人工瞭望与固定监控的盲区:为什么会依赖航拍数据

传统森林防火巡护主要靠人工瞭望,护林员站在瞭望塔上拿望远镜看,或者在固定路线开车巡山。这个方法在天气好的时候有效,但在海拔高差大、树冠密集、阴天雾大的区域,漏报概率很高。一个护林员能同时盯住几个方向就已经不错了,视野内出现疑似烟点,还要靠经验判断是烟还是雾,距离远了连烟的浓度变化都看不清。

固定监控摄像头解决了“24小时有人在看”的问题,但解决不了“看不到”的问题。摄像头装在塔上,水平朝向周边山体,画面里树冠和山脊的遮挡是天然的盲区。即便现在有云台和热成像双光谱设备,也受限于机位位置,无法深入山谷、河谷这类火险高危区域。无人机航拍的优势恰恰在这里:无人机可以顺着既定航线飞进山谷,从正上方往下扫,或者沿着山脊线贴地飞行,画面覆盖的是固定监控看不见的区域。正因为如此,航拍巡检图像数据集的场景价值才会被单独拿出来说。

从预警链条来看,无人机航拍解决的也不是“灭火”那一环,而是“发现”这一环。发现越早,蔓延面积越小,处置成本越低。所以这类数据集在实际应用里最看重的指标不是检测精度有多好看,而是漏报率能压到多低。宁可每天多几次误报让后端人工复核,也不能让真正燃起的烟漏过去,这个逻辑贯穿了后面所有的标注和训练决策。

1.2 航拍数据集与普通烟火数据集的差异点

刚开始接触这个任务时,我下意识以为烟雾识别就是个普通的二分类或者目标检测问题,把公开的烟火数据集拿来训练就行。实际对比下来发现,差异比想象中大得多。

第一是视角分布。公开烟火数据集大多来自固定监控、手机拍摄,画面里烟通常占据较大面积,而且是水平视角。无人机航拍数据里,烟往往是俯视的小目标,可能只占整张图的百分之零点几。模型如果看惯了“大头烟”,遇到“小屁股烟”反而检测不出来。

第二是场景构成。森林里不仅有树冠,还有裸土、岩石、水体、阴影;田间有人工铺设的深色地膜、收割后的秸秆堆;农村有蓝色铁皮屋顶、白色塑料大棚、水泥路面。这些都会在画面里形成类似烟雾的纹理和颜色干扰。通用烟火数据集里很少覆盖这类航拍场景,直接用效果不佳。

第三是动态信息缺失。很多固定监控的火灾识别方案会用到视频帧间的动态特征,比如烟雾在连续帧中的扩散趋势。但航拍巡检数据处理时,单帧图像占了很大比重,有些任务甚至要求对单帧静态图做检测,这对模型的静态特征提取能力要求更高了。

2. 拆解一份森林/田间烟雾识别数据集,里面到底放了什么

标题里把“森林火灾烟雾”“田间及农村烟雾”“安防监控与火灾预警”放在一起,看起来是三类场景,其实对应的是三种完全不同的拍摄对象和干扰背景。搞不清楚这一点,数据标注阶段就会开始糊涂。我自己在整理10358期数据时,第一步不是抽帧,而是把所有原始图像按场景语义分了三大类,然后才针对每一类去设计标注规则。

2.1 三类场景的拍摄对象与背景差异

森林场景,主要拍摄对象是天然林和人工林。画面里以树木、山体、裸岩、沟壑为主。烟雾来源大概率是树冠火或林下火产生的烟羽,烟的颜色偏灰白或灰褐色,扩散方向受山谷风影响明显,有时会贴着树冠低空流动。森林场景的干扰物是山地雾、云层在山体上的投影、远处的低矮积云。

田间场景,拍摄对象是农田、耕地、秸秆堆放区。秸秆焚烧是这类场景烟雾的主要来源。特点是烟柱比较集中、边界相对清晰,颜色偏青白或灰白,燃烧点通常在地表,烟在大田里看起来会拖成一条长带。田间场景的干扰物是地膜反光、收割机扬尘、灌溉水雾、翻耕后大面积裸土的颜色纹理。

农村场景,拍摄对象是村庄、院落近旁的焚烧点。生活垃圾、枯枝落叶燃烧产生的烟比较松散,经常混着塑料燃烧的黑烟,颜色明显偏深。农村场景最棘手的是炊烟,尤其清晨和黄昏,家家户户屋顶升起灰蓝色的烟气,和火灾初期烟雾在单张图片上几乎没有本质区别。

这三种场景的干扰物不同,标注难度也不同。我建议数据准备阶段做一份“场景—干扰物—烟雾特征”对照表,方便后续筛选容易误报的难例图像。这里列一下我常用的划分方式:

场景烟雾常见来源烟雾颜色特征最主要的干扰物标注难度
森林林下火、树冠火灰白、灰褐色,形态受气流影响山雾、云影、低空云高
田间秸秆焚烧、荒地烧草青白、灰白,烟柱集中扬尘、地膜反光、水雾中
农村生活垃圾、炊事用火灰蓝、深灰,可能夹黑烟炊烟、屋顶阴影高

2.2 标注类别设计:烟、火、干扰物怎么定义

很多人会把标注类别直接设为“fire”和“smoke”两类,听起来没错,但实际训练时很容易处罚模型混乱。因为烟雾图像里火点往往被烟遮挡,即便裸露出火点,在无人机高度上也很难看清。我在这次项目中把类别设计成了四类:可见明火、明显烟雾、疑似烟雾、干扰物。

可见明火对应画面中能明确看到火焰的区域,这类标签数量通常很少,因为无人机到达时大部分火点已经被烟覆盖,或者距离太远连火焰细节都拍不清楚。明显烟雾就是肉眼能确认的烟羽,标注框尽量框住烟的实体区域,不要把外围非常淡的扩散区算进去。疑似烟雾是针对那些“像烟但不完全确定”的目标准备的,比如远处一条垂直的浅灰色带,标注时打上疑似,训练时通过权重调整来处理。干扰物则是一个比较特殊的类别,包括云、雾、扬尘、反光等,把它们标出来让模型学会“这些不是烟”,比单纯靠负样本学习更高效。

这里有一个必须强调的点:标注框的边界。烟雾没有固定边缘,标注员对同一股烟画出的框差别很大。为了减少这种不一致,我在项目里固化了一套规则:以肉眼可见的烟羽不透明区域为准画框,扩散开后变得半透明的尾部不纳入框内;如果烟柱从地面升起,框从地面起点开始;如果画面里同时有多个烟羽,每个独立烟羽分别画框,高度上明显属于同一个源头的可以用一个框覆盖,但要保持标准一致。

2.3 目录、格式与切分的实操建议

数据集目录我习惯这样组织:

10358_dataset/ ├── images/ │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── raw_frames/ # 未筛选的原始抽帧 ├── scene_tags.csv # 每张图的场景标签(森林/田间/农村) └── meta.json # 数据来源、拍摄高度、飞行平台等元信息

标注格式上,如果主力框架是YOLO系列,直接用txt格式的归一化坐标比较方便,每行一个目标:class_id x_center y_center width height。如果对接的是检测加分割混合任务,可以额外导出一份COCO格式的JSON,用来自动生成分割掩码或者做后续的半自动标注。我的习惯是源头保留一份COCO格式作为“母版”,再脚本转换成YOLO格式,这样换框架时不会作废重标。

切分数据时有个反直觉的坑:不能直接随机切。无人机航拍数据集通常是按“趟次”拍的,同一趟航线里相邻帧高度相关,如果随机切分,模型在训练集里见过同一场景的不同帧,验证集里也出现这个场景的邻近帧,精度会虚高。在真实部署时无人机每次飞的区域可能有变化,模型必须对没见过的场景有泛化能力。所以我按视频片段或飞行架次来切分,同一架次的所有帧进同一个集合,保证训练集和验证集在场景层面相互独立。

3. 训练烟雾识别模型前,先把这几个问题想清楚

数据集准备好之后,大家最容易犯的错就是直接开训。烟雾识别这个任务如果不提前想清楚几点,训练过程会非常折磨人,表现好的模型反复掉点,还不知道问题出在哪。

3.1 为什么烟雾比火焰更难学

火焰有清晰的亮橙色区域,形状虽然跳动但颜色和亮度特征非常强,模型学起来相对容易。烟雾不是这样的,烟雾的本质是半透明的细颗粒悬浮物,它的颜色、纹理、透明度都随浓度变化。同一股烟,靠近源头的部分浓且不透明,扩散区域渐渐变淡,最后融入背景;在俯视画面里,背景可能是绿色树冠、黄色农田、灰色水泥屋顶,烟雾叠加在上面,呈现出不同的混合颜色。

这意味着模型不能只学“烟雾长什么样”,它还得学会“烟雾叠加在不同背景上会变成什么样”。背景变化越多,学习难度越大。另一个难点是烟雾和干扰物的类间相似性。云和烟都是灰白色的、边界模糊的团状物;雾和烟一样呈半透明状,在山谷里还会顺着地形流动;炊烟在颜色上和清晨湿气几乎无法区分。这些相似目标会把模型的特征空间搅乱,直接提升误报率。

我在训练前专门做了一组对比实验,把几千张含云的图像作为负样本加入训练集,模型在验证集上的误报率下降明显。这个结论听起来简单,但很多人做烟雾检测时会忽略掉云这类高频干扰,值得专门提一下。

3.2 模型选型:YOLO系列为主,但别忽略小目标层

烟雾识别在工业项目里首选还是YOLO系列,推理速度快,工程支持好,部署方便。具体版本上,YOLOv8和YOLOv5我都跑过,如果硬件算力足够,建议直接用YOLOv8;如果要在老一点的嵌入式设备上部署,YOLOv5依然够用。主要差别不在于精度,而在于训练工具链和部署生态的便利度。

但有一个关键点:基础YOLO结构对远距离小目标烟雾的敏感度不够。无人机在150米高空看一股刚燃起的烟,目标可能只有十几个像素大小,普通检测层很难有效捕捉。我实测下来有几个有效的改进方向。

第一是增加小目标检测层。YOLOv8的P2层对微小目标有专门的感受野设计,可以用它替换或增加检测头,代价是推理时延略有增加。第二是切图推理,把大图切块成比如640×640的若干小图推理,再把结果映射回原图坐标。这个方法对小目标非常有效,代价是会重复检测,需要做NMS合并。第三是在模型里加注意力机制,比如在C2f模块后面插入轻量级的注意力,让小目标烟雾区域的特征权重提高。

跑在Jetson设备上的话,我会再配合TensorRT做FP16量化,实测在保证精度不大幅下降的前提下,推理速度能提升差不多一倍。当然量化后要重新跑一遍验证集,烟雾这种边缘模糊目标对量化误差比较敏感,偶尔会出现原本能检测到的薄烟被过滤掉的情况。

3.3 数据增强与超参数的一些经验值

烟雾检测的数据增强要克制一些。像Mosaic这种拼接增强能提升模型的定位能力,但拼接会产生很多不自然的纹理边界,特别是把农田和森林拼在一起,容易让模型学到“画面有拼接痕迹就可能是烟”的错误关联。我自己的做法是Mosaic只在训练前中期使用,最后几十个epoch关闭,让模型在干净的原始图像上做参数收敛。

颜色增强方面,要仔细调亮度、对比度、色相的范围。无人机在不同光照条件下拍摄的画面明暗差别很大,但过强的颜色增强会把云的灰色拉成烟的灰白色,反而增加误报率。我的经验是亮度扰动控制在±20%,对比度扰动控制在±15%,色相不要动,饱和度做一点微小扰动即可。

超参数方面,有几个以YOLOv8为基准的经验值可以参考。输入分辨率设置成1280×1280或1280×640,太小的话小目标直接淹没在特征图里。Batch size在单卡A30/A100上可以开到16或32,但烟雾数据集通常不是特别大,过大batch size反而容易陷入sharp minima,我用16左右效果比较稳。学习率初始值0.01配余弦退火,weight decay设0.0005,这组参数在多个数据集上都比较稳定。类别不平衡问题通过调整loss权重来处理,可见明火类的权重可以适当调高,因为这类样本通常最少但最紧急。

4. 无人机视角实测,最容易翻车的几类画面

训练完成后的实测阶段才是真正的考验。航拍视角下很多训练时没注意到的画面问题会集中爆发。我挑几个翻车最严重的场景说一下,这些基本都是实际飞行中真实出现的,解决方式也是一点一点试出来的。

4.1 云、雾、炊烟:误报重灾区的特征对比

无人机航拍画面里,误报最多的是云和雾。有一次测试,模型把一片远方低空云识别成了烟雾,置信度居然到了0.75以上。回看那帧图像,云的形态呈柱状向上发展,颜色灰白,下方正好有山体阴影衬托,看起来确实和森林烟羽几乎一样。这类误报很难通过单纯增加负样本彻底解决,因为物理特征上相似度实在太高。

我后来做了一个特征统计表,把误报比较多的目标拉出来对比,帮助判断哪些特征值得模型去区分:

目标颜色趋势形态边界透明度与地形关系
森林烟雾灰白到灰褐随时间变化,风向拉扯边缘逐渐扩散中心不透明从地面/树冠升起
云白色,上表面明亮团状稳定,移动缓慢底部通常较平不透明浮在山体之上
雾蓝灰,均匀大面积铺开模糊弥散半透明沿山谷、低洼地分布
炊烟灰蓝或深灰柱状,夜间更难分边缘均匀中等贴近屋顶,低矮

这个表在误报调优里很有用。比如模型报出低置信度目标时,人工复核可以快速判断是不是云。后来我把表的内容做成提示词喂给一个辅助分类小模型,让它在检测结果上做二次过滤,误报率又压下去一截。

炊烟的问题更隐蔽。清晨和黄昏时段,无人机航线如果经过居民区上空,画面里会出现大片的炊烟。这些烟柱在单帧画面上和焚烧产生的烟几乎没有区别。我的实际处理是:对农村场景单独采集一批炊烟样本加入训练集,并且调整检测策略为“低置信度保留、高置信度预警”。炊烟问题靠纯视觉比较难根治,最稳妥的办法是结合巡检路线和时段时间信息,在已知居民区上空飞行时适当提高报警阈值,同时安排地面复核。

4.2 远烟、薄烟、半透明烟的漏检问题

漏检比误报更致命。训练过程中我发现,模型对浓烟很敏感,但对远处的薄烟经常直接漏掉。原因很直观:距离越远,烟羽越细,目标像素很少,特征也很弱;距离近的半透明烟,又因为亮度对比不足,模型抓到它之后置信度很低,被阈值过滤掉。

针对远烟,最有效的方法是切图推理配合高分辨率输入。把4K航拍图切成若干1280×1280的小块,每个小块单独推理一次,检测置信度会比整图直接推理高不少。这个做法会带来同一股烟在小块重叠区域被重复检测的问题,解决办法是降低重叠率到10%左右,再对映射回原图的框做一次合并。实测下来,相同数据下远烟漏检率能降低一半以上。

针对半透明烟,还有一个很实用的做法:利用时间上下文。连续帧中烟雾是动态变化的,云和建筑物不会快速扩散。在部署推理时做一个简单的帧间状态跟踪,同一检测框在连续若干帧都出现,并且位置和形状有缓慢膨胀趋势,判定为烟雾的可信度大幅提升。这个方法在单帧检测基础上能把很多薄烟从漏检边缘拉回来。

4.3 运动模糊、曝光跳变和海拔变化的影响

无人机飞行不是静止的,机身抖动、云台转向、高速飞行都会造成运动模糊。运动模糊对烟雾检测的影响有两个方面:烟羽边缘被拉淡,目标特征减弱;背景纹理也变得模糊,模型容易把模糊的大片区域误判为烟雾。在数据准备阶段一定要加入模糊增强策略,我自己是在训练时对一部分图像施加不同程度的随机高斯模糊和方向模糊,模拟飞行抖动效果。模型学会模糊特征后,实测抗抖动能力明显变强。

曝光跳变则发生在无人机转向或云层遮挡太阳的瞬间,画面突然变暗或者突然过曝。过曝画面里烟雾目标一片死白,变成与背景完全融合的高亮区域,模型难以分辨。对这类极端曝光图像,与其让模型硬学,不如在预处理阶段加入自动曝光校正,先把图像拉回正常亮度范围再推理。单帧上的瞬时光照跳变,则需要靠后端预警逻辑做连续帧确认,避免单帧过曝产生误报。

海拔变化影响的是目标尺度分布。无人机在100米和500米高度拍摄同一股烟,目标尺度差异巨大。如果训练数据集中在某个高度范围,模型在其他高度的表现会打折。我在筛选数据时会刻意按高度打标签,在meta.json里记录每帧的飞行高度,训练时按高度分桶做均衡采样,确保每个高度区间都有足量样本。

5. 从数据集到预警系统:部署联调和上线闭环

模型训完只是第一步,真正决定项目成败的是能否稳定跑在巡检系统里,把检测结果转成有人处理的预警事件。这个环节是我觉得很多团队会低估的部分。实际上,视觉效果不错的模型一装到无人机和边缘设备上,各种问题就冒出来了。

5.1 边缘设备上的推理优化

无人机端的算力有限,常用的推理设备是Jetson系列或者自研的边缘盒子。这些设备上要跑规模不小的检测模型,优化是必须的。首先是模型导出,PyTorch模型先转ONNX,再用TensorRT做FP16推理优化,这一步能明显降低时延。其次是输入尺寸权衡,1280×1280的输入在边缘盒子上跑起来比较吃力,可以动态选择:航线高度高时用1280,低空巡检时切到960或640,在保证小目标检测能力的同时提升帧率。

另一个容易被忽略的点是输入缓冲和预处理。航拍视频流如果直接走CPU解码加BGR转换,CPU占用会飙升,推理被拖住。正确的做法是用硬件加速解码,比如Jetson的硬解通道直接输出YUV,在GPU上做缩放和色彩转换,减少内存拷贝。实测中这部分优化能省下不少时间,让整体帧率从十几帧提升到二十帧以上。

部署时还要考虑温控。无人机机身上设备散热差,持续高负载推理容易触发降频,表现为检测时延突然波动。我在实际项目里给推理进程做了类优先级调度,并在管线里加入丢帧逻辑,在CPU占用过高时主动跳过部分帧,保证关键帧的检测优先处理。

5.2 预警消息的防抖与去重

无人机巡检时,同一股烟雾会在连续几十帧画面中反复出现。如果每一帧都推一条预警消息,值班人员会被淹没。线上系统必须做检测结果的时序聚合。我实现的方式是维护一个目标跟踪列表,每次检测通过IoU匹配已有目标,连续匹配超过N帧且平均置信度超过阈值,才触发一条预警。同时给每一条预警设置冷却时间,同一个目标在冷却时间内不重复提醒,防止长期的烟雾目标反复刷屏。

置信度阈值也要因地制宜。森林大场景里,我一般把检测置信度阈值设为0.3左右,宁可多报一点,让后端人工判断;而在居民区等容易误报的区域,阈值提到0.55,避免炊烟导致大量无效预警。这个阈值是动态的,跟随航线经过的场景切换,而不是用全局固定值。实测下来,这个策略能把每天的误报次数从几十条压到个位数,同时漏报没有明显增加。

5.3 误报复核与数据回流

预警系统上线后要形成一个持续优化的闭环。每一次预警产生时,系统自动截取一段现场图像和检测框快照,推送到值班人员的复核工作台。值班人员确认后,结果分为两类:如果确认是真实烟雾,相关帧自动进入置信度较高的样本集;如果确认为误报,相关帧进入难例样本集。

这些回流样本的价值非常大。无人机航拍环境不断变化,不同季节、不同地物、不同光照条件下都会出现新的干扰物,训练集不可能一次覆盖完毕。我会每两周从回流难例里筛选一批新样本,和原有数据合并后做一次增量训练。这个过程不需要从零开始,沿用之前训练好的权重做fine-tune,几百张难例补进去就能显著改善该类型误报或漏检。

顺带说一个细节点:标注回流数据时不要完全依赖之前的标注结果,因为新出现的干扰物类型可能和旧类别有语义交叉。比如某种新的农业设施在俯视画面中会反光,看起来像浅色烟柱,如果直接标成干扰物,可能学到的特征是“这个特定位置的反光”,而不是“这个颜色的反光不是烟”。这种情况下标注时最好把反光区域单独截出来做聚类,分析它的共性特征后再决定怎么融入训练。

从数据整理到模型上线,整个流程走下来,我的体会是:航拍巡检烟雾识别的难点不在单一算法环节,而在整个链路对真实场景变化的适应能力。一份好的数据集是起点,持续回流更新才是让系统长期稳定可靠的关键。后面再有机会,我想把增量训练过程中的具体调参细节也整理出来分享,这篇就先到这里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询