首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python3GUI--基于YOLO的火焰与烟雾检测系统By:PyQt5(详细图文介绍)

python3GUI--基于YOLO的火焰与烟雾检测系统By:PyQt5(详细图文介绍)

原创
作者头像
懷淰
修改2025-07-27 08:50:07
修改2025-07-27 08:50:07
14600
代码可运行
举报
文章被收录于专栏:PyQt5PyQt5
运行总次数:0
代码可运行

@toc


一.前言

1.引言

火灾作为威胁人类生命和财产安全的主要灾害之一,早期识别对减少损害至关重要。传统的烟雾探测器作用范围有限,而基于计算机视觉的火焰与烟雾识别系统能够覆盖更广泛区域,实现及时预警。本项目的开发具有多方面重要价值:它可应用于商场、学校、地铁站等公共场所,实现全天候监测,快速发现火情隐患,争取人员疏散的宝贵时间;在石油化工、电力及制造等高风险行业,能够实时监控异常火焰和烟雾,防止严重事故发生;结合无人机及监控设备,可用于大范围森林火灾防控,解决传统人工巡逻效率低及覆盖面窄的问题;系统还能集成到智能家居平台,提升家庭火灾报警能力,尤其适合无人居住的场景;此外,本项目验证了YOLOv8算法在火焰烟雾检测中的适用性,为相关领域研究提供了宝贵的实践经验和技术支持;从经济角度来看,该视觉检测方案相较传统火灾报警系统安装维护成本更低,覆盖范围更广,显著降低安全保障投入;社会层面上,它通过技术手段有效降低火灾发生频率及损失,有助于营造更加安全的社会环境,保障人民生命与财产安全。

2.正文

朋友们好!本次给大家介绍我开发的“基于YOLO的火焰与烟雾检测系统”,本系统通过自行训练YOLO目标检测模型,使用PyQt5制作交互界面,设置了多种告警方式以及数据可视化方案,用户能够设置详细的目标检测参数配置,系统支持多种输入数据源,主打美观实用!接下来我以详细图文的方式和大家介绍我开发的系统~

二.核心内容

1.数据集

我们的数据集包括了包含烟雾和火焰的图像共909张,其中训练集为673张,验证集为236张,每张图都进行了详细的标注,标注的目标为烟雾(0)和火焰(1)下面截图为训练集图像示例,数据集已经打包!

我们按照训练集:测试集8:2的比例对全集进行划分,最后产出两个目录

数据集当然不是手动划分的,因为太机械了,我们可以先把标注好的图像放到一起,把标注好的txt(YOLO格式)文件也放到一起,最后使用脚本设置好相关数量,就能实现自动划分啦!

代码语言:python
代码运行次数:0
运行
复制
import os
import shutil
import random

# 输入路径
labels_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\labels'           # 输入YOLO标签文件目录
images_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\JPEGImages'           # 对应图像文件目录
output_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\output_dataset2'   # 输出目录

# 分配数量
train_count = 400
val_count = 100

# 创建输出目录结构
for split in ['train', 'val']:
    os.makedirs(os.path.join(output_dir, split, 'images'), exist_ok=True)
    os.makedirs(os.path.join(output_dir, split, 'labels'), exist_ok=True)

# 获取所有标注文件(假设图像和标签同名)
label_files = [f for f in os.listdir(labels_dir) if f.endswith('.txt')]
random.shuffle(label_files)

# 检查数量是否足够
total_needed = train_count + val_count
if len(label_files) < total_needed:
    raise ValueError(f"标签文件不足,共有 {len(label_files)} 个,要求至少 {total_needed} 个。")

# 分配训练和验证
train_files = label_files[:train_count]
val_files = label_files[train_count:train_count + val_count]

def copy_samples(file_list, split_name):
    for label_file in file_list:
        base_name = os.path.splitext(label_file)[0]
        image_file = None

        # 尝试匹配图像扩展名
        for ext in ['.jpg', '.png', '.jpeg']:
            possible_image = os.path.join(images_dir, base_name + ext)
            if os.path.exists(possible_image):
                image_file = possible_image
                break

        if image_file is None:
            print(f"⚠️ 图像文件 {base_name} 不存在,跳过。")
            continue

        # 拷贝标签和图像
        shutil.copy(os.path.join(labels_dir, label_file), os.path.join(output_dir, split_name, 'labels', label_file))
        shutil.copy(image_file, os.path.join(output_dir, split_name, 'images', os.path.basename(image_file)))

    print(f"✅ {split_name} 集合完成,共复制 {len(file_list)} 张图像。")

