news 2026/10/15 14:26:52

基于 YOLOv8 + PySide6 的火焰烟雾检测系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 YOLOv8 + PySide6 的火焰烟雾检测系统

博主介绍

一线CV算法工程师 / 毕设实战派导师 / 踩坑无数但都填平了的老司机

从事计算机视觉与深度学习落地开发多年,主攻目标检测、视频分析、边缘部署方向。做过安防监控、工业质检、智慧交通等多个方向的真实项目,不是只会跑demo的调参侠,是从数据标注、模型训练、推理加速到GUI开发、打包部署全链路都亲手趟过的人。
一句话:从选题到答辩,从代码到论文,从跑通到跑快,都能给你兜底。


前言

这是一篇本科毕业设计的完整实录。项目目标是做一个低成本、多路 RTSP、抗红色误报、支持硬件自动识别与自动加速选择的火焰烟雾检测系统。

硬件环境:AMD Ryzen 5 5600X + AMD RX 7650 GRE 8GB + 16GB 内存 + Windows 10,没有 NVIDIA 显卡,没有服务器

整个项目从零开始,踩了不少坑,也积累了一些经验,写成博客分享给同样在做毕设的同学。


一、项目功能概览

  • 支持多路 RTSP 视频流同时检测(海康、大华、TP-LINK 等)

  • 没有多摄像头时,用 MediaMTX + FFmpeg 把本地视频推成 RTSP 模拟摄像头

  • 硬件自动识别:OS、CPU、内存、GPU、NPU、已安装加速库

  • 自动选最优加速后端,失败自动降级

  • PySide6 桌面 GUI,多路画面、报警、日志、性能报告一体化

  • 视频区支持动态网格布局(1x2、2x2、2x4、3x3、4x2、4x4)

  • 双击某路画面全屏,ESC 退出

  • 多帧投票 + 双层去抖,降低误报

  • 支持 ONNX Runtime DirectML 加速

  • 全程面向对象开发,工厂 + 策略 + 观察者 + 单例 + 模板方法


二、技术栈

类别技术
检测模型YOLOv8n(ultralytics 8.4.176)
推理加速ONNX Runtime DirectML
GUIPySide6
视频流OpenCV + FFmpeg + MediaMTX
跟踪自实现轻量 IOU 跟踪器
日志Loguru
可视化matplotlib
Python3.14.3

三、项目结构

text

fire_smoke_detection/ ├── configs/ │ ├── cameras.yaml │ ├── accelerate.yaml │ ├── gui.yaml │ └── detection.yaml ├── models/ │ └── best.pt ├── scripts/ │ ├── start_mediamtx.ps1 │ ├── push_streams.ps1 │ ├── stop_streams.ps1 │ ├── export_onnx.py │ └── benchmark.py ├── src/ │ ├── core/ │ │ ├── config_manager.py │ │ ├── logger_manager.py │ │ ├── hardware_probe.py │ │ └── model_loader.py │ ├── accelerators/ │ │ ├── base_accelerator.py │ │ ├── accelerator_factory.py │ │ ├── onnxruntime_accelerator.py │ │ ├── pytorch_accelerator.py │ │ └── ... │ ├── streams/ │ │ ├── base_stream_reader.py │ │ ├── rtsp_stream_reader.py │ │ ├── file_stream_reader.py │ │ └── frame_queue.py │ ├── detection/ │ │ ├── detector.py │ │ ├── tracker.py │ │ └── voting_manager.py │ ├── alarm/ │ │ ├── alarm_event.py │ │ └── alarm_manager.py │ └── gui/ │ ├── pyside6_gui.py │ ├── camera_widget.py │ ├── video_grid_widget.py │ ├── fullscreen_viewer.py │ └── ... ├── tests/ ├── videos/ ├── alarms/ ├── logs/ ├── requirements.txt └── README.md

四、核心模块设计

4.1 硬件自动识别

启动时自动探测本机硬件,输出logs/accelerator_report.json:

python

@dataclass class HardwareInfo: os: str cpu: str memory_gb: float gpus: list[dict] npus: list[str] installed_libs: dict cuda_version: str | None rocm_version: str | None

探测结果示例(我的机器):

json

{ "os": "Windows 10 (10.0.19045)", "cpu": "AMD Ryzen 5 5600X 6-Core", "memory_gb": 15.93, "gpus": [ {"vendor": "AMD", "name": "Radeon RX 7650 GRE", "vram_gb": 7.98} ], "available_backends": [ "ONNXRuntime-DirectML", "ONNXRuntime-CPU", "PyTorch-CPU" ], "selected_backend": "ONNXRuntime-DirectML" }

4.2 加速器工厂 + 策略模式

抽象基类定义接口,具体后端继承实现:

python

