
简介这份资源面向希望入门目标检测与火灾图像识别的Python开发者提供基于yolov5框架的完整实践方案覆盖从数据准备、模型训练到推理预测的全流程。压缩包共19个文件约30.45MB包含pt预训练权重、yaml配置文件、ipynb训练笔记、png与jpg结果图表、mp4演示视频及gif动图等可直观查看训练曲线与检测效果。资源内附火灾与非火灾图像数据集说明并给出训练脚本、数据加载与预测脚本的组织方式便于读者理解YOLO网格预测、边界框与类别概率等核心机制。已有239人学习下载适合具备一定Python与深度学习基础、想通过真实项目掌握yolov5训练调参、数据集构建与性能优化的读者参考。1. 火灾图像识别为什么总在烟雾刚起时掉链子凌晨两点仓库角落的纸箱开始冒烟监控画面里只有一小团灰白雾状区域值班人员没注意到等明火起来已经晚了。这类场景正是火灾图像识别要解决的核心问题在火焰还没成型、只有烟雾或微弱火光时就把异常框出来。Python 基于 YOLOv5 实现的火灾图像识别本质是把火灾检测当成目标检测任务用标注好的火焰、烟雾图片训练模型再部署到摄像头或图片流上做实时推理。它适合做安防、园区、仓储、森林防火方向的工程师也适合想拿一个完整项目练手 YOLOv5 训练自己数据集的人。标题里提到的源代码、模型文件、数据集对应的就是一套能跑通训练和推理的最小闭环而不是只给一个权重文件让你猜怎么用。2. 火灾数据集怎么准备从原始图片到 YOLO 标签2.1 火灾图像识别的类别定义与数据来源做火灾检测第一步不是写代码而是想清楚你要检测什么。常见做法是把类别分成两类fire明火和 smoke烟雾有些场景会再加一类 spark火花或 flame_small小火苗。类别越细标注成本越高但误报会少一些。我一般建议新手先用 fire 和 smoke 两类跑通等模型能稳定识别再考虑细分。数据来源上公开火灾数据集通常包含几千到上万张图片覆盖室内、室外、白天、夜间、近距离和远距离。但公开数据有个通病烟雾图片偏少明火图片偏多模型容易把橙色物体误判成火。所以拿到数据后先做一次类别分布统计如果 smoke 占比低于 30%要么补采烟雾图片要么在训练时给 smoke 类更高权重。图片格式统一成 jpg 或 png分辨率不用强求一致YOLOv5 训练时会自动缩放到 640。但要注意如果原图特别大比如 4000×3000建议先缩到 1280 宽再标注否则标注框坐标容易算错。2.2 用 labelImg 标注并转成 YOLO 格式标注工具用 labelImg 就够了安装命令如下pip install labelImg labelImg打开后设置图片目录和保存目录格式选 YOLO。每张图至少框出所有火焰和烟雾区域框要贴紧目标边缘不要留太多背景。标注完成后每张图对应一个 txt 文件每行格式是class_id x_center y_center width height其中坐标都是归一化到 0 到 1 之间的浮点数。class_id 从 0 开始0 代表 fire1 代表 smoke。标注完检查一遍常见错误是框超出图片边界或者宽高为 0。可以用下面这段脚本快速检查import os import glob label_dir labels for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(f格式错误: {txt} - {line}) continue cls, x, y, w, h map(float, parts) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): print(f坐标越界: {txt} - {line})这段脚本遍历所有标签文件检查每行是否有 5 个字段以及中心点和宽高是否在合理范围内。如果输出大量越界记录说明标注时图片被缩放但标签没同步更新需要重新导出。2.3 划分训练集、验证集和测试集YOLOv5 要求数据目录结构如下dataset/ images/ train/ val/ labels/ train/ val/常见做法是按 8:1:1 划分训练、验证、测试。但火灾数据有个坑同一个视频截出来的连续帧不能同时出现在训练集和验证集否则验证指标会虚高。正确做法是按视频或按场景划分同一场景的图片只进一个集合。划分脚本可以这样写import os import random import shutil img_dir all_images label_dir all_labels out_dir dataset train_ratio, val_ratio 0.8, 0.1 os.makedirs(f{out_dir}/images/train, exist_okTrue) os.makedirs(f{out_dir}/images/val, exist_okTrue) os.makedirs(f{out_dir}/labels/train, exist_okTrue) os.makedirs(f{out_dir}/labels/val, exist_okTrue) imgs [f for f in os.listdir(img_dir) if f.endswith((.jpg, .png))] random.shuffle(imgs) n_train int(len(imgs) * train_ratio) n_val int(len(imgs) * val_ratio) for i, img in enumerate(imgs): name os.path.splitext(img)[0] label name .txt if i n_train: split train elif i n_train n_val: split val else: continue shutil.copy(os.path.join(img_dir, img), f{out_dir}/images/{split}/{img}) shutil.copy(os.path.join(label_dir, label), f{out_dir}/labels/{split}/{label})这段代码把全部图片打乱后按比例复制到对应目录标签文件同名复制。注意测试集这里没单独建目录实际项目里可以再留 10% 做最终测试训练时完全不碰。3. YOLOv5 训练火灾检测模型配置文件与关键参数3.1 准备 YOLOv5 代码和火灾数据配置文件先把 YOLOv5 代码拉下来安装依赖git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt然后新建一个火灾数据配置文件 fire_data.yaml放在 yolov5/data 目录下path: ../dataset train: images/train val: images/val nc: 2 names: [fire, smoke]path 是数据集根目录train 和 val 是相对路径。nc 是类别数names 按 class_id 顺序写。如果只检测火焰nc 改成 1names 只留 fire。模型配置文件不用自己写直接用 yolov5s.yaml 就行。火灾检测通常不需要太大模型yolov5s 在速度和精度之间比较平衡树莓派 4B 或 RK3568 这类边缘设备也能跑。如果服务器端追求精度可以换 yolov5m 或 yolov5l但推理速度会明显下降。3.2 训练命令与超参数怎么设最小训练命令python train.py --img 640 --batch 16 --epochs 100 --data data/fire_data.yaml --weights yolov5s.pt --project runs/fire --name exp1参数含义img 是输入尺寸640 是默认值显存不够可以降到 416 或 320batch 是批大小16 适合 8G 显存12G 可以上 32epochs 是训练轮数火灾数据一般 100 到 300 轮够用weights 是预训练权重用 yolov5s.pt 做迁移学习比从零训练收敛快很多。如果烟雾样本少可以在 train.py 里加类别权重或者用 --hyp 指定超参数文件。常见做法是复制 data/hyps/hyp.scratch-low.yaml把 smoke 对应的损失权重调高。但更简单的办法是数据增强时对烟雾图片多做几次复制。训练过程中看几个指标box_loss 和 obj_loss 是否稳定下降mAP0.5 是否在涨。如果 mAP 卡在 0.3 以下大概率是标注有问题或者学习率太大。可以先用 --epochs 10 跑一遍小实验确认 loss 在降再开长训练。3.3 训练结果怎么看mAP、召回率和误报训练结束后 runs/fire/exp1 目录下有 results.csv 和 weights/best.pt。results.csv 里记录了每轮的指标重点看metrics/mAP_0.5IoU 阈值 0.5 时的平均精度火灾检测一般能到 0.7 以上算可用。metrics/recall召回率火灾场景宁可误报也不能漏报所以召回率比精度更重要。val/box_loss验证集损失如果训练损失降但验证损失涨说明过拟合。可以用下面脚本画一下 mAP 曲线import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/fire/exp1/results.csv) df.columns df.columns.str.strip() plt.plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) plt.plot(df[epoch], df[metrics/recall], labelrecall) plt.xlabel(epoch) plt.ylabel(value) plt.legend() plt.savefig(fire_train_curve.png)这段代码读取训练日志画出 mAP 和召回率随轮次的变化。如果召回率明显低于 mAP说明漏检多需要补烟雾或小火样本。4. 推理与部署从单张图片到视频流4.1 用 detect.py 跑通单张图片和视频训练完先用官方推理脚本验证python detect.py --weights runs/fire/exp1/weights/best.pt --source test_fire.jpg --img 640 --conf 0.4source 可以是单张图片、图片目录、视频文件甚至摄像头编号。conf 是置信度阈值火灾检测建议设 0.3 到 0.5太低会误报太高会漏报。推理结果默认保存在 runs/detect/exp 下。如果要在 Python 代码里调用模型可以这样写import torch model torch.hub.load(ultralytics/yolov5, custom, pathruns/fire/exp1/weights/best.pt) model.conf 0.4 model.iou 0.45 results model(test_fire.jpg) results.print() results.save(output)model.conf 是置信度阈值model.iou 是 NMS 的 IoU 阈值。火灾检测里如果两个框重叠度高NMS 会保留一个iou 设 0.45 比较稳。results.print() 输出检测到的类别和坐标results.save() 保存带框图片。4.2 视频流推理的帧率与跳帧策略直接对视频每一帧跑 YOLOv5在普通 CPU 上可能只有 2 到 5 FPS达不到实时。常见做法是跳帧推理比如每 3 帧检测一次中间帧复用上一次结果。代码示例import cv2 import torch model torch.hub.load(ultralytics/yolov5, custom, pathbest.pt) model.conf 0.4 cap cv2.VideoCapture(fire_video.mp4) frame_id 0 last_boxes [] while True: ret, frame cap.read() if not ret: break frame_id 1 if frame_id % 3 0: results model(frame) last_boxes results.xyxy[0].cpu().numpy() for box in last_boxes: x1, y1, x2, y2, conf, cls box cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 0, 255), 2) cv2.imshow(fire, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码每 3 帧推理一次其余帧画上一次的框。跳帧数根据设备性能调GPU 上可以每帧都跑树莓派上可能得跳到 5 或 10。注意跳帧太多会导致快速移动的火焰框位置滞后需要根据场景权衡。4.3 模型导出与边缘设备部署注意点如果要在树莓派 4B 或 RK3568 上部署先把 PyTorch 模型导出成 ONNXpython export.py --weights best.pt --include onnx --img 640导出后可以用 onnxruntime 推理速度比 PyTorch 快不少。RK3568 这类带 NPU 的芯片还需要把 ONNX 转成 RKNN 格式用 rknn-toolkit2 转换。转换时注意输入尺寸和归一化参数要和训练时一致否则精度会掉。树莓派 4B 上跑 YOLOv5s ONNX640 输入大概 3 到 5 FPS320 输入能到 8 到 10 FPS。如果帧率不够优先降输入尺寸而不是换更小的模型因为火灾检测对小火焰敏感模型太小召回率会明显下降。5. 火灾识别项目避坑与排查那些让我返工的细节5.1 模型把夕阳和灯光误判成火焰现象模型在傍晚或路灯场景下频繁框出 fire置信度还不低。原因训练数据里明火图片大多是橙红色而夕阳、暖色灯光颜色分布接近模型学到了颜色捷径而不是火焰纹理。解决补采黄昏、灯光、橙色物体负样本标注时这些图片不放任何框让模型学会区分。也可以在数据增强里加 HSV 色调扰动降低对颜色的依赖。5.2 烟雾漏检严重mAP 虚高但实际不可用现象验证集 mAP 有 0.75但实际视频里烟雾刚起时完全没框。原因烟雾样本太少且标注时只框了浓烟薄烟没标。模型只学会了浓烟特征。解决重新检查标注把薄烟、远距离烟雾都框上。如果数据不够用烟雾合成工具在正常图片上叠加烟雾纹理扩充样本。训练时把 smoke 类损失权重调高 1.5 到 2 倍。5.3 训练 loss 不降或变成 nan现象训练几轮后 box_loss 变成 nan或者一直不降。原因学习率太大、标注坐标越界、或者某张图片损坏。解决先用第 2 章里的检查脚本过一遍标签确认没有越界。然后把学习率降到 0.001 或 0.0005 再试。如果还不行检查图片是否有 0 字节文件用 PIL 打开每张图确认能正常读取。5.4 推理时框位置偏移或框太大现象检测到的框比实际火焰大一圈或者位置偏了。原因训练时图片被 letterbox 缩放推理时如果没做同样处理坐标会对不上。解决用官方 detect.py 或 torch.hub 加载模型时预处理是自动的不要自己写 resize。如果自己写推理代码必须复现 letterbox先等比例缩放到 640再填充灰边推理后再把坐标映射回原图。5.5 模型文件在另一台机器上加载失败现象best.pt 在训练机上能跑拷到部署机上报错。原因PyTorch 版本不一致或者 torch.hub 加载时联网下载 YOLOv5 代码失败。解决部署机上装和训练机相同版本的 PyTorch 和 ultralytics/yolov5。如果无法联网把 YOLOv5 代码目录一起拷过去用 torch.load 直接加载模型或者导出 ONNX 后用 onnxruntime 推理摆脱对 YOLOv5 代码的依赖。6. 把火灾识别模型压到边缘设备还能保住召回率的几个手法边缘设备部署火灾识别最大的矛盾是算力有限但召回率不能降。我自己的习惯是先在服务器上把模型训到召回率 0.85 以上再做压缩压缩后重新在验证集上测一遍如果召回率掉超过 5 个百分点就回退。第一个手法是输入尺寸分级。不要一上来就用 640先试 416 和 320看召回率掉多少。火灾场景里远距离小火对分辨率敏感如果 320 下漏检明显就保持 416用跳帧换帧率。第二个手法是通道剪枝。YOLOv5 里可以用 torch-pruning 对 Conv 层做 L1 剪枝剪掉 20% 到 30% 通道再微调 10 轮。剪枝后模型体积能小三分之一推理快 20% 左右。但剪枝比例超过 40% 后召回率会断崖下跌别贪。第三个手法是量化。ONNX 转 TensorRT 时用 FP16 量化速度能翻倍精度几乎不掉。INT8 量化需要校准集火灾数据校准集里必须包含烟雾和明火样本否则量化后烟雾检测会明显变差。验证压缩效果时不要只看 mAP要单独统计 fire 和 smoke 的召回率。下面这段脚本可以按类别算召回率import numpy as np def recall_per_class(preds, gts, num_classes2, iou_thres0.5): recalls [] for c in range(num_classes): tp, fn 0, 0 for img_id in gts: gt_boxes [b for b in gts[img_id] if b[4] c] pred_boxes [b for b in preds.get(img_id, []) if b[4] c] matched set() for gt in gt_boxes: best_iou 0 best_idx -1 for i, pred in enumerate(pred_boxes): if i in matched: continue iou compute_iou(gt[:4], pred[:4]) if iou best_iou: best_iou iou best_idx i if best_iou iou_thres: tp 1 matched.add(best_idx) else: fn 1 recalls.append(tp / (tp fn 1e-6)) return recalls这段代码按类别统计召回率compute_iou 需要自己实现或从 YOLOv5 utils 里导入。跑完后如果 smoke 召回率比 fire 低很多说明压缩对烟雾特征损伤大需要把烟雾样本加进量化校准集重新导出。最后一个习惯每次换设备或换模型格式都拿同一段测试视频跑一遍人工数一下漏检和误报。指标好看不代表现场能用我吃过好几次 mAP 0.8 但实际视频里烟雾漏一半的亏。希望帮到你。本文还有配套的精品资源点击获取