ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

YOLOv8火灾检测实战:结构、训练与GUI部署

YOLOv8火灾检测实战:结构、训练与GUI部署 简介基于YOLOv8的火灾烟雾检测系统完整资源包面向深度学习开发者、安全监控项目人员以及火灾检测相关专业学生。内含训练好的best.pt和last.pt权重支持图片、视频和摄像头三种输入方式的实时检测配套PyQt5编写的图形界面可一键导出检测结果到指定目录方便快速搭建演示或实际部署。整个压缩包共33个文件大小16.18MB组成包括两个pt权重文件、两个Python推理脚本、yaml环境配置、训练曲线与混淆矩阵等可视化图表、结果统计csv以及readme说明文档。权重与代码结构清晰适合作为YOLOv8火灾检测项目的基线参考。目前已有523人学习。借助这份资源能省去数据标注与训练调参时间直接运行图形界面体验完整检测流程也能基于现有代码进行二次开发是入门烟雾火灾检测和YOLOv8实践的实用工具。1. 火灾检测不是换个数据集那么简单YOLOv8 的边界要先想清楚把 YOLOv8 用在火灾检测上常见做法是下载一套带权重的工程源码然后跑一下图片、视频、摄像头三种输入总觉得「能出框」就完事了。但实际交付过的人都知道火灾检测真正麻烦的是两类问题一是火焰边缘在热浪扰动下形态不稳定标注本身就有噪声二是烟雾是半透明目标置信度天然偏低直接套用 COCO 预训练权重的默认阈值很容易出现漏报或者框在乱跳。这篇内容就围绕一套可落地的 YOLOv8 火灾检测系统来展开训练好的权重要怎么组织、推理代码怎么写才能同时吃图片/视频/摄像头、GUI 界面怎么在不卡界面的前提下显示检测结果以及结果导出时要注意的坐标和编码问题。适合要亲手交付这套系统的人也适合刚入行、想照着一个完整结构做目标检测项目的开发者。2. YOLOv8 模型结构拆解C2F、Anchor-Free 检测头和火灾小目标的关系2.1 C2F 模块如何改善火灾目标的梯度流YOLOv8 的 backbone 里C2F 是替换 YOLOv5 C3 的核心模块。它的结构是输入先过一个 1x1 卷积将通道数降下来然后分成两条路径一条直接向后传播另一条依次经过多个 Bottleneck关键区别在于每个 Bottleneck 的输出都会保留下来最后在通道维度上拼接再通过 1x1 卷积恢复输出通道。相比 C3 只保留整个模块最后一个输出C2F 相当于把分支里每一层学到的特征都拿了出来梯度回传时可以选择更短的路径绕过中间层。这个设计对火灾检测的意义在于烟雾区域本身纹理弱、对比度低经过多层卷积后小目标的响应容易被背景淹没。C2F 更丰富的梯度路径能让网络在前几层就保留住烟雾边缘的低阶特征避免信息在深层传播里被稀释。在 ultralytics 的实现里C2F 的实例化参数包括nBottleneck 数量和hidden_ratio隐藏层通道比例默认配置下 YOLOv8s 的 C2F 使用 3 个 Bottleneck这个数量在精度和速度之间已经比较平衡不需要为火灾场景特意加深。2.2 SPPF 与 PAN-FPN多尺度特征怎么传给检测头YOLOv8 在 backbone 末端接了 SPPF 模块把同一份特征图分别做 1/5/9/13 像素的池化再拼接起来。这个设计的价值在于固定监控视野里火灾目标的尺寸跨度非常大远处刚冒出的烟可能只有十几个像素近处的大火可以占满整帧画面。SPPF 用不同池化核把不同感受野的信息拼在一起让后面检测头能同时注意到这两类极端尺寸。之后是 PAN-FPN 路径聚合网络它除了自顶向下的特征传递还加了一条自底向上的路径把浅层的位置信息和高层的语义信息做双向融合。针对烟雾这类边缘模糊的目标位置信息尤其重要因为烟雾框的定位误差主要来自边界不确定性而不是语义判断错误。这也是为什么 yaml 结构里 YOLOv8 沿用 PAN-FPN 而不是简单 FPN 的原因。2.3 Anchor-Free 解耦头为什么它对火灾更友好YOLOv8 的检测头有两个特点一是分类和回归分支解耦各自用独立的卷积二是回归分支使用 Anchor-Free 方式直接预测每个位置到目标框四条边的距离配合 DFL 损失把距离分布建模成概率分布再取期望。对火灾检测来说最大的好处是不再依赖聚类生成的 anchor 表。火焰和烟雾的形状极不规则传统 anchor 机制如果长宽比设置不合理训练时正样本数量会很不均匀导致召回率偏低。Anchor-Free 让模型在每个特征图位置上自适应学习边框对长宽比奇怪的火灾目标容忍度更高。DFL 的作用也值得一提火焰边界在热浪中不稳定标注时即使是同一个框不同标注员画出的边缘差异也很大DFL 通过分布建模弱化了对单一边框数值的强依赖训练时不会因为少数标注偏差产生过大梯度。2.4 模型尺寸怎么选参数量、帧率与部署目标火灾检测场景的算力差异很大从 Jetson Orin Nano 到服务器 GPU 都有。下表是几个常见型号的参考对比帧率为 640 输入在单卡环境下的大致表现实际数值会受 batch、线程数和 TensorRT 影响。如果需要精确实测建议用系统自带的yolo benchmark modelweights/best.pt命令在目标设备上跑一遍。模型参数量级640输入参考帧率适用场景YOLOv8n约 3.2M150~180 FPSRK3588 等边缘盒子YOLOv8s约 11.2M80~110 FPSGTX 1660 Ti / Orin NanoYOLOv8m约 25.9M50~60 FPS单路服务器 GPUYOLOv8l约 43.7M30~35 FPS多路视频流分析YOLOv8x约 68.2M20~25 FPS追求最高精度火灾检测属于单类或双类目标检测任务类别数少YOLOv8s 在精度和速度上通常已经够用。如果摄像头数量多且没有 GPU考虑 YOLOv8n 并配合后续蒸馏如果画面里小目标烟雾占比高可以直接上 m 或 l 级模型靠输入尺寸 768 或 1024 提升小目标召回。3. 环境搭建与推理代码从权重文件到图片、视频、摄像头三种输入3.1 用 conda 装出干净的 ultralytics 推理环境权重文件一般放在weights/目录下和推理代码、GUI 代码分离这样换模型时不需要改业务代码。环境搭建推荐用 conda 隔离避免把系统 Python 搞乱conda create -n fire python3.10 -y conda activate fire pip install ultralytics opencv-python pandasultralytics 包会自动安装 torch 依赖但默认装的是 CPU 版本。如果本机有 NVIDIA GPU需要把 torch 换成 CUDA 版以 CUDA 12.1 为例pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121安装完成后用python -c import torch;print(torch.cuda.is_available())验证输出True才说明 GPU 可用。这里有个经常踩的坑训练机器的 CUDA 版本和推理机器的 CUDA 版本不一致时模型在加载时有概率直接报 CUDA error所以交付前最好在目标机器上做一次权重加载测试不要假设本地跑通就一定能部署。提示OpenCV 在无显示器 Linux 服务器上调用cv2.imshow会报错需要屏蔽 GUI 显示或用 Qt 窗口替代下文 GUI 部分会专门说明。3.2 三合一推理脚本一个入口处理图片、视频和摄像头推理代码的核心是拿到输入来源后判断类型再走对应分支。摄像头传0或其他设备编号图片传路径视频传视频文件路径。下面是一个可以直接用的三合一函数import cv2 from pathlib import Path from ultralytics import YOLO def run_inference(source, weightsweights/best.pt, conf0.25, imgsz640): model YOLO(weights) # 摄像头source 是设备编号如 0 if isinstance(source, int) or str(source).isdigit(): cap cv2.VideoCapture(int(source)) while True: ret, frame cap.read() if not ret: break results model.predict(sourceframe, confconf, imgszimgsz, verboseFalse) annotated results[0].plot() cv2.imshow(fire-detect, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() return # 图片 if isinstance(source, (str, Path)) and Path(source).suffix.lower() in [.jpg, .jpeg, .png, .bmp]: results model.predict(sourcesource, confconf, imgszimgsz, verboseFalse) annotated results[0].plot() cv2.imwrite(output_annotated.jpg, annotated) print(f检测到 {len(results[0].boxes)} 个目标) return # 视频文件 cap cv2.VideoCapture(str(source)) fps int(cap.get(cv2.CAP_PROP_FPS)) writer None while True: ret, frame cap.read() if not ret: break results model.predict(sourceframe, confconf, imgszimgsz, verboseFalse) annotated results[0].plot() if writer is None: h, w annotated.shape[:2] writer cv2.VideoWriter(output_video.mp4, cv2.VideoWriter_fourcc(*mp4v), fps, (w, h)) writer.write(annotated) cap.release() writer.release()代码里的几个关键参数按场景调conf0.25是置信度阈值低于这个值的框会被滤掉监控场景想要减少漏报适量调低到 0.2但随后误报会增加imgsz640是输入分辨率检测小目标烟雾时可以提高到 768显存占用同时上涨verboseFalse关闭每帧日志输出否则视频推理时终端会被刷屏。results[0].plot()返回的是画好框的 BGR 图像直接用 OpenCV 显示或写盘即可。这里有个容易忽略的问题model.predict每次调用都会做预处理和后处理视频循环中如果verboseTrueCPU 占用会比推理本身还高。另外不要在循环里重复调用YOLO(weights)模型加载一次就够了放在循环外。3.3 验证权重是否健康先看这三项再交付拿到一套「训练好的权重」先不要急着接 GUI按下面三步验证第一跑yolo val modelweights/best.pt datafire.yaml查看 mAP50 和混淆矩阵。如果 jar 包自带数据集这步能直接得到精度指标没有数据集时至少用三张没参与训练的图片做人工 sanity check分别挑白天大火、夜间火光、远距离小烟雾三种典型场景。第二检查类别 ID 映射。火灾检测一般有两种单类fire或双类fire, smoke。权重文件里的names是训练时固化下来的推理端必须和它一致否则会出现「烟雾框但打印成火焰」的低级错误。在代码里可以通过model.names打印确认model YOLO(weights/best.pt) print(model.names) # 例如 {0: fire, 1: smoke}第三验证推理设备的显存占用。best.pt 在 CPU 上跑一张 640 图片可能需要 200ms 以上如果交付给了只有 CPU 的用户可能需要换成 ONNX 格式并启用halfTrue。4. 用自己的火灾数据微调模型数据集组织、训练参数与损失曲线判读4.1 数据集怎么组织目录、标注格式和常见标注错误如果系统里不包含训练脚本通常的做法是从公开火灾数据集起步再用自己监控场景的截图做增量微调。公开数据集一般已经转成 YOLO txt 格式但类别命名不统一拿到手第一件事是统一类别。建议只保留fire和smoke两个类别最多加一个background或直接忽略类别越多误报率越高。目录结构按 YOLO 标准组织datasets/fire/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── fire.yamlfire.yaml内容如下train: ./datasets/fire/images/train val: ./datasets/fire/images/val nc: 2 names: [fire, smoke]标注时最容易犯的错误是「框大不框准」。火焰的边缘在热浪里不断抖动标注时看到红色就尽量框住整个火苗但火苗核心区才是有判别力的区域框得太大反而让模型学到背景。烟雾同理标注时把半透明区域完整框进去不要只框浓烟部分。另一个常见问题是数据增强没有针对性火灾训练时fliplr通常可以开因为水平翻转不改变火的语义但hsv_h色相扰动建议保持默认 0.015不要大幅度调整否则会出现绿色火焰这种不真实训练样本。4.2 训练命令与超参数含义从 yolov8s.pt 起步从官方预训练权重yolov8s.pt上继续训练比从零训练收敛快很多。训练命令如下yolo train modelyolov8s.pt \ datadatasets/fire/fire.yaml \ epochs100 \ imgsz640 \ batch16 \ device0 \ patience20关键参数的推荐值与原因参数推荐值说明modelyolov8s.pt火灾检测类目少s 级性价比最高边缘设备用 nepochs100~150火灾数据集一般几千张100 轮足够收敛配 patience 早停imgsz640~768小目标烟点占比高时调大显存不够则优先降 batchbatch16~32与显存挂钩默认自适应OOM 时减半optimizerauto 或 AdamWauto 会自动选 SGD小数据集上 AdamW 收敛更稳patience20验证损失连续 20 轮不降则停止防止过拟合浪费时间训练过程中 ultralytics 默认开启 Mosaic、MixUp、HSV 扰动等数据增强。有一个细节Mosaic 增强会在最后 10 个 epoch 自动关闭这是官方设计目的是让网络在最后阶段适应真实分布不用手动干预。训练完成后runs/detect/目录下会有best.pt和last.pt两个权重best.pt是验证集上表现最好的交付时用这个last.pt是最后一个 epoch 的调试时看用。4.3 怎么读 results.png损失曲线和混淆矩阵的判读方法训练结束后打开runs/detect/exp/下的results.png里面有三组关键曲线train/box_loss、train/cls_loss、train/dfl_loss以及对应的验证集曲线。判断标准很简单训练损失持续下降验证损失不再下降甚至回升就是过拟合信号直接拿patience停掉即可不用硬跑满 epoch 数。更值得看的是confusion_matrix.png。火灾检测的常见问题是smoke类别大量被分到背景这时回到数据集检查标注半透明烟雾区域如果漏标模型会学到「边缘模糊的目标背景」。反过来如果fire和smoke互相混淆说明两类特征太接近常见解决方法是合并成单类fire只在后处理逻辑里区分火焰和烟雾。损失函数方面YOLOv8 默认 CIoU 配合 DFL 已经够用部分项目尝试把回归损失改成 SIoU 确实在火灾数据上有一点提升但收益和调参成本不成正比建议先把数据做干净再考虑。5. GUI 界面、推理线程与导出细节把检测能力交给非技术用户5.1 用 PySide6 搭 GUI推理必须放 QThreadGUI 界面用 PySide6 实现时最容易犯的错是把model.predict直接放在按钮回调里。图片推理还能忍视频和摄像头实时流会让界面彻底卡死。正确做法是检测逻辑放QThread主线程只负责显示结果。from PySide6.QtCore import QThread, Signal import cv2 from ultralytics import YOLO class DetectWorker(QThread): frame_ready Signal(object) def __init__(self, source, weights, conf0.25): super().__init__() self.source source self.model YOLO(weights) self.conf conf self.running True def run(self): cap cv2.VideoCapture(self.source) while self.running: ret, frame cap.read() if not ret: break results self.model.predict(frame, confself.conf, verboseFalse) self.frame_ready.emit(results[0].plot()) cap.release()主线程里连接frame_ready信号把图像转成QImage后setPixmap更新界面。视频流场景中摄像头读取和模型推理在同一个线程帧率受模型速度限制但界面不会卡顿。如果视频源是本地文件建议在 Worker 里用cv2.VideoWriter边读边写避免内存堆积。5.2 导出功能标注图、CSV 坐标、视频三种格式一次做全结果导出要覆盖使用者的实际需求可视化检查用标注图后续数据分析用 CSV 坐标存档用视频。CSV 导出代码import pandas as pd def export_csv(results, output_path): rows [] for box in results[0].boxes: x1, y1, x2, y2 box.xyxy[0].tolist() rows.append([ box.cls.item(), box.conf.item(), round(x1), round(y1), round(x2), round(y2) ]) df pd.DataFrame(rows, columns[class_id, conf, x1, y1, x2, y2]) df.to_csv(output_path, indexFalse, encodingutf-8-sig)这里用utf-8-sig编码避免 Windows 下 Excel 打开 CSV 中文乱码。输出文件名统一用时间戳比如fire_20250610_143022.csv方便大量告警图归档。5.3 三个具体技巧帧率、重复识别和阈值策略实时检测的三个调优点。第一摄像头缓冲会导致画面延迟随手势系统越来越大cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)可以强制读取最新帧同时把imgsz从 640 降到 480视觉损失不大但帧率可能提升 20%。第二运动的物体经过摄像头只识别一次这个问题本质是置信度抖动导致反复报警简单的做法是连续三帧都在同一位置检测到目标且置信度上升超过 0.1 才触发告警不需要引入跟踪器。第三烟雾和火焰不要共用同一个conf烟雾是半透明目标置信度天然低单独给smoke用 0.2、fire用 0.3能同时兼顾两类目标。本文还有配套的精品资源点击获取
返回列表