class BaseAccelerator(ABC): @abstractmethod def load_model(self, path: str) -> None: ... @abstractmethod def infer(self, frame: np.ndarray) -> list: ... @abstractmethod def warmup(self) -> None: ... @abstractmethod def get_name(self) -> str: ... @abstractmethod def is_available(self) -> bool: ... @abstractmethod def get_device(self) -> str: ...

工厂按优先级自动选择,失败自动降级:

python

class AcceleratorFactory: PRIORITY = [ "TensorRT", "ONNXRuntime-DirectML", "ONNXRuntime-CPU", "PyTorch-CPU", ] def auto_select_backend(self) -> str: for name in self.PRIORITY: acc = self.try_init_backend(name) if acc is not None and acc.is_available(): return name raise RuntimeError("没有可用的推理后端")

TensorRT、OpenVINO、CoreML 因硬件不匹配,保留占位符,is_available()恒返回False,架构完整但不影响降级链。

4.3 多帧投票 + 双层去抖

第一层(track 级):连续 5 帧中 3 帧命中才报警。

python

class VotingManager: def vote(self, track: Track) -> bool: history = self._history[track.track_id] history.append(1 if track.cls_name in ("fire", "smoke") else 0) if len(history) > self.window: history.popleft() return sum(history) >= self.min_hits

第二层(摄像头 × 类别):10 秒冷却,防止刷屏。

python

class AlarmManager: def _should_suppress(self, event: AlarmEvent) -> bool: key = (event.camera_id, event.cls_name) last = self._last_alarm.get(key) if last is None: return False return (datetime.now() - last).total_seconds() < self.cooldown

4.4 动态网格布局

VideoGridWidget预创建 16 个CameraWidget,切换布局只做 show/hide + 重排,零重建、零丢帧:

python

class VideoGridWidget(QWidget): camera_double_clicked = Signal(int) def set_layout(self, rows: int, cols: int): while self.layout.count(): item = self.layout.takeAt(0) w = item.widget() if w: w.setParent(None) total = rows * cols for i in range(total): r, c = divmod(i, self.cols) self.layout.addWidget(self.cameras[i], r, c) self.cameras[i].show() for cam in self.cameras[total:]: cam.hide()

4.5 双击全屏

CameraWidget双击发信号,主窗口打开FullScreenViewer:

python

class CameraWidget(QLabel): double_clicked = Signal(int) def mouseDoubleClickEvent(self, event): self.double_clicked.emit(self.cam_id)

主窗口在update_frame时同时推送网格和全屏窗口,单一数据源,天然同步。

4.6 模拟摄像头

用 MediaMTX + FFmpeg 把本地视频推成 RTSP:

powershell

ffmpeg -re -stream_loop -1 -i videos/fire.mp4 ` -c:v libx264 -preset veryfast -tune zerolatency ` -pix_fmt yuv420p -f rtsp rtsp://localhost:8554/cam1

没有多摄像头也能测试多路并发。


五、踩坑记录

坑 1:Hugging Face 下载超时

国内直连 Hugging Face 基本不可能。解决方法:

python

import os os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

或者直接浏览器手动下载best.pt放到models/。

坑 2:Git Bash 里激活虚拟环境

\.venv\Scripts\activate在 Git Bash 里报错,因为反斜杠是转义符。正确写法:

bash

source .venv/Scripts/activate

坑 3:Python 3.14 + onnxruntime-directml

Python 3.14 太新,某些包没有预编译 wheel。实测onnxruntime-directml能用,但未来如果某个包报ImportError,直接降到 Python 3.11 或 3.12,零成本。

坑 4:DirectML 加速有限

实测 ORT-DirectML 比 ORT-CPU 快约 2 倍,但远不如 NVIDIA + TensorRT 的 5-10 倍。原因是 DirectML 的算子覆盖不全,NMS 等后处理可能落到 CPU。

这本身就是毕设的一个有效结论,论文里可以写"在 AMD 消费级显卡上,DirectML 对 YOLOv8 加速有限,主要瓶颈在算子覆盖和后处理"。

坑 5:PySide6 + matplotlib 兼容性

PySide6 6.12 + matplotlib 3.11 的backend_qtagg偶尔有兼容问题。解决方案是加降级保护:

python

try: from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg HAS_MPL = True except ImportError: HAS_MPL = False # 降级到 QTableWidget

坑 6:多线程更新 UI 崩溃

PySide6 禁止子线程直接操作 UI 控件。必须用信号槽:

python

class DetectionWorker(QThread): frame_ready = Signal(int, np.ndarray, str, bool) alarm_raised = Signal(object) def run(self): # 子线程推理,只发信号 self.frame_ready.emit(cam_id, frame, text, alarm)

六、性能数据

后端FPS延迟(ms)CPU%
PyTorch-CPU12.381.365
ONNXRuntime-CPU18.753.558
ONNXRuntime-DirectML45.222.135

测试环境:AMD RX 7650 GRE + Ryzen 5 5600X,单路 1080P 子码流,imgsz=640,batch=1。

