
简介基于YoloV5的火灾检测系统Python工程面向深度学习、人工智能方向的开发者与学生用于在图像中快速定位火灾区域。工程实现了从数据集配置、模型训练到推理检测的完整流程适合作为课程设计、毕业设计或企业预研的基础项目。压缩包共130个文件约20.67MB核心包括44个YAML配置数据集与模型参数、33个Python脚本训练、检测与工具代码、19张JPG与12张PNG测试样例、1个PT权重文件以及sh启动脚本、pyc编译文件和md说明文档结构清晰便于按需调用。目前已有470人学习下载。内容涵盖模型训练、权重加载、图像/视频检测与结果可视化等环节。资源内代码经测试运行成功可直接复现检测效果也可根据自身数据替换配置与样本进行迁移学习。对于需要快速搭建火灾检测原型或理解YoloV5工程组织方式的读者具有不错的借鉴与实战价值。 做火灾检测这个项目最容易被忽视的其实是数据而不是模型。很多人拿到一套YoloV5的火灾检测代码第一件事就是急着训练结果环境配了两天、数据集随便下一堆网图就开始跑最后精度稀烂还以为是模型的问题。这套基于YoloV5的火灾检测系统本质上是把深度学习目标检测技术落地到消防预警场景从图像或视频中直接框出火焰区域。它解决的痛点是传统传感器只能检测“已经烧起来”的烟雾或温度而视觉方案能在火苗初起时就看到目标反应更快覆盖范围也更广。适合正在做毕设、准备竞赛或者想熟悉“YoloV5训练自己的数据集”全流程的读者。这篇文章我会按照实际项目从零到一的推进顺序来写方案选型、环境配置、数据集标注、模型训练、推理部署、踩坑排查。每一部分都是我在真实项目里验证过的做法不是纸面上照搬文档。1. 项目目标与方案选型先搞清楚到底要做什么1.1 火灾检测为什么需要深度学习这类视觉模型火灾检测如果只走传统图像处理路线方案基本集中在颜色阈值和运动检测。比如把RGB图像转到HSV空间通过设定火焰颜色的H、S、V范围把疑似区域抠出来再用面积、圆形度、闪动频率这些规则去判断是不是火。这种方法在实验室环境里效果尚可一旦到了真实场景就很脆弱隧道里的橙色灯光、傍晚的霞光、穿着橙色工服的人、反光的路面都会被当成疑似火焰误报率非常高。深度学习目标检测的思路完全不同。它不依赖人工设定颜色规则而是从大量标注好的火焰图像中自动学习“火焰长什么样”。特征有纹理、边缘、颜色、形状、上下文关系等多层语义信息所以对光照变化、火焰形态差异的鲁棒性比传统方法高出一个量级。YoloV5属于单阶段目标检测算法一次前向传播就能同时输出目标类别和边界框坐标速度比双阶段的Faster R-CNN快很多在实时监控场景里非常合适。1.2 YoloV5网络结构快速拆解YoloV5的整体结构可以拆成三块Backbone负责从输入图像中提取特征Neck负责把不同尺度的特征融合起来Head负责最终输出检测结果。Backbone使用的是CSPDarknet53结构它的核心思想是把特征图拆成两部分一部分直接通过残差连接传递另一部分经过卷积块提取后合并。这样做的好处是在加深网络的同时控制计算量梯度回传也更顺畅。输入图像默认缩放成640×640经过一系列下采样操作后会在多个尺度上得到特征图。Neck部分用的是PANet结构它同时包含自顶向下的路径和自底向上的路径。自顶向下传递的是语义信息自底向上传递的是位置信息两者融合后小目标和大目标都能获得足够的上下文。这就是为什么YoloV5能同时检测远处的小火苗和近处的大火源。Head部分在三个不同尺度的特征图上做预测。比如输入640×640时输出特征图分别是80×80、40×40、20×20对应感受野从小到大的三种先验框尺寸分别负责检测小、中、大目标。每个特征图上的每个网格会预测边界框坐标、置信度和类别概率。1.3 为什么是YoloV5不是YoloV8也不是YoloV6我经常被问到这个问题。YoloV8的精度和训练稳定性确实比V5好一些YoloV6在工业部署方面也做得很极致但在这个火灾检测项目里我仍然会选YoloV5原因很务实。首先是生态太成熟。YoloV5从2020年发布到现在教程数量、常见问题的解决方案数量是其他版本没法比的。很多环境配置的坑、训练参数的含义、部署的细节都有大量现成经验可以参考。其次是硬件要求相对友好YoloV5s模型只有大约14MB单张GPU就能训练甚至CPU也能凑合跑推理。最后是代码清晰度对于想学习深度学习目标检测的人来说YoloV5的代码结构比V8更容易读懂修改起来也更直接。毕设、课设这种场景稳定跑通比盲目追新更重要。2. 环境搭建与工程初始化别让配置卡住三天2.1 Python、CUDA、PyTorch版本之间怎么搭配环境版本不匹配是这个项目里最常见的翻车原因。我实测过一套稳定组合直接照着装基本不会出问题。组件推荐版本说明Python3.8.10兼容性好很多依赖库对3.10以上支持仍有坑CUDA11.3和PyTorch 1.10配套最稳cuDNN8.2配合CUDA 11.3使用PyTorch1.10.0较老但稳定YoloV5官方支持良好torchvision0.11.0必须和PyTorch版本一一对应给只有一个显卡、显存不大比如6GB的同学一个建议不要追求最新版本。新版PyTorch对显卡驱动要求更高装不上或者ImportError的概率会明显增加。安装时如果直接pip安装GPU版PyTorch经常因为网络问题失败或者超时。我习惯用下面的方式先把torch、torchvision的whl包下载到本地再安装稳定得多。# 创建conda环境 conda create -n fire_yolov5 python3.8 conda activate fire_yolov5 # 安装GPU版PyTorch注意cuda版本参数 pip install torch1.10.0cu113 torchvision0.11.0cu113 -f https://download.pytorch.org/whl/torch_stable.html如果电脑没有独立显卡就把命令里的cu113去掉安装CPU版本。训练会慢但对入门验证、小数据集跑通流程来说完全可行。2.2 把YoloV5工程跑起来最快的方式环境装好后接下来就是把仓库代码拉下来跑通一次最小流程。我用的是YoloV5官方仓库的代码基础项目压缩包里其实也是类似的工程结构。git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txtrequirements.txt里包含opencv-python、matplotlib、numpy、pandas、tensorboard等常用视觉和深度学习库。如果你的网络环境下载快几分钟就能装完如果慢可以先修改pip源到国内镜像再install。跑通“hello world”的方式是直接用官方预训练权重做一次检测验证环境和依赖都正常python detect.py --weights yolov5s.pt --source data/images/bus.jpg第一次运行会自动下载yolov5s.pt权重。如果下载卡住可以手动去官方仓库的Release页面下载之后放进weights目录。运行成功后在runs/detect/exp目录里能看到画了检测框的bus.jpg到这一步工程环境就算正式通了。2.3 工程目录结构梳理很多新手拿到代码包第一反应是直接找model.py去改网络结构这是一个常见的误区。YoloV5工程里的核心目录结构是这样的data存放数据集配置yaml文件和标签说明。models存放模型定义文件包括yolov5s.yaml、yolov5m.yaml等不同尺寸的配置。utils各种工具函数包括数据增强、损失计算、日志记录等。weights权重文件目录放预训练权重和训练好的best.pt。runs训练和推理的输出目录包含每次运行的日志、曲线图、验证结果。train.py训练入口。detect.py推理入口。val.py验证入口。实际改动最多的文件其实是data目录下的yaml配置和模型存档而不是网络结构代码。理解这个结构后后面调起来会顺畅很多。3. 数据集准备精度上限在标注里决定3.1 开源数据集与自建数据的取舍火灾检测数据集在开源社区有不少选择比如ImageNet相关子集、专门的Fire Detection数据集、公路隧道火灾检测数据集等。直接用这些数据集有一个好处已经标注好可以立刻开始训练。但缺点也很明显公开数据集和实际应用场景往往存在差异比如公开数据集以室外火灾为主而你要部署到隧道里光照、背景差异大会导致训练好的模型在目标场景掉点。我的建议是混合策略公开数据集作为预训练来源用自己拍摄或采集的场景视频抽帧后补充标注作为微调数据。这样做效率最高。自己采集数据并不复杂用手机拍摄监控画面或者从监控录像中截取视频再用Python脚本按固定帧数抽帧即可。import cv2 import os video_path fire_video.mp4 save_dir custom_frames os.makedirs(save_dir, exist_okTrue) cap cv2.VideoCapture(video_path) fps int(cap.get(cv2.CAP_PROP_FPS)) frame_interval max(fps // 2, 1) # 每秒抽两帧 frame_id 0 saved_id 0 while True: ret, frame cap.read() if not ret: break if frame_id % frame_interval 0: save_path os.path.join(save_dir, fframe_{saved_id:06d}.jpg) cv2.imwrite(save_path, frame) saved_id 1 frame_id 1 cap.release()注意覆盖的多样性白天、黑夜、强光、阴影、近距离、远距离、不同燃烧物。数据集的多样性比绝对数量更重要五百张覆盖充分的图片比五千张同场景图片的价值高得多。3.2 标注工具与标注规范标注工具我习惯用LabelImg它小巧、免安装版直接解压就能用并且原生支持YOLO格式导出。YOLO格式的核心是每个图片对应一个同名txt文件文件中每行标注一个目标格式为class_id x_center y_center width height注意框的坐标全部是归一化到0到1的相对坐标用目标框的中心点和宽高除以图片宽高得到。开始标注前先预定义一个类别清单。这个项目里我建议先只做一个类别fire后期再加smoke。一次引入多个类别会明显增加训练难度容易造成类别混淆火焰和烟雾特征重叠度高新手很容易标乱。标注时有几个实操要点不要把边框卡得太紧。火焰边缘在不停跳动如果框紧贴火焰轮廓前面几帧框的标注框就会和后面几帧的标注框差异很大训练出来的模型在推理时框体不稳定。留5%到10%的余量反而更稳。同一个火焰如果有多个不连续区域可以拆成多个框也可以合成一个大的外接框关键是在整个数据集里保持一致。只框火焰本身不要框烟雾、红光区域或者反射出来的橙色区域。这类样本对模型的干扰最大宁可跳过也不要硬标。标注完成后用Python脚本检查一下是否有空标注文件、类别编号是否超出范围这能省掉不少训练时的排查时间。3.3 划分数据集并生成yaml配置数据准备好了还需要按照YoloV5要求的目录结构整理。我常用的划分比例是训练集8、验证集1、测试集1。fire_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/划分完数据集后在项目data目录下创建fire.yaml这是训练时告诉YoloV5数据长什么样的关键文件train: /absolute/path/to/fire_dataset/images/train val: /absolute/path/to/fire_dataset/images/val test: /absolute/path/to/fire_dataset/images/test nc: 1 names: [fire]路径如果使用相对路径必须相对于运行train.py时的当前目录。为了防止各种路径问题我强烈建议所有路径都用绝对路径同时确保路径中没有任何中文。4. 训练、调参与推理把模型真正用起来4.1 训练核心参数怎么选训练命令大概是这个形式python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data data/fire.yaml \ --weights yolov5s.pt \ --name fire_experiment每个参数都直接影响训练效果值得花点时间理解。--img是输入图像的尺寸默认640。尺寸越大模型能看到更多细节对小火焰目标更友好但显存占用同步增大。如果显存只有4GB把img降到416运行速度会快很多精度损失在火焰这种纹理目标上并不明显。--batch是每次迭代送入模型的图片数量。显存不足时的处理顺序是先减batch比如从16减到8还不足再减到4。尽量不要动img因为降低img会导致小目标检测能力下降而火焰初期恰恰就是小目标问题。--epochs是训练轮数。公开数据集预训练权重已经提供了良好的初始化火灾数据集训练100轮足够收敛。如果数据量很少300轮也不划算训练100轮之后观察损失曲线没有再下降趋势就提前停。训练过程中YoloV5还会有一组超参数文件hyp.scratch-low.yaml里面包含学习率lr0、动量momentum、权重衰减weight_decay等。新手不要动这些值等主线流程跑通了再去琢磨。4.2 训练过程看什么指标训练开始后每轮结束都会在终端输出一组指标同时在runs/train/fire_experiment目录下生成曲线图。需要重点关注三个损失值box_loss边界框回归损失、obj_loss置信度损失、cls_loss分类损失。它们都应该随着训练轮数增加而下降如果到了一定轮数后曲线变得平缓甚至略微回升说明模型开始过拟合了。验证集上的mAP是更直观的指标。mAP0.5表示IoU阈值0.5时的平均精度火灾检测这样的场景mAP0.5能到0.85以上就已经很能用了。mAP0.5:0.95会严格一些一般会比mAP0.5低不用太纠结。训练结束后runs/train/fire_experiment/weights目录下会有last.pt和best.pt。best.pt是验证集上表现最好的权重推理时优先使用它而不是last.pt。这个细节常被忽略但用错权重直接导致检测效果打折。4.3 推理部署图片、视频、实时摄像头模型训练好后推理命令很简洁# 单张图片 python detect.py --weights runs/train/fire_experiment/weights/best.pt --source test.jpg # 视频文件 python detect.py --weights runs/train/fire_experiment/weights/best.pt --source test.mp4 # 实时摄像头source为0表示默认摄像头 python detect.py --weights runs/train/fire_experiment/weights/best.pt --source 0推理结果会保存在runs/detect/目录下。打开输出的图片如果火焰目标被框住并有置信度数字恭喜你训练好的模型已经能正常工作了。如果直接调用Python代码来做实时检测YoloV5的detect.py里已经封装好了模型加载和预测逻辑核心只有几行import torch from models.experimental import attempt_load from utils.general import non_max_suppression from utils.augmentations import letterbox model attempt_load(best.pt, map_locationcpu) img letterbox(frame, 640, stride32)[0] img img[:, :, ::-1].transpose(2, 0, 1) img torch.from_numpy(img).float() / 255.0 img img.unsqueeze(0) pred model(img)[0] pred non_max_suppression(pred, conf_thres0.25, iou_thres0.45)这段代码可以作为一个最小演示。实际项目中建议把模型封装成一个FireDetector类初始化时加载一次权重之后每次推理只调用类方法避免频繁加载权重带来的开销。5. 高频踩坑记录与经验速查表5.1 常见报错与排查清单我把项目中反馈最多的问题整理成了一张速查表基本覆盖绝大多数卡点。问题现象主要原因解决方法CUDA out of memorybatch或img超出显存先减batch再减img分辨率KeyError: fire标签中的类别名与yaml中names不匹配检查txt标注和fire.yaml的names一致训练后检测框完全找不到目标best.pt和last.pt用混了或置信度阈值过高确认使用best.pt调低conf_thresLoss一直在高位不下降学习率不合适、数据集太单一恢复默认超参数检查标签是否准确加载权重时报错Key mismatchpre权重类别数与自定义数据不一致用yolov5s.pt做预训练不要用COCO微调过的其他权重中文路径导致无法读取图片Windows编码问题所有路径改为英文路径5.2 火焰检测场景的独家技巧项目做了几轮之后我自己总结了一套对火焰检测特别有用的经验。第一正负样本合理搭配。如果训练数据全是火焰图片模型会变得“过度自信”一片红色区域都可能被当成火焰。建议在训练集中加入10%到20%的不含火焰的干扰图片标注文件为空txt即可。这些负样本能显著降低误报率让模型学会说“不”。第二针对火焰边缘不稳定的特点推理时可以把置信度阈值conf_thres适当降低到0.2左右然后用NMS的IoU阈值iou_thres控制重叠框。因为火焰的形态时刻在变一个目标的多个检测框往往无法形成高IoU阈值太严格会导致同一个火焰输出大量重叠框看起来就像“很多个火”。第三摄像头实时监控场景下建议把检测频率限制在每秒2到5帧而不是每帧都做推理。火焰在视频里是连续出现的每秒2帧的检测频率对预警来说已经足够却能把CPU占用降一个量级。第四发一个小技巧训练时如果发现模型对小火苗的召回率低可以试试数据增强里mosaic和mixup的开关。YoloV5默认开启mosaic这对大目标效果好但会让小目标变形严重。把mosaic关闭小目标的召回率往往会有明显提升。做这套系统的过程最大的体会是深度学习项目里模型训练占整个工作量的比例其实没有想象中那么高数据整理和环境配置反而占掉大半时间。如果你已经在调试这套代码卡在一个奇怪的环境问题上面很久我的建议是先冷静下来重装一个干净的conda环境照着版本表完整来一遍多半能解决。等模型能正常出框了再回来调数据、调效果。这样一步步走下来你会发现YoloV5火灾检测做起来并没有想象中那么难。本文还有配套的精品资源点击获取