
简介基于YOLOv5的火焰识别检测项目面向电力、工地、社区等工业安防场景的开发者提供从数据集到模型训练/测试的完整可运行方案。压缩包约275.8MB共2000个文件其中包含约3700张JPG火焰图片及对应txt标签、xml标注文件并附有yaml配置、Python训练脚本、Dockerfile等环境部署与二次开发所需内容数据已预处理为txt格式无需额外转换即可直接训练。项目内还提供7400余个txt标签文件覆盖多种标注格式方便对比与微调。描述显示模型在本机准确率约97%具备工业化落地潜力。目前已有7281人学习下载适合具备一定Python与深度学习基础、希望快速上手目标检测的工程技术人员。资源附带README与常用工具脚本遇到环境或训练问题可联系博主获得无偿协助。1. 火焰识别检测4000 张数据集与 YOLOv5 选型的判断火焰识别检测在电力行业落地卡点往往不是模型精度而是数据底子撑不住现场。变电站外的设备反光、黄昏夕阳、焊接弧光都可能把模型带偏。这套基于 YOLOv5 火焰识别检测的资源自带 4000 张火焰数据集覆盖白天、夜晚、室内、户外和不同距离的火焰形态能从零训出一个单类火焰检测模型直接用于电力监控的火灾预警验证。解决的问题很直接不用自己攒图数据、标注、训练脚本都打好包按流程跑就能拿到权重。适合做电力巡检算法验证的工程师也适合拿真实数据集练手的新手。下面从拆包检查数据开始讲。2. 先把数据集盘清目录结构、标注格式与划分脚本拆包第一步要做的不是急着训练而是把数据集“体检”一遍。目标检测项目里数据问题通常会在训练两三个小时后以莫名其妙的 mAP 抖动形式暴露出来到那时再回头查就费劲了。我习惯按目录结构、标注格式、划分比例三件事依次检查每一步都有现成脚本可抄。2.1 4000 张图的构成与场景覆盖先统计图片数量、分辨率和标注框数量。4000 张对单类任务来说不算大但前提是场景分布合理。常见的做法是写个小脚本把分辨率、标注框数量、文件大小拉出来看分布我一般用下面这段import os from collections import Counter from PIL import Image IMG_DIR images res_counter, box_counter Counter(), Counter() for f in os.listdir(IMG_DIR): with Image.open(os.path.join(IMG_DIR, f)) as im: res_counter[im.size] 1 txt os.path.join(labels, os.path.splitext(f)[0] .txt) n len(open(txt).readlines()) if os.path.exists(txt) else 0 box_counter[n] 1 print(分辨率分布:, res_counter.most_common(5)) print(每图目标数分布:, box_counter.most_common(5))逻辑说明这段代码同时读图片元信息和同名标注文件把分辨率和每张图的目标数量聚合成计数。参数说明只取 top5 就够判断问题重点看是否有分辨率差异巨大的混用如果每图目标数集中在 1说明数据多为“单火苗”特写这类数据训出来的模型换到大视野监控画面会明显“近视”。电力场景要额外留意一个问题数据集里有没有变电站、配电房、电缆沟这类与现场接近的画面而不是全是森林、街区火灾照。我一般会从 4000 张里抽出 10% 快速扫一遍场景标签把电力相关场景占比记下来低于三成就得考虑补现场帧不然训练完的模型需要二次迁移。另一个检查项是夜间占比——打包数据通常白天图偏多如果夜间图不足 20%就要在心里先记一笔训练阶段得靠增强或补图把这部分补齐。2.2 标注格式核对与 VOC 转 YOLO火焰检测数据集的标注格式最常见的是 YOLO 的 txt 和 VOC 的 XML 两种。YOLO 格式每一行是类别 x_center y_center width height四个坐标值全部做过归一化范围 01。拿到包装好的数据集时我先用一个小脚本过一遍所有标注防止坐标越界和空标注混进去import os LABEL_DIR labels bad_files [] for f in os.listdir(LABEL_DIR): if not f.endswith(.txt): continue lines open(os.path.join(LABEL_DIR, f)).read().strip().splitlines() if not lines: bad_files.append(f) # 空标注 for line in lines: cls, cx, cy, w, h map(float, line.split()) if not (0 cx 1 and 0 cy 1): bad_files.append(f) # 中心点越界 if w 0 or h 0: bad_files.append(f) # 宽高非法 print(异常文件:, bad_files)逻辑说明遍历所有 txt把空文件、归一化坐标越界、宽高非法的文件收集起来。越界坐标通常来自转换脚本没有按原图尺寸归一化训练时这些框会被直接过滤掉等于目标凭空少了一批。参数说明单类火焰任务里 cls 固定为 0如果遇到 cls 值大于 0说明包里混入了其他类别需要先确认标注规范再继续。如果拿到的是 VOC XML就得先转成 YOLO 格式再进训练。转换脚本我常用下面这个函数import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_txt, w, h): root ET.parse(xml_path).getroot() with open(out_txt, w) as f: for obj in root.findall(object): cls_id 0 # 单类任务只有 fire 一个类别 box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h f.write(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}\n)参数说明w、h 是原图宽高必须和 XML 对应的图片一致中心点用 (xminxmax)/2 求宽度直接相减再归一化注意 ymax 朝下所以不需要额外变换。手动转换最容易翻车的点是 XML 里 size 标签和真实图片尺寸不一致我一般转换前先把图片实际尺寸读出来传进去而不是信 XML 里的值。转换完重新跑一遍上面的检查脚本确认没有全零坐标或越界再做划分。提示VOC 转 YOLO 的脚本跑完别直接删 XML训练出问题时要能反查原始标注。2.3 train/val/test 划分与 fire.yaml 生成数据检查完就划分数据集。划分比例我用 80/12/8 到 86/10/4 之间火焰检测里 test 集可以小一点但 val 集必须涵盖白天、夜晚、室内、室外四类场景否则验证结果会有幸存者偏差。划分脚本如下import os, random, shutil random.seed(42) IMG_DIR, LAB_DIR images, labels TRAIN_R, VAL_R 0.82, 0.10 # test 占 0.08 all_imgs [f for f in os.listdir(IMG_DIR) if f.endswith(.jpg)] random.shuffle(all_imgs) n_train, n_val int(len(all_imgs) * TRAIN_R), int(len(all_imgs) * VAL_R) splits {train: all_imgs[:n_train], val: all_imgs[n_train:n_train n_val], test: all_imgs[n_train n_val:]} for split, files in splits.items(): for f in files: src_img os.path.join(IMG_DIR, f) src_lab os.path.join(LAB_DIR, os.path.splitext(f)[0] .txt) os.makedirs(fdataset/{split}/images, exist_okTrue) os.makedirs(fdataset/{split}/labels, exist_okTrue) shutil.copy(src_img, fdataset/{split}/images/{f}) shutil.copy(src_lab, fdataset/{split}/labels/{os.path.basename(src_lab)})逻辑说明先固定随机种子再 shuffle保证复现一致按比例切片后按 YOLOv5 要求的 images/labels 同级目录结构复制。参数说明TRAIN_R 和 VAL_R 按数据量调整单类 4000 张时 82/10/8 够用需要做交叉验证时把切片逻辑换成按场景分层采样。注意这里用 copy 不是 move原始数据保留一份后悔药总得留。划分完成后生成 fire.yaml指向新目录train: ./dataset/train/images val: ./dataset/val/images test: ./dataset/test/images nc: 1 names: 0: fire参数说明train 和 val 路径必须写成训练脚本能访问到的绝对路径或相对仓库根路径nc1 表示只有“火焰”一个类别test 路径在 train.py 里不会用到留给后续评估脚本。还有一个细节火焰数据包里通常只有含火图片空标注文件很少。如果现场误报多可以专门建一个 background 目录放不含火的监控画面对应 labels 放空 txt。YOLOv5 的 loader 能正常读入空标注文件目的就是把“这里没有火”这个信息教给模型。注意 mosaic 增强会把多张图拼在一起负样本和正样本可能同图出现这在单类任务里影响不大不用额外处理。3. 训练参数这样定模型尺寸、分辨率与评估指标选择数据集就位后训练参数就不是“照着默认跑”这么简单了。这套 yolov5 算法流程在电力场景里有一个特殊点漏检的代价远高于误检火情报警晚几分钟可能就烧大了。所以模型尺寸、输入分辨率、检查点策略都得围着“高召回”来调。下面按选型、命令、日志三个层面讲我实际跑的步骤。3.1 yolov5s 还是 yolov5m算力与精度的取舍YOLOv5 把同一套结构按深度和宽度系数分成 s/m/l/x 四档。深度影响网络层数宽度影响通道数两者都直接影响参数量和推理速度。4000 张单类数据我第一版用 s 起步理由很简单单类检测任务相对简单s 的容量足够现场部署的设备往往是工控机s 换 m 可能把帧率从 25 掉到 12。只有明确感觉到小目标漏检时才上 m。模型深度系数宽度系数典型适用场景yolov5s0.330.50边缘盒子、工控机、多路视频轮询yolov5m0.670.75服务器推理、大视野画面追求高召回参数说明这两个系数是结构缩放参数缩放之后模型结构和预训练权重一一对应不能把 yolov5s.pt 塞给 yolov5m 的网络结构。换模型后要重新下载对应预训练权重或者干脆从零开始训练。实际项目里我还常用一种折中先固定主干freeze训练 20 到 30 个 epoch再解冻全模型精调。这种做法的好处是前期 loss 下降快不易把预训练特征冲坏适合数据量偏少的情况。train.py 支持--freeze参数比如--freeze 10表示冻结前 10 层但我更习惯直接把 backbone 对应的层数冻住具体数值按网络结构数一遍再填。选型不只看精度还要看现场有多少路视频。一路 1080p 用 yolov5s 在工控机上能做到实时四路同时跑就得考虑分时复用这时候 s 和 m 的差距会直接叠加到设备成本上所以我的原则是先用 s 跑通链路确认瓶颈在小目标漏检再考虑升级。3.2 训练命令、批次与超参数说明训练入口是官方仓库的 train.py。我先在项目根目录放好 fire.yaml指向第 2 章划分的数据然后跑下面这条命令python train.py --data fire.yaml --weights yolov5s.pt \ --img 640 --batch 16 --epochs 150 --workers 4 --cache参数说明--img 是输入分辨率640 是默认平衡点火焰小目标占比高时提到 960显存占用大约翻倍。--batch 取决于显存8GB 显存跑 640 输入时 16 是安全值4GB 显卡降到 8。--cache 把图片缓存到内存训练速度快 30%代价是内存占用飙升机器内存吃紧时建议先不开试跑一个 epoch 再说。--epochs 150 配合早停不会真跑满后面讲怎么看 loss 决定提前停。有个常见认知误区单类任务照样要用预训练权重。yolov5s.pt 是在通用数据集上训过的特征火焰不在那些类别里但底层纹理、边缘特征仍然有效从预训练权重开始比 from scratch 收敛快得多。网络受限的环境下把 --weights 留空也能训只是要多花十几个 epoch。我自己一般再叠加两个开关python train.py --data fire.yaml --weights yolov5s.pt \ --img 640 --batch 16 --epochs 150 --workers 4 \ --cache --multi-scale --patience 20--multi-scale 会在每个 batch 随机抖动输入尺寸等效数据增强对火焰这种尺度变化明显的目标很有效缺点是拖慢训练节奏。--patience 20 表示连续 20 个 epoch 验证集 mAP 没有提升就自动停止这是最实用的防过拟合手段。注意早停保存的是历史最优权重 best.pt不是最后一个 epoch 的权重。提示训练前把数据集路径写成绝对路径避免换机器后路径不一致导致数据加载失败。学习率方面默认的 lr00.01 在 batch 16 下是合理值如果显卡不够把 batch 降到 8建议同步把 lr0 调到 0.005否则大学习率配小 batch 会让 loss 震荡训练曲线看着像锯齿。这个参数在训练日志里看不出来问题但会直接影响最终 mAP。3.3 训练日志怎么读火焰场景先看召回率训练完成后run 目录下会生成 weights/best.pt 和 last.pt还有一堆图表。外行看 mAP内行先看 PR 曲线和召回率。火焰检测的指标优先级是 R mAP P原因很直接漏检意味着火灾预警缺位误检至少还能被值班人员发现。具体操作打开 runs/train/exp/PR_curve.png看曲线整体形状。如果曲线在置信度 0.5 附近大面积凹陷说明模型对很多样本“没把握”优先怀疑小目标或遮挡样本不足如果曲线形状漂亮但精确率低说明有大量红色干扰物被当成火。val 集上单类火焰任务的 mAP0.5 一般能跑到 0.85 以上低于 0.8 就先回头查数据别继续调参。还要养成看 loss 曲线的习惯train loss 和 val loss 间距越拉越大就是过拟合信号。每次实验用 --project 和 --name 分开存结果不然过两天就不知道哪版权重是什么超参跑出来的这个黑匣子一旦出现浪费的是双倍时间。训练完再跑一遍验证脚本输出测试集上的整体指标python val.py --data fire.yaml --weights runs/train/exp/weights/best.pt \ --img 640 --task test --conf-thres 0.001 --iou-thres 0.5参数说明--task test 指定评测测试集--conf-thres 0.001 是为了把全部预测都保留下来这样 mAP 计算不被阈值截断--iou-thres 0.5 是 mAP0.5 的标准设定不要随意改。还有一个容易理解的参照如果 val 集 PR 曲线在 recall 0.8 附近精度急剧下跌说明模型为了吃下部分极端样本牺牲了大量精确率这批样本大概率是角度刁钻的火焰特写或严重遮挡。我会把这些图单独挑出来看确认是不是标注框太小。火焰数据里标注框过小模型学到的特征是“小色斑”而不是“火焰结构”这个问题在第 4 章的排查里会细说。4. 火焰检测避坑指南五类现场问题的现象、原因与对策这一章是资源落地时最值钱的部分。模型训练本身没有太多悬念真正让项目翻车的是下面五类问题我按实际踩坑顺序整理每条都按“现象→原因→解决”来讲。4.1 误检红色安全帽、警示灯和夕阳都被框成火现象模型在 val 集上 mAP 挺高一搬到现场红色安全帽、警示灯、橙色工程车频繁触发报警值班人员半小时就麻木了。原因火焰检测的静态模型本质上在学颜色和纹理的组合火焰的橙红色调与上述干扰物高度重叠打包数据集里这类“像火但不是火”的负样本几乎没有模型没机会学会区分。解决第一步补负样本采集一批含红色干扰物但不含火焰的画面标注为空 txt放进训练数据里。第二步在现场把报警置信度从 0.25 调到 0.4 左右。第三步是业务层面的连续帧确认——单帧检测结果不直接报警连续 3 帧都命中才触发这一步能过滤掉大部分闪烁误报。误报治理越靠规则层越便宜改阈值和确认逻辑比重新训练快得多。4.2 漏检大视野里的小火苗完全框不出来现象变电站户外大画面中火焰只有 30×30 像素模型在推理图上直接没反应置信度输出就是零。原因640 输入下小目标经过多次下采样后特征几乎消失数据集里近距离特写占比高小目标样本太少模型没见过这个尺度。解决把输入分辨率提到 960同时统计小目标占比。判断脚本可以复用 2.1 的计数逻辑把宽或高小于 0.05 的框单独数一下import os small 0 for f in os.listdir(labels): for line in open(os.path.join(labels, f)): w float(line.split()[3]) h float(line.split()[4]) if w 0.05 or h 0.05: small 1 print(小目标标注数:, small)逻辑说明w、h 是归一化后的框宽高0.05 对应 640 输入下的 32 像素小于这个值就属于容易丢失的小目标。参数说明这个阈值按实际画面微调大视野监控里 0.03 更合理。如果小目标占比不足 20%优先从远距离监控帧里补标不想重新采集的话滑窗裁剪大图、把小火焰放大贴回原图都能撑住训练但裁剪增强样本不能混进 val 集否则验证指标虚高。4.3 夜间和低照度场景掉点严重现象白天验证 mAP 0.9换到低照度摄像头后掉到 0.6火苗在暗背景上反而更难检出。原因火焰在夜间的形态与白天差异很大白天是亮斑加烟羽夜间可能是过曝的光球数据集里夜间图占比不足模型没学到两种分布的边界。解决先统计夜间图数量低于总量 20% 时用图像级增强补分布常见做法是降低亮度、提高对比度、加高斯噪声各生成一份副本。更直接的办法是找现场红外监控帧补充标注。如果现场用的是红外热像仪白天彩色模型基本失效需要把红外图单独建类或用灰度图补训这一步很多人会漏掉。注意增强生成的副本也要走一遍 4.5 的标注核对流程纯自动生成的脏数据会把模型带偏别为了省事把这一步跳过。4.4 过拟合训练 loss 降、验证 mAP 抖现象epoch 到 120 之后 train loss 还在下降val mAP 却在相邻几个 epoch 之间大幅跳动甚至明显回落。原因4000 张数据对单类任务偏少网络把训练集里的背景细节也背了下来属于典型的小数据过拟合。解决先加 --patience 早停再开 mosaic 和 HSV 增强。也可以把 weight decay 从默认的 0.0005 调大到 0.001给参数更新加约束。但 mosaic 增强不是越猛越好概率开太大时合成图上会出现四个半截火焰模型会把这些半截目标当作常态现场反而对完整火焰反应迟钝我一般把 mosaic 概率维持在 0.5 附近。如果验证集还是涨不上去回头查重复图——网络爬来的数据集经常有同一事件的多帧连续图同时出现在 train 和 val 会导致指标虚高删除相似图后再训。4.5 标注质量问题框没标完模型学歪现象PR 曲线在低置信度区间有一个奇怪的凹陷模型好像总在“试探”人工抽查发现部分图片只标了火苗烟雾区域的框被漏掉还有几张图标注框明显偏移。原因数据集来源不统一标注标准不一致是最常见的原因转格式时图片与 txt 文件名对错位也会产生这种症状。解决训练前抽 20 张图做标注可视化把 YOLO 坐标还原画回图上人工扫一遍。判断重复图最简单的方式是计算文件 MD5完全相同的图直接删相似帧可以用感知哈希再筛4000 张规模下 MD5 通常就够用了。标注质检这一步我从不在项目里跳过尤其是接外部数据集先花十分钟确认质量能省掉后面两天白训的时间。5. 部署验证走一遍ONNX 导出、阈值调整与误报治理现场部署最常见的路径是把 best.pt 导出成 ONNX用 onnxruntime 跑推理既不用在工控机上装完整 PyTorch 环境又能保持不错的推理速度。导出和推理验证的完整路径如下。5.1 ONNX 导出与最小推理脚本导出命令一行搞定python export.py --weights runs/train/exp/weights/best.pt \ --include onnx --img 640参数说明--include 指定导出格式--img 必须和训练时一致否则输出特征图尺寸对不上。导出后在相同目录生成 best.onnx接着用最小推理脚本验证输出import cv2, numpy as np, onnxruntime as ort sess ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) img cv2.imread(test.jpg) img_640 cv2.resize(img, (640, 640)) x cv2.cvtColor(img_640, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0 x x.transpose(2, 0, 1)[None] # HWC - NCHW out sess.run(None, {sess.get_inputs()[0].name: x})[0] # [1, 25200, 6]逻辑说明onnxruntime 输入要求 NCHW 且数值归一化到 01输出形状 [1, 25200, 6] 中 25200 (80² 40² 20²) × 3是三个尺度下 anchor 总数最后一维 6 对应 cx、cy、w、h、置信度、类别号。解码和 NMS 需要自己写坐标先缩放回 640 图再按原图尺寸比例还原。5.2 置信度阈值与连续帧确认推理结果不等于报警。我在现场按场景把阈值分开设部署场景置信度阈值确认规则室内配电房0.30连续 2 帧命中户外变电站0.40连续 3 帧命中参数说明室内干扰物少阈值低一点保召回户外夕阳、车灯干扰多阈值拉高加连续帧确认。固定机位还可以叠加区域屏蔽——焊接作业区、落日方向在特定时段直接跳过检测这类规则比调模型参数见效更快。这套带 4000 张火焰数据集的 YOLOv5 火焰识别资源按第 2 章到第 5 章的流程走一遍就能完整复现检查、训练、避坑、部署的脚本都在包里改好路径就能重跑。从那以后我每次接目标检测资源都会强制走一遍固定流程先做标注可视化抽检再看 val 集 PR 曲线上的召回率最后才谈阈值和报警逻辑。热力图、误报样例、漏检样例这三样不齐绝不上生产。希望帮到你。本文还有配套的精品资源点击获取