简介:这是一份基于YoloV5的火灾识别与检测系统完整项目,面向计算机视觉、深度学习方向的在校学生、算法工程师及毕设/课设开发者,覆盖从数据集配置、模型训练到推理部署的完整流程,可快速上手目标检测与火灾区域定位。资源共130个文件,包含44个yaml配置(模型结构与环境参数)、33个Python脚本(训练、验证及推理入口)、19张jpg/12张png测试图片、pt模型权重文件、sh运行脚本和md说明文档,压缩包约20.68MB,目录结构清晰,便于按模块阅读和二次开发。目前已有99人学习下载。项目代码已经过运行验证,附有图片预览和文档说明;读者可获得可直接调用的检测模型、含有标签的数据集配置、完整的训练推理脚本及常见问题处理思路,还可基于此扩展烟雾检测、多场景火情预警等功能,尤其适合作为课程设计、毕业设计或火灾检测应用系统的基础版本。
1. YoloV5 火灾识别与检测系统:一套能闭环的深度学习目标检测项目
监控画面里火光出现的前几秒,往往是决定损失大小的关键窗口。与其让值班员同时盯几十路画面,不如让 YOLOv5 在视频流上直接做火灾识别与检测:框出火焰区域、输出置信度、触发声光或消息联动。这是一套典型的深度学习目标检测落地项目,标题里的“python 项目源码 + 文档说明”意味着拿到手的不只是一段 Demo,而是从数据标注、模型训练到推理部署都串得起来的完整工程。也正因为如此,“基于 YoloV5 的火灾识别与检测系统”成了算法入门、毕业设计、消防物联网预研里出现频率最高的组合之一。本文按一线工程习惯把这个系统拆成四件事:YOLOv5 网络结构为什么适合做这件事、环境与数据集怎么备、训练和超参数怎么调、实时视频流推理与误报怎么压。
2. YOLOv5 网络结构拆解:为什么火灾检测选它而不是 Faster R-CNN
2.1 YOLOv5 网络结构的三个关键部件
YOLOv5 的网络结构由 Backbone、Neck、Head 三部分组成。Backbone 用的是 CSPDarknet53,核心是 C3 模块,借鉴了 CSPNet 的跨阶段局部连接思路,把特征图在通道维度上分成两支,一支直接往下传,一支经过若干 Bottleneck 再合并。这样做既减少了重复梯度计算,也让模型在同样参数量下特征表达能力更强。对火灾识别来说,这个 Backbone 的性价比很关键,因为消防摄像头往往不止一路,算力要摊到多路画面上。
Neck 部分采用 PANet 结构,在 FPN 自顶向下传递语义特征的基础上,又加了一条自底向上的路径,把定位信息再送回去。火焰检测里“远处的小火点”和“近处的大火团”在尺度上差异很大,PANet 的多尺度融合就是用来处理这种差异的。Head 则是 YOLOv5 经典的耦合检测头,在三个尺度特征图上做密集预测,输出边界框、类别置信度和目标置信度,而不是像 YOLOv8 那样把分类和回归头拆开。
| 输出特征图 | 网格尺寸(以 640 输入为例) | 更擅长检出 |
|---|---|---|
| P3 | 80 × 80 | 远处小火点、早期烟头级火苗 |
| P4 | 40 × 40 | 中等面积火焰、烟雾团 |
| P5 | 20 × 20 | 大面积明火、整体火场 |
这个表格在实际项目里的直接用途是判断误报来自哪一层。如果大量误报框都是小框,问题很可能在 P3 层的置信度阈值太低;如果火势已经很大却只框住局部,就要检查 P5 层特征是否被下采样过头。
2.2 YOLOv5 与两阶段检测器、YOLOv8、SSD 的取舍
| 模型 | 推理速度 | 部署生态 | 火灾场景注意点 |
|---|---|---|---|
| Faster R-CNN | 慢,单路还行 | 组件多,转设备端麻烦 | 精度上限高,但多路并发不现实 |
| SSD | 快 | 旧生态,算子支持越来越弱 | 小目标召回弱,远处火点容易丢 |
| YOLOv5 | 快,s 级可跑边缘设备 | 导出 ONNX/TensorRT 链路最成熟 | 需要额外做误报抑制 |
| YOLOv8 | 比 v5 略快 | 新生态,但改源码成本高 | 自带功能多,项目定制灵活性反而低 |
实际选型时,很多人纠结 YOLOv8 和 YOLOv5。我的看法是:做产品原型,YOLOv5 的社区资料最厚,任何一句报错几乎都能搜到现成解决方案;做研究性课题,YOLOv8 的 Anchor-Free 设计更贴近前沿。但对“火灾识别与检测系统”这个项目,YOLOv5 的成熟度是实打实的优势,尤其是老旧 IPC 芯片、Jetson 这类设备上,v5 的算子兼容性明显更好。
2.3 火灾识别的真正难点:烟雾、火焰与误报的博弈
火灾识别的难点不在“框出明火”。火焰颜色鲜明、轮廓较硬,任何检测器都能学得会;难的是烟雾的半透明扩散形态,以及大量容易混淆的干扰物。红色车灯、夕阳反光、路灯闪烁、电焊火花,在视频里都可能呈现“红黄色亮斑”的视觉特征。YOLOv5 这类深度学习模型学的是语义特征,比传统 OpenCV 的 HSV 阈值法鲁棒得多,但它同样分不清“像火的东西”和“真的火”。
这就是为什么只跑通源码不够。一个能交付的 YOLOv5 火灾识别系统,必须把注意力放在数据怎么挑、负样本怎么凑、连续帧怎么确认上。后面几章会针对这些点给出可执行的方案。
提示:火焰检测项目的核心指标不是 mAP,而是召回率。漏报一次火灾,前面所有精度都失去意义。
3. Python 环境配置与火灾数据集构建:YOLOv5 的最小可运行闭环
3.1 YOLOv5 环境配置:从 Python 解释器到依赖安装
拿到项目源码包后,第一件事不是改模型,而是先把环境跑通。YOLOv5 对 Python 版本不苛刻,3.8 到 3.10 都是常见组合。建议用虚拟环境隔离,不要一股脑装进系统 Python:
git clone https://github.com/ultralytics/yolov5 cd yolov5 python -m venv .venv # Windows 下用 .venv\Scripts\activate source .venv/bin/activate pip install -r requirements.txt这段命令做了四件事:拉取官方仓库、进入项目目录、创建隔离的虚拟环境、安装依赖。要求文件里的 torch 和 torchvision 是联动版本,pip 会自动匹配。显卡用户要特别注意,requirements.txt 默认安装的是对应 CUDA 版本的 PyTorch,装完用python -c "import torch; print(torch.cuda.is_available())"验证 GPU 是否可用;如果输出 False,多半是显卡驱动版本太旧或没装 CUDA 工具链。纯 CPU 机器也能训练,速度慢但小数据集跑通流程没问题。
用 PyCharm 打开项目时,把解释器指向.venv/bin/python;用 VSCode 则在命令面板里选择 Python 解释器路径。这一步看似基础,却是环境配置中最容易卡住的地方,很多“import torch 报错”其实都是解释器没切到虚拟环境。
3.2 火灾数据集目录结构与 YOLO 标注格式
数据集的组织方式 YOLOv5 约定得很死,目录不对直接报错:
fire_dataset/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 与图片同名的 txt │ └── val/ └── classes.txt # 类别名列表每张图片对应一个同名 txt 文件,里面的每一行代表一个目标框,格式是五个数字:类别id x_center y_center width height,后四个值全部归一化到 0~1。比如0 0.5123 0.4387 0.2201 0.1805,表示类别 0 的火焰框,中心点位于图片横向 51.23%、纵向 43.87% 的位置。这个格式一定要注意,很多新手把像素坐标直接写进去,训练出来的损失值会异常大,因为 YOLOv5 默认读取归一化坐标。
标注工具常见的用 LabelImg 或 LabelStudio。火焰和烟雾建议分两个类别,因为初期火灾往往是先冒烟后起火,业务上需要区分报警级别。如果数据量不够,可以用一个取巧的流程:先把仓库自带的yolov5s.pt跑一遍detect.py --save-txt,让它先标出候选框,再用标注工具人工修正错框和漏框,速度快一半以上。
3.3 数据集划分与校验脚本
训练前要先把图片和标签按比例拆成训练集和验证集。我一般用 80/20 划分,并顺手做一次完整性检查:
import random import shutil from pathlib import Path root = Path("fire_dataset") images = sorted((root / "images_all").glob("*.jpg")) random.seed(42) random.shuffle(images) split_idx = int(len(images) * 0.8) for idx, img in enumerate(images): label = root / "labels_all" / (img.stem + ".txt") # 有图无标签直接跳过,避免训练时报错 if not label.exists(): continue subset = "train" if idx < split_idx else "val" shutil.copy(img, root / "images" / subset / img.name) shutil.copy(label, root / "labels" / subset / label.name)这段脚本的逻辑是:固定随机种子保证每次划分一致,按 8:2 切分,复制到 train/val 子目录。if not label.exists()这行很关键,YOLOv5 在训练时遇到有图无标签的样本会直接跳过,但如果你没在意,会误以为模型训练正常而实际训练样本少了一大截。划分完成后,检查每个 train 目录下图片数和标签数是否一致,再随便打开几个 txt 确认坐标都在 0~1 区间。
提示:数据集里至少留 10% 的负样本(没有人任何火灾目标的普通场景图)。YOLOv5 的置信度抑制依赖这些负样本教会模型“不确定就不输出”,少了它们,误报率会明显上升。
4. 训练自己的火灾数据集:YOLOv5 训练命令、超参数与日志解读
4.1 fire.yaml 配置文件必须拆开看
YOLOv5 训练前需要一份数据配置文件,很多项目源码里的文档说明会把这一节放在最前面,因为它直接决定模型学什么:
# fire.yaml path: fire_dataset train: images/train val: images/val nc: 1 names: 0: fire字段含义分别是:数据集根目录、训练集相对路径、验证集相对路径、类别总数、类别名列表。这里最容易踩的坑是把path写成相对train.py的位置。如果在yolov5/目录下执行训练,上面的配置没问题;但如果把数据集放在yolov5/外面的../fire_dataset,path 也要相应改成../fire_dataset。如果项目要同时识别火焰和烟雾,就把nc改成 2,names 里增加1: smoke,注意顺序必须和标注时的类别 id 一致。
4.2 训练自己的火灾数据集:train.py 参数表与超参数调整
最小可运行训练命令如下:
python train.py \ --data fire.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --hyp hyp.scratch-low.yaml \ --cache ram \ --device 0| 参数 | 作用 | 火灾场景建议值 |
|---|---|---|
| --weights | 预训练权重,yolov5s.pt 是速度/精度均衡档 | yolov5s.pt 起步,边缘设备用 yolov5n.pt |
| --img | 训练分辨率 | 640 通用;摄像头距离远可试 1280,显存压力翻倍 |
| --batch | 批大小,显存不足报 CUDA OOM | 先按显存上限定,再往下调 4~8 |
| --epochs | 训练轮数 | 小数据集 100 起步,看到 mAP 不再涨就停 |
| --hyp | 超参数文件 | 低配置机器用 hyp.scratch-low.yaml |
| --cache | 把图片预载入内存/显存 | ram 能显著加快小数据集训练 |
| --device | 指定 GPU/CPU | 0 是第一块 GPU,CPU 写 cpu |
超参数文件是真正体现经验的地方。hyp.scratch-low.yaml里几个关键项:lr0初始学习率默认 0.01,火灾这种单类别小数据集可以调到 0.005,收敛更稳;fliplr水平翻转默认 0.5,火焰检测可以保留;但flipud垂直翻转默认 0,千万别开,倒过来的火焰在物理语义上是错误样本,会干扰模型对火势上窜方向的理解。mosaic默认 1.0,前 90% 训练轮次生效,最后 10 轮自动关闭,这个设计是为了让模型在真实分布上做最后的精细调整。如果数据集只有几百张,建议把mixup从 0 调到 0.2,能变相扩充样本,但训练时间会长一些。
4.3 训练日志与 results.png 教你看什么
训练结束后看两个位置。一是终端里每轮打印的metrics/precision、metrics/recall、mAP_0.5、mAP_0.5:0.95;二是runs/train/exp/目录下的results.png,里面有十张子图,按行排。
第一行是 box、obj、cls 三类损失,训练集跟验证集的曲线间距要小;验证集损失连续多轮不降反升,就是过拟合信号。第二行是 precision、recall 和 mAP。对火灾项目,recall 比 precision 重要,宁可在某几帧多报,也不要漏判。如果 recall 明显低于 precision,把 detect 阶段的--conf阈值下调。模型文件会同时生成best.pt和last.pt,best 由验证集 mAP 决定,部署时只用 best。还可以加上--patience 30,连续 30 轮验证集指标不提升就自动早停,省时间。
提示:训练日志里
obj_loss居高不下时,先回查数据集,看看是不是标签坐标错乱或负样本太多,而不是急着堆超参数。
5. 把 YOLOv5 火灾识别接到视频流:实时推理、导出与误报抑制
5.1 一条命令跑通摄像头与 RTSP 视频流
训练完的模型拿去做实时检测,入口是detect.py:
python detect.py \ --weights runs/train/exp/weights/best.pt \ --source 0 \ --conf 0.35 \ --max-det 3--source 0表示本机 USB 摄像头,换成 RTSP 地址就能接入网络摄像头;--conf是置信度阈值,火灾项目建议先设 0.3,把召回拉起来再慢慢往上提到 0.4;--max-det 3限制每帧最多输出三个目标,避免画面里多个红点同时触发大量报警框。项目文档说明里如果提供了参数速查表,这一页通常是排错时翻得最多的。
5.2 导出 ONNX 加速推理
Python 推理速度不够时,用export.py把模型转成 ONNX 再交给 onnxruntime 或 TensorRT 执行,能在不换硬件的情况下提升不少帧率:
python export.py \ --weights runs/train/exp/weights/best.pt \ --include onnx \ --simplify导出后得到best.onnx,边缘设备上再转 TensorRT engine,int8 量化后体积能压到几十 MB 级别,适合部署在 Jetson 系列设备上。这里有个常见误区:ONNX 只是换了个推理引擎,模型本身的检测能力一点没变,不要指望导出后误报自动消失。
5.3 用连续帧确认机制压低误报
单帧检测误报几乎不可避免,但真实火灾在时间轴上具有持续性,可以利用这一特性做帧间确认:
FRAME_THRESHOLD = 3 # 连续命中 3 帧才报警 hit_count = 0 for frame in video_stream: results = model(frame) has_fire = len(results.xyxy[0]) > 0 if has_fire: hit_count += 1 else: hit_count = 0 if hit_count >= FRAME_THRESHOLD: trigger_alarm() # 联动声光或推送消息 hit_count = 0 # 触发一次后重置,防重复报警逻辑很简单:每帧送入模型推理,有检测结果就累加计数器,没有就清零,连续三帧命中才真正报警。这个FRAME_THRESHOLD是系统里最值得调的一个参数,室内固定摄像头调到 3 就够,室外阳光晃动的场景调到 5~8,误报会明显下降,代价是火灾发现时间延后零点几秒,完全可接受。这套阈值压制的成本比任何模型调优都低,也是文档说明里最容易被忽略的交付内容。
本文还有配套的精品资源,点击获取