YOLOv8森林烟火检测:从数据集构建到部署落地的完整实践

发布时间:2026/10/12 0:21:13
YOLOv8森林烟火检测:从数据集构建到部署落地的完整实践 简介面向森林防火与计算机视觉应用场景这份基于YOLOv8的森林烟雾火焰检测工程包内置源码、数据集、说明文档与测试视频适合希望快速搭建烟雾火焰识别模型的开发者、研究者和学生参考。压缩包共2003个文件约373.97MB主体为987张jpg图片与981个txt标注文件配套4个pt权重、2个yaml配置、11个mp4及1个3gp测试视频另有模型说明docx、results.csv、验证集预测/标注图等覆盖数据准备、模型训练到效果验证的完整流程。该工程包已有1496人学习下载目录结构清晰便于按模块检索。借助模型说明文档可了解YOLOv8火焰检测、烟雾识别与森林火灾实时监控的关键原理训练事件文件与多段测试视频能辅助对照预测效果便于直接基于近千张标注样本开展训练、评估与二次开发。1. YOLOv8 森林烟火检测这份工程包的完整构成森林防火巡检里烟雾和火焰的检测越来越依赖视觉模型但很多人卡在第一步数据集难找标注格式五花八门训练到一半发现自己整理的数据根本跑不起来。这份资源正好撮合了这个断层——它是一个能直接训起来、直接推理的 YOLOv8 森林烟火检测工程源码里带了数据集、训练脚本、推理脚本和说明文档解压之后目录结构清楚训练流程是完整的。它的价值不在于算法多新而在于这本身就是一套能落地的基线你拿到它不必从零收集数据不必纠结标注格式直接在预训练权重上微调或从头训练就能得到一个检测火焰和烟雾的模型。适合的人群很具体一是需要给无人机或监控摄像头配一个烟火识别模块的开发者二是刚学目标检测、想要一个真实场景数据集来练手的学生。这套东西不承诺那种动辄 99% 的夸张精度而是老老实实给你一条能复现的训练链路让你在现有基础上做调优。2. 数据集与标注规范训练前先把训练素材摸透2.1 目录结构与文件组成压缩包解压后第一眼看到的是相对规整的目录典型的组织方式是这样的fire_smoke_dataset/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练用的 txt 标注 │ └── val/ # 验证用的 txt 标注 └── data.yaml # YOLOv8 需要的数据集配置images 和 labels 是严格一一对应的每张图片对应一个同名 txt 文件。这个对应关系是后续所有脚本的根基换自己数据时千万别把这两层的对应关系改掉否则训练时加载器经常会报found no labels或者更隐蔽地静默跳过一批图让你以为训练数据很多实际有效数据少了一截。我第一次拿到这种数据集时习惯先跑一个校验脚本确认图片能打开、标注文件不是空的、类别编号没有越界。常见的做法是写一个 Python 脚本刷一遍import os from PIL import Image img_dir images/train lab_dir labels/train for name in os.listdir(img_dir): # 只处理图片文件 if not name.endswith((.jpg, .png, .jpeg)): continue # 找同名标注文件 label_file os.path.join(lab_dir, name.rsplit(., 1)[0] .txt) if not os.path.exists(label_file): print(f[缺失标注] {name}) img Image.open(os.path.join(img_dir, name)) img.verify() # 只校验文件头速度快 print(f[OK] {name} size{img.size})这段脚本做的事情很简单遍历每张图片检查标注文件是否存在再用 PIL 打开图片确认不是损坏文件。参数上要注意img.verify()只做基础校验不会真正解压全部像素所以跑全量数据也不会太慢。如果发现某张图本身就是 0 字节训练时 YOLO 会直接跳过它但推理时一旦碰到就会报错最好在训练前把这类脏数据清掉。2.2 标签格式与类别设定YOLO 格式的标签不是框坐标的绝对值而是归一化后的相对值一行代表一个目标class x_center y_center width height这四项全是小数范围在 0 到 1 之间是相对于图片宽高的比例。比如一个火焰在 640x480 的图片里中心点像素坐标是 (320, 240)宽度占了一半高度占了三分之一那对应的一行就写成1 0.5 0.5 0.5 0.333333这份资源里的烟雾和火焰一般定义成两个类别通常是0: smoke, 1: fire具体以 data.yaml 里的 names 字段为准。训练前要把类别顺序记死因为推理时输出的类别编号就是按这个顺序来的排错了画框的时候标签就会张冠李戴。有一种常见错误是把背景当成了第三个类别。YOLO 格式不允许出现 background 类别背景是靠没有任何标注的像素隐含表达的。如果标注文件里出现了第 2 类训练能硬跑但最终模型的输出维度会多一个永远学不明白的类精度会受到实质影响而且不容易察觉。2.3 数据划分与重复帧检查拿到数据集先看 train 和 val 的比例这个资源给出的划分一般是 8:2 或 9:1具体数量以 labels 目录下文件数为准。如果自己重新划分数据需要保证 train 和 val 之间没有同源图片——比如同一段视频连续抽帧得到的帧一部分进了 train 一部分进了 val验证集就形同虚设了mAP 会显得虚高等真上现场就露馅。我一般把近重复照片的排查写进脚本import hashlib import os def file_md5(path): h hashlib.md5() with open(path, rb) as f: for chunk in iter(lambda: f.read(8192), b): h.update(chunk) return h.hexdigest() train_imgs [n for n in os.listdir(images/train) if n.endswith((.jpg, .png))] val_imgs [n for n in os.listdir(images/val) if n.endswith((.jpg, .png))] train_hash {file_md5(os.path.join(images/train, n)) for n in train_imgs} dup [n for n in val_imgs if file_md5(os.path.join(images/val, n)) in train_hash] print(重复文件:, dup)MD5 校验比较慢但一次能抓出真正的重复文件。像素内容完全相同但文件名不同的图片MD5 一致如果图片被重新压缩过MD5 会变那种情况可以叠加感知哈希pHash查近似重复属于进阶做法。数据校验这件事看着琐碎其实决定了整个训练流程后面会不会翻车我见过不止一次因为训练和验证集污染导致指标虚高、上线后被现场数据反噬的案例这一层过滤值得在动手训练之前做掉。3. 训练环境与参数把第一个模型跑起来3.1 环境安装与依赖版本这份源码基于 ultralytics 的 YOLOv8 实现训练环境主要依赖 Python、PyTorch 和 ultralytics 包。最简单的安装方式是用 pip 建一个干净环境Python 3.8 到 3.10 都行我一般用 3.10。PyTorch 版本要注意和 CUDA 驱动匹配比如 CUDA 11.8 对应 torch 2.1.x装错了会运行时报libcudart之类的动态库错误。python -m venv venv source venv/bin/activate pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install opencv-python pillow pyyaml逻辑上分成两段先是虚拟环境隔离再是装训练相关的包。ultralytics包本身集成了 YOLOv8 的训练、验证、导出命令不需要额外装复杂的训练框架。--index-url指定 CUDA 版本的 pytorch 源CPU 机器就把后缀去掉直接装默认版本。装完后跑一下yolo detect predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg验证链路能出框说明环境没毛病。3.2 数据集配置文件与训练启动训练前需要一份 data.yaml这份资源已经内置了关键内容长这样path: fire_smoke_dataset train: images/train val: images/val nc: 2 names: 0: smoke 1: firepath是数据集根目录train 和 val 是相对根目录的图片文件夹路径nc是类别数names的编号必须和标注文件的 class 字段对得上。很多人把 path 写成绝对路径项目目录移动之后又要改一次我习惯直接用相对路径并保证终端从项目根目录启动训练。训练命令yolo detect train \ datafire_smoke_dataset/data.yaml \ modelyolov8s.pt \ imgsz640 \ epochs100 \ batch16 \ device0 \ projectruns \ namefire_exp1简单拆解一下参数modelyolov8s.pt是yolov8s的预训练权重resource 里应该也有对应的初始权重文件imgsz640会把训练图片统一缩放为 640x640batch16是批量大小取决于显存epochs100是训练轮数project和name决定权重和日志的输出目录。如果显存吃紧先把 batch 调成 8 或 4也可以换yolov8n.pt起步但检测精度会低一些。3.3 训练监视与损失曲线解读训练过程中ultralytics 会在runs/fire_exp1/下生成results.png和权重文件。results.png 里画了四类曲线主要看 box_loss、cls_loss 和 dfl_loss。box_loss 是框回归的误差cls_loss 是分类误差dfl_loss 是分布焦点损失。随着训练推进train 的三个 loss 应该稳定下降val loss 降到某个点后如果开始反弹就是过拟合的早期信号。tensorboard --logdir runs或者在 python 里直接读 results 目录下的 CSV 文件自己画我习惯用 tensorboard 看曲线方便对比多次实验。训练完看runs/fire_exp1/weights/下有两个文件best.pt和last.pt。best.pt是验证集上 mAP 最好的权重last.pt是最后一轮的权重。部署和继续训练的基准都选best.pt不要手滑拿 last.pt 去推理效果差不少。4. 推理与部署从单张图片到视频巡检4.1 图片与视频推理脚本训练出的权重直接可以用于推理这份源码里提供的是基于 ultralytics 的调用方式from ultralytics import YOLO # 加载训练好的权重 model YOLO(runs/fire_exp1/weights/best.pt) # 推理单张图片 results model.predict( sourcetest_images/forest_01.jpg, conf0.25, iou0.45, saveTrue, imgsz640 )conf0.25是置信度阈值低于 0.25 的框会被丢掉iou0.45是 NMS 交并比阈值控制重叠框的合并力度。这两个参数是推理阶段最需要调的。saveTrue会直接把画了框的结果图存到当前目录实测时方便肉眼看效果。处理视频或者摄像头的逻辑几乎一样唯一区别是source换成视频文件路径或者摄像头编号results model.predict( sourcevideos/forest_camera.mp4, conf0.3, iou0.5, imgsz640, streamTrue, saveTrue )加了streamTrue后模型会按帧生成结果内存不会一次性被视频帧占满。如果发现某个视频里烟和火检测断断续续多半是单帧检测漏检这种场景建议把conf调到 0.2 以下宁可多画几个误检框也别放过真的火情。4.2 导出 ONNX 与边缘设备部署训练完的.pt权重只能在 PyTorch 环境里运行实际项目要么部署到服务端要么下放到 RK3588 这类边缘 NPU 板子上。常见做法是先导出 ONNXyolo export modelruns/fire_exp1/weights/best.pt formatonnx imgsz640 dynamicTruedynamicTrue允许动态输入尺寸方便后期切换分辨率。导出后可以顺手用onnxruntime验证一下导出的模型输出import onnxruntime as ort import numpy as np from PIL import Image session ort.InferenceSession(best.onnx) img np.array(Image.open(test.jpg).resize((640, 640))) img img[:, :, ::-1].transpose(2, 0, 1) # HWC 转 CHW img np.expand_dims(img, 0).astype(np.float32) / 255.0 outputs session.run(None, {session.get_inputs()[0].name: img}) print(outputs[0].shape)验证 ONNX 模型有两点很关键一是输入维度和归一化方式要和训练时一致YOLOv8 一般输入NCHW的 RGB 图除以 255二是输出是1x84x8400的矩阵其中 84 表示 4 个框坐标加上 80 个类别概率但从这个源码数据集训练出来的模型类别数只有 2所以输出维度是1x6x8400左右解析时要注意按实际的nc调整。如果目标平台是 RK3588常见流程是 ONNX 再转成 RKNN 格式精度的损失一般能控制在 1%~2% 的 mAP 范围内森林烟火检测这种相对大目标的任务可以接受。4.3 输出解析与结果过滤拿到模型输出后还需要自己完成 NMS 之后的解析完整的处理代码如下import numpy as np def postprocess(output, conf_thres0.25, iou_thres0.45): # output shape: (1, 6, 8400) preds np.squeeze(output, 0) # (6, 8400) # 前4行是 cx, cy, w, h后两行是类别概率 boxes preds[:4, :].T # (8400, 4) scores preds[4:, :].T # (8400, 2) class_ids np.argmax(scores, axis1) confs scores[np.arange(len(scores)), class_ids] keep confs conf_thres boxes, class_ids, confs boxes[keep], class_ids[keep], confs[keep] # 简单 NMS 逻辑可换成 cv2.dnn.NMSBoxes from cv2 import dnn indices dnn.NMSBoxes( boxes.tolist(), confs.tolist(), conf_thres, iou_thres ) return boxes[indices], class_ids[indices], confs[indices]这段是在边缘端用 C 或纯 Python 推理时的通用后处理模板。这里的 8400 是 640x640 输入下三个尺度特征图的预测框总数如果用别的输入尺寸这个数会变。模型输出的坐标是归一化的中心点和宽高换算成像素时记得乘回原图的宽高。5. 避坑排查森林烟火检测最容易翻车的五个问题5.1 坑一训练 loss 很漂亮验证 mAP 却惨不忍睹现象训练三条 loss 曲线都在下降best.pt也保存了但验证集 mAP 只有 0.2 左右肉眼检查结果图发现大量漏检。原因大概率是训练集和验证集存在数据污染。很多森林烟火数据来自视频抽帧相邻帧之间高度相似如果不做去重就随机划分验证集里几乎全是训练集里看过的图模型记住了帧的内容而不是烟火特征。另一个原因是标注错误某一类标签混入了大量噪声框。解决用前面提到的 MD5 去重脚本把重复帧清掉再重新划分 train 和 val。标注层面随机抽样 20 张图人工核对重点看标签框是否贴合目标、类别是否标反。森林画面里远处的烟雾经常被标成 fire这类错误会直接把精度拖下来。5.2 坑二烟雾怎么调都检测不出来现象火焰检测效果还行但半透明的烟雾基本不触发尤其是清晨林间薄雾和白色背景下的浅淡烟雾。原因烟雾是半透明目标边缘模糊特征没有火焰那么明确。数据集里如果烟雾样本偏少或者标注框把大范围的弥散烟雾框得太大导致标注质量差模型就很难学出稳定的纹理特征。解决降低推理阶段conf到 0.15 左右先看有没有检出同时收集更多正样本专门补充薄雾、远山背景下的烟雾图。训练时对烟雾类别做 mosaic 增强把它放到不同背景里合成多样本。常见的做法是把数据增强的 hsv_h、hsv_s 参数调大改变烟雾在色相和饱和度上的分布让模型不要只认固定颜色。5.3 坑三小目标火焰漏检率高现象远处的零星火点、几百米外的明火人眼能看到模型当成背景直接忽略。原因森林场景多为广角大图火焰像素占比往往小于 1%。YOLOv8 在 640x640 输入下小目标可能在下采样后只剩几个像素特征图上的响应微弱自然检不出来。这是目标检测的经典小目标问题不是配置参数玄学。解决有两个方向。一是训练时把imgsz提到 960 或 1280小目标保留的像素多了精度会明显上升训练时间也会成倍增加。二是部署时对原始大图做切块把一张 4K 图切成 4 个 640x640 的小块分别推理再合并结果。后者在无人机巡检场景里很实用代价是推理耗时变大。5.4 坑四训练时显存溢出现象启动训练后没几个 epoch直接报CUDA out of memory进程被杀。原因batch size 和 imgsz 组合起来超出了 GPU 显存。6000 张图听起来不多但 YOLOv8s 在 640 输入下batch 16 大约需要 10GB 显存如果是 8GB 的显卡这个问题会立刻爆出来。解决一是把 batch 降到 8 或 4二是加ampTrue开启混合精度训练显存占用能降 30% 左右三是用梯度累积ultralytics 里没有内置参数可以通过调低 batch 并手动改训练循环实现。在 GTX 1660 Ti 这种入门卡上我一般用 batch 8、amp 开启的方式能跑完 100 个 epoch。5.5 坑五白天的效果不错黄昏和夜晚却失效现象白天测试的检测框很准换成黄昏、逆光或夜间红外画面模型大面积漏检。原因训练数据的光照分布太集中。森林烟火检测的数据大多来自日间监控截图黄昏和夜间样本稀疏模型没有见过足够多的低照度特征自然会失效。解决训练时把语义相关的增强打开hsv_h、hsv_s调大是其一更直接的是给数据集补充低照度样本。图像预处理可以用histogram equalization做一次 CLAHE 增强把夜间画面的对比度提上来再喂给模型。如果做的是夜间森林防火建议单独采集红外或热成像数据训练专门的模型明暗特征差别太大一个模型通吃白天黑夜本身就有点强人所难。6. 进阶验证用热力图定位模型的注意力盲区这一节说一个我强烈建议做的验证动作热度图可视化。模型训练完mAP 也看了但你仍然不知道它到底在看照片的哪个区域。森林烟火场景里火往往只占画面的很小一块模型可能学歪了靠画面里一些背景特征判断只在特定的山地背景下有效换个场景就漏检。热力图就是把模型对检测框的决策做反向传播算出每个像素对输出的贡献权重最终以伪彩色叠加在原始图上看看模型注意力集中在哪个位置。举个例子如果一张森林图里有一团烟雾和一栋小房子模型把烟雾框出来后热力图却显示注意力集中在小房子的边缘那模型学到的可能是地形特征而不是烟本身。这种情况下调整数据比调参数更有效——增补不同背景的烟雾样本让模型必须学会烟雾本身的纹理和颜色特征。实现热力图不需要自己从零写反向传播常见做法是宿舍里跑一个基于梯度类激活映射的思路用 ultralytics 的模型对象取中间层特征再做梯度加权汇总。简化版的思路是这样的import torch from ultralytics import YOLO model YOLO(runs/fire_exp1/weights/best.pt) m model.model.float().eval() # 注册前向钩子抓取最后一层骨干特征 features {} def hook_fn(module, input, output): features[out] output.detach() handle m.model[-4].register_forward_hook(hook_fn) img torch.rand(1, 3, 640, 640) # 实际换成真实图像张量 output m(img) handle.remove() # 反向传播取梯度计算加权激活图 act features[out] grad torch.autograd.grad( output.sum(), act, retain_graphTrue )[0] weights grad.mean(dim(2, 3), keepdimTrue) heatmap (act * weights).sum(dim1).squeeze() heatmap heatmap.clamp(min0).numpy()这段代码只是一个最小的框架实际使用时需要把显式构建的图像经过合适的归一化处理model.model内部的结构在不同 ultralytics 版本里有差异可以打印 model 结构定位最后一层骨干特征图的位置。热力图不需要每张测试图都跑选几十张有代表性的场景烟雾、近火、远火、误检图各抽几张就能大致判断数据够不够全面。从那以后我每次迭代一版数据集都会先抽 30 张图跑一遍热力图再决定要不要训练省下大量反复训练的时间。训练之前先看模型在旧权重上的注意力分布比训练后才发现问题要高效得多。这一步虽然简单但能避免你把几天时间花在一个对背景过拟合的模型上。希望这份基于 YOLOv8 的森林烟火检测工程和这些排查思路能帮到你少踩几个我当年踩过的坑。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询