# 执行复制
copy_samples(train_files, 'train')
copy_samples(val_files, 'val')

这里多说一句,如果大家拿到的是VOC格式的数据集也不要慌,我们可以使用下面的脚本将VOC数据集转化成YOLO数据集以供模型训练。

代码语言:python
代码运行次数:0
运行
复制
import os
import xml.etree.ElementTree as ET
from PIL import Image

# VOC 类别列表(顺序必须固定)
classes = ['fire']  # 替换成你自己的类别

# 输入路径
voc_anno_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\Annotations'
voc_img_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\JPEGImages'

# 输出路径
yolo_label_dir = r'C:\Users\13978\Downloads\fire_detection\VOC2020\labels'
os.makedirs(yolo_label_dir, exist_ok=True)


def convert_box(size, box):
    """将VOC边界框坐标转为YOLO格式"""
    dw = 1. / size[0]
    dh = 1. / size[1]
    x_center = (box[0] + box[1]) / 2.0
    y_center = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    return (x_center * dw, y_center * dh, w * dw, h * dh)


def convert_annotation(xml_path, img_path, output_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()
    img = Image.open(img_path)
    w, h = img.size

    with open(output_path, 'w') as out_file:
        for obj in root.iter('object'):
            cls = obj.find('name').text
            if cls not in classes:
                continue
            cls_id = classes.index(cls)
            xml_box = obj.find('bndbox')
            b = (
                float(xml_box.find('xmin').text),
                float(xml_box.find('xmax').text),
                float(xml_box.find('ymin').text),
                float(xml_box.find('ymax').text)
            )
            bb = convert_box((w, h), b)
            out_file.write(f"{cls_id} {' '.join(map(str, bb))}\n")


# 遍历VOC标注文件夹
for filename in os.listdir(voc_anno_dir):
    if not filename.endswith('.xml'):
        continue
    xml_path = os.path.join(voc_anno_dir, filename)
    img_filename = filename.replace('.xml', '.jpg')
    img_path = os.path.join(voc_img_dir, img_filename)
    output_path = os.path.join(yolo_label_dir, filename.replace('.xml', '.txt'))

    if not os.path.exists(img_path):
        print(f"Warning: image {img_path} not found, skipping.")
        continue

    convert_annotation(xml_path, img_path, output_path)
    print(f"Converted {filename} to {output_path}")

By:如有需要,本人可提供标注好的VOC(XML)格式火焰数据集2059张,欢迎了解!

2.模型训练

我们使用yolov8n.pt作为基础模型,对标注好的数据集进行深度学习模型训练,训练的话需要准备

data.yaml配置文件,此文件内容可以参考我的:

代码语言:python
代码运行次数:0
运行
复制
path: C:\Users\13978\Downloads\fire_detection\VOC2020\output_dataset2  # 数据集的根目录
train: train                 # 相对于 path 的训练图像路径
val: val                     # 相对于 path 的验证图像路径

names:
  0: smoke
  1: fire

然后执行下面的命令,就可以开始训练模型了

代码语言:bash
复制
yolo task=detect mode=train model=../data/models/yolov8n.pt data=./data.yaml epochs=50 imgsz=640  batch=16 lr0=0.01

下表为上面命令的详细解读

参数

解释

yolo

调用 YOLOv8 的命令行接口工具。

task=detect

detect

任务类型为“目标检测”(可选值还有:segment, classify 等)。

mode=train

train

模式为训练模式(其他模式有 predict, val, export 等)。

model=../data/models/yolov8n.pt

../data/models/yolov8n.pt

指定预训练模型的路径,这里是 YOLOv8n(nano)版本的权重。

data=./data.yaml

./data.yaml

数据集配置文件的路径,定义了训练集、验证集的路径及类别等信息。

epochs=50

50

模型将训练 50 个 epoch。

imgsz=640

640

输入图像尺寸为 640×640 像素。

batch=16

16

每个 batch 包含 16 张图像(batch size)。

lr0=0.01

0.01

初始学习率设置为 0.01。

害,由于博主电脑不支持GPU加速,所以确实花费了一些时间成本,最终训练50轮我们花费了将近3个小时,好在功夫不负有心人,训练任务如期结束。

下面的数图为模型输出目录和文件

代码语言:bash
复制
卷 Data 的文件夹 PATH 列表
卷序列号为 9AD9-E265
D:\PROJECTS\GITEE\YOLO_PROJECTS\YOLOV8-FIRE-SMOKE-DETECTION\TRAIN\RUNS\DETECT\TRAIN3
│  args.yaml
│  confusion_matrix.png
│  confusion_matrix_normalized.png
│  events.out.tfevents.1753497631.Admin.16932.0
│  F1_curve.png
│  labels.jpg
│  labels_correlogram.jpg
│  PR_curve.png
│  P_curve.png
│  results.csv
│  results.png
│  R_curve.png
│  train_batch0.jpg
│  train_batch1.jpg
│  train_batch1720.jpg
│  train_batch1721.jpg
│  train_batch1722.jpg
│  train_batch2.jpg
│  val_batch0_labels.jpg
│  val_batch0_pred.jpg
│  val_batch1_labels.jpg
│  val_batch1_pred.jpg
│  val_batch2_labels.jpg
│  val_batch2_pred.jpg
│
└─weights
        best.pt
        last.pt

简单介绍一下输出文件、目录内容

文件/文件夹名

类型

说明用途

best.pt

模型权重

验证集表现最佳的模型,推荐用于推理部署

last.pt

模型权重

最后一轮训练后保存的模型

args.yaml

配置文件

本次训练的参数配置(batch size、epoch、数据路径等)

results.png

图像

训练过程关键指标(Loss、mAP、Precision、Recall)趋势图

results.csv

表格数据

results.png 对应的原始数据(每个 epoch 的指标)

confusion_matrix.png

图像

混淆矩阵,展示预测 vs 真实类别的关系

confusion_matrix_normalized.png

图像

归一化混淆矩阵,更易观察类别预测比例

F1_curve.png

图像

F1 分数曲线,衡量精度与召回的平衡

P_curve.png

图像

Precision(准确率)随阈值变化曲线

R_curve.png

图像

Recall(召回率)随阈值变化曲线

PR_curve.png

图像

PR 曲线(Precision vs Recall)

labels.jpg

图像

各类别标注的分布频率图

labels_correlogram.jpg

图像

类别之间的共现关系图(哪些类别常一起出现)

train_batch0.jpg

图像

训练集部分图像及其标注框(训练样本可视化)

val_batch*_labels.jpg

图像

验证集图像+真实标签框

val_batch*_pred.jpg

图像

验证集图像+模型预测框(用于与真实值对比)

events.out.tfevents.*

日志文件

TensorBoard 日志文件,支持训练过程可视化

weights/ 文件夹

文件夹

存放训练过程中生成的模型权重文件(包含 best.pt, last.pt

下图为results.png

我们最关心的当然是weights/best.pt模型文件,这是我们火焰与烟雾检测系统的核心。

3.界面窗口

在本章节仅简单介绍一下界面:

我们的核心界面包括:

1.登录注册界面

2.核心功能界面

3.检测告警提示窗口

提示:为了使用不同需求的用户,我们这里为大家设置了方便的设置开关,具体来说是代码里面的system_conf.py我们设置了一个SHOW_LOGIN_FLAG用来控制“是否启用登录系统”,当此标志位为True时,启用登录系统,反之不启用。

1.登录注册界面

我们为用户设计了美观简约的登录注册界面,用户可以选择注册或者登录,拿到代码的小伙伴可以自行调整系统相关文字以及图标和背景图片,系统附带了登录注册使用的数据库,默认用户名和密码为

用户名:admin 密码:admin

2.核心功能界面

只有用户名和密码匹配并且成功登录的用户才能使用我们系统的核心功能,我们的和弦功能界面采用PyQt5开发,包含多个功能模块和显示区域,这些子模块我会在下一个章节详细介绍。

3.检测告警提示窗口

我们设置了多种告警提示方案,下图为“系统弹窗提示”方案,当发现画面中有烟雾或者火情时,系统会自动在桌面右下角弹出警告提示窗,发出声音进行告警提示。

三..核心界面模块介绍

本章节是我们系统的核心章节,我会使用图文的方式介绍每个核心界面的子模块,让大家了解我设计的目的和具体代码实现方案,大家能够了解到我具体的设计初衷以及想法。

1.顶部信息区域

顶部信息区域由三部分组成,分别为:标题区域、日期与系统指标区域、用户信息区域。

首先,系统名称以大号字体居中展示,并采用半透明背景样式,以突出系统标识和整体视觉效果。其下方左侧显示当前时间和日期,实现实时更新。

在底部,系统会每秒刷新一次当前 CPU 和内存使用率,数据精确到小数点后一位,方便用户实时掌握系统运行状态。

右侧为用户信息区域,显示当前登录用户的姓名。旁边的小三角图标为功能入口,点击后可选择 “退出登录” 或 “退出系统” 两项操作:

退出登录:系统将跳转回登录界面,用户需重新输入正确的用户名和密码以重新登录;

退出系统:系统会弹出确认提示,询问用户“是否确定退出”。点击 YES 后,系统将完全关闭。

2.数据输入

该区域为系统的整体数据输入控制面板,支持四种数据输入方式,具体包括:

图片

视频

RTMP/RTSP 视频流

本机摄像头

多样化的输入方式极大地扩展了系统的数据接入能力与应用场景。

在下方区域,用户可以选择博主提供的预训练模型 best.pt 作为目标检测模型,也可加载自行训练的模型文件。系统在模型选择方面提供了较高的灵活性,只要模型符合系统支持的格式与规范,即可顺利接入使用。

3.参数配置

在参数配置子模块中,用户可以灵活调整输入参数,包括重叠度(IOU)和置信度(Confidence),这些参数的变动将直接影响最终的目标检测结果。

我们提供了两种参数调节方式:SpinBox 和 Slider。这两个组件基于 Vue 的双向绑定机制,实现了数据的同步更新——当用户调整其中一个组件时,另一个组件的数值也会自动联动变化。

这种便捷的参数调节方式大大降低了用户配置系统输入参数的操作难度,提升了使用效率和体验。

4.告警设置

在告警设置模块中,用户需手动选择所需的告警方式。系统内置了五种告警方式,具体如下:

语音播报:通过语音播放具体的告警内容;

声音告警:播放预设的告警音效;

系统弹窗提醒:在屏幕右下角弹出告警提示窗口;

短信提醒:调用第三方服务发送短信(需进行相关配置);

邮件提醒:通过第三方服务发送邮件通知(需进行相关配置)。

这些可多选的组件为复选框(QCheckBox),用户可以根据需求选择多个。

5.操作台

用户可在操作台上直接对系统进行操作,包括:

停止任务

导出数据(支持 TXT、CSV、Excel 格式)

保存画面(将当前画面保存为本地文件)

清空画面(清除当前显示内容)

为提升功能辨识度,我们贴心地为不同功能设置了颜色区分的交互按钮,帮助用户更高效地完成操作。

6.关于

此处展示了若干信息入口,包括:

关于作者:点击后将提示用户是否前往作者博客;

技术支持:可直接通过 QQ 与作者联系,进行在线咨询;

关于软件:展示当前软件的基本信息和简介;

关于 Qt:调用系统原生的 Qt 信息弹窗。

通过这些入口,用户可以方便地了解软件背景,并快速获取开发者的技术支持。

7.指标变化

我们为系统设置了高颜值的折线图可视化界面,用于实时展示 CPU 与内存占用情况 的变化趋势。图表采用 ECharts 实现,背景为透明样式,整体风格简洁美观,提升了系统界面的视觉体验。

CPU 利用率 以发光黄色折线展示;

内存使用率 以发光紫色折线展示;

数据每秒更新一次,通过多线程方式刷新,确保图表实时性同时不会阻塞主线程,避免界面卡顿。

当鼠标悬停于折线图上时,将自动显示对应时间点的详细指标值,方便用户精确查看系统资源变化。

8.异常速览

此模块为博主的一个巧思,旨在于快速让用户看到汇总起来的每个目标图像数据,用户可以使用点击图像的方式按需保存每一块截取出来的图像,我们为每个图像进行了编号,这里的编号和检测结果表格里的编号是对应的,如果有多个会自动添加滚动条进行展示。

9.日志输出

顾名思义,该模块用于展示实时检测结果日志,包括检测出的目标数量及相关告警信息。

每条新日志在展示前,都会自动添加精确到时分秒的时间戳,便于用户后续回溯与分析。新生成的日志将按时间顺序追加至日志末尾,并支持自动滚动显示,确保用户始终能够查看到最新的检测信息。

10.检测结果

在此区域,我们以二维表格的形式展示当前图像检测的结果,所有检测到的目标均以列表方式呈现,便于统一查看。

图像数据采用 Base64 编码 方式进行切割与嵌入,用户可以直观地查看每个目标的图像片段,并与当前画面进行快速比对,便于问题定位与分析。

表格基于简约的 HTML<table> 结构构建,设计轻量,显著降低了系统资源开销。

当检测结果较多时,表格右侧会自动显示滚动条,用户可通过拖动滚动条查看更多内容,保证良好的交互体验与数据可读性。

11.核心内容显示区域

本区域用于展示每次目标检测的结果,采用 堆栈组件(QStackedWidget) 实现多页面切换。具体包括:

第一页:用于显示图像检测结果;

第二页:用于显示视频、视频流或摄像头检测结果。

通过这种设计,系统能够灵活支持 静态图像 与 动态视频流 两种类型的内容展示。

该区域是整个软件中占据界面面积最大的部分,同时也是用户最为关注的核心功能区域。

四.问题回答

在这个章节我将对大家关注的问题进行回答

1.项目结构是怎样的,好上手么?

请放心,项目好上手!

我们的项目定义为yolov8-fire-smoke-detection,我们使用包、类和函数对主要功能进行区分,核心代码位于src目录下,项目根目录的main.py为程序入口,每个目录的功能和作用大家见名知意,我们的代码采用标准格式的编码,比如类名就是大驼峰,函数名就是小写加下划线,下图为项目结构

2.项目依赖

我们的项目核心为PyQt5+YOLOv8,下面是我们项目的依赖

代码语言:bash
复制
PyQt5==5.15.11
PyQt5_sip==12.15.0
QtAwesome==1.3.1
torch==2.4.1
torchvision==0.19.1
Pillow==9.3.0
PyQtWebEngine==5.15.5
opencv-python==4.10.0.82
ultralytics==8.3.98
pyttsx3==2.71

大家拿到代码之后直接执行下面的命令,即可一键安装依赖!

代码语言:bash
复制
pip install -r requirements.txt

请你放心,我们的项目一定能运行!

3.我想更改背景图或文字

这个需求还是很常见的

1.改文字

改文字很简单,比如要更改项目名字,就去代码中全局搜索指定的字符串,下图为PyCharm全局搜索的方式png#pic_center)

然后搜索要替换的字符串

然后重新启动项目验证一下,生效

2.改图片

这里以更改背景图片为例,给大家演示如何更改主界面背景图

首先要现有一张背景图,然后放到imgs/目录下替换同名文件

然后执行script/create_qrc.py脚本,重新生成qrc二进制资源文件,最后验证一下

ok没问题!

五.总结

这次和大家详细分享了我使用PyQt5+YOLOV8开发的火焰与烟雾检测系统,本系统实用性强、可拓展性强、能够满足不同用户的差异化需求。

需要源码可以点击下方二维码加我好友带数据集,非无偿请理解!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.前言
    • 1.引言
    • 2.正文
  • 二.核心内容
    • 1.数据集
    • 2.模型训练
    • 3.界面窗口
      • 1.登录注册界面
      • 2.核心功能界面
      • 3.检测告警提示窗口
  • 三..核心界面模块介绍
    • 1.顶部信息区域
    • 2.数据输入
    • 3.参数配置
    • 4.告警设置
    • 5.操作台
    • 6.关于
    • 7.指标变化
    • 8.异常速览
    • 9.日志输出
    • 10.检测结果
    • 11.核心内容显示区域
  • 四.问题回答
    • 1.项目结构是怎样的,好上手么?
    • 2.项目依赖
    • 3.我想更改背景图或文字
      • 1.改文字
      • 2.改图片
  • 五.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档