DirectML 相比 CPU 提升约 2.4 倍,相比 PyTorch-CPU 提升约 3.7 倍。


七、误报优化

针对"红色衣服人行走"的误报问题,采取三层策略:

  1. 数据层:加入红色衣服、红车、夕阳等负样本,标注为other类

  2. 推理层:提高 fire_conf 阈值到 0.5-0.6,smoke_conf 到 0.4-0.45

  3. 后处理层:多帧投票 + 双层去抖 + IOU 跟踪

合成测试视频上的误报率从优化前的 12% 降到 2% 以下。


八、经验总结

8.1关于面向对象

每个类单独文件,职责单一,虽然文件多,但:

  • 论文里能画清晰的类图

  • 答辩时能讲设计模式

  • 后续改功能不用动其他文件

8.2关于硬件加速

AMD 显卡在 Windows 上跑深度学习,DirectML 是唯一现实的选择。ROCm 对消费级显卡支持有限,不要在上面浪费时间。

如果预算允许,二手 NVIDIA 显卡(如 RTX 3060 12GB)在深度学习上体验会好很多,TensorRT 生态成熟。


九、后续改进方向

  • 支持更多类别(加入other类,进一步降低误报)

  • 模型轻量化(剪枝、蒸馏)

  • 部署到边缘设备(Jetson、RK3588)

  • 增加 Web 端远程查看

  • 支持报警推送(邮件、微信、Webhook)


十、结语

整个项目从零开始,踩了不少坑,但最终跑通了完整流程。

如果这篇文章对你有帮助,欢迎点赞收藏。有问题欢迎评论区交流。


项目地址:[GitHub 链接]

参考:

  • Ultralytics YOLOv8 官方文档

  • ONNX Runtime DirectML

  • MediaMTX

  • PySide6 官方文档


标签:YOLOv8 火焰检测 烟雾检测 PySide6 ONNX Runtime DirectML 本科毕设 计算机视觉

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 14:26:14

SpringBoot旅游订票系统开发与高并发优化实践

1. 项目概述与核心价值 旅游景点订票系统是当前文旅行业数字化转型的典型应用场景。这个基于SpringBoot的全栈项目&#xff0c;涵盖了从后端API开发到前端交互、数据库设计乃至部署上线的完整生命周期。我曾在多个景区信息化项目中采用类似架构&#xff0c;实测证明这种技术组合…

作者头像 李华
网站建设 2026/10/15 14:25:08

STM32直线倒立摆控制实战:从LQR算法到嵌入式实时部署

简介&#xff1a;本资源是一套基于STM32微控制器实现直线倒立摆动态平衡控制的完整嵌入式工程代码&#xff0c;面向自动化、控制工程与嵌入式系统方向的本科生、研究生及开发者&#xff0c;解决经典非线性控制系统建模、实时算法部署与硬件闭环调试等核心实践问题。压缩包共214…

作者头像 李华
网站建设 2026/10/15 14:24:49

云客服会话数据,怎么做结构化统计和分析?

摘要&#xff1a;云客服会产生大量聊天会话原始数据&#xff0c;如果不做结构化处理&#xff0c;很难提取有效业务信息&#xff0c;本文分享会话数据统计分析的实现方法。从数据采集、清洗、结构化建模、指标定义、技术选型对比到可视化与工程落地&#xff0c;给出可复用的方案…

作者头像 李华
网站建设 2026/10/15 14:23:48

几片晶圆封装无配套产线:小批量订单的封测困局与破局之道

几片晶圆封装无配套产线的行业现象剖析 在半导体封测领域&#xff0c;一个不容忽视的现实是&#xff1a;设计公司或初创团队手中握有“几片晶圆”的流片成果&#xff0c;却往往找不到合适的封装产线来完成后续工序。这种“几片晶圆封装无配套产线”的困境&#xff0c;并非个例&…

作者头像 李华
网站建设 2026/10/15 14:23:37

适合新手的量化交易工具解析,从代码平台到零代码策略

聊到量化交易&#xff0c;很多人脑子里会出现满屏代码。其实现在的工具已经分成了不同路线&#xff1a;一种时用Python写策略&#xff0c;一种是条件单和可视化模板创建策略。但量化的核心没有变&#xff0c;都是把选股、买卖、仓位这些想法变成明确条件&#xff0c;让系统按条…

作者头像 李华
网站建设 2026/10/15 14:23:14

ORA-01403与ORA-06512错误解析:PL/SQL中no data found的定位与根治

1. 这不是报错&#xff0c;是Oracle在给你递纸条——读懂ORA-01403和ORA-06512的真实含义刚看到“ORA-01403: no data found ORA-06512: at line 12”这串字符&#xff0c;很多刚接触PL/SQL的开发者第一反应是慌&#xff1a;数据库崩了&#xff1f;数据丢了&#xff1f;程序跑飞…

作者头像 李华