Python基于改进YOLOv5的烟叶病害检测系统实战与PPT汇报指南 简介这份PPT围绕基于改进YOLOv5的烟叶病害检测系统展开面向计算机视觉深度学习方向的学生、科研人员及农业智能化从业者帮助其理解如何将目标检测算法落地到烟叶病害识别场景。内容涵盖烟叶病害防治背景、传统诊断方法的局限、嵌套式YOLOv5识别思路、数据集采集与labelimg标注、环境搭建、训练与识别效果以及网络结构改进、损失函数与激活函数选择等优化方向并给出论文选题与研究思路建议。资源包为1个pptx文件约10.34MB结构完整、图文并茂适合直接用于课程汇报、毕业答辩或项目方案参考。目前已有3123人学习下载读者可从中获取从问题定义、数据准备到模型训练与系统整合的完整技术路线并借鉴YOLOv5改进与性能优化的具体切入点。1. 烟叶病害检测系统从一份 PPT 到一套能跑通的 YOLOv5 方案烟叶病害检测这件事真正做过的人都知道难点从来不在能不能识别而在识别得准不准、部署得动不动。我最早接触这个方向是帮一个做烟草种植的朋友看他的病害巡检流程——人工背着相机下田回来一张张翻图一天下来眼睛都花了还容易漏掉早期病斑。后来他问我能不能用 Python 加 YOLOv5 做一套自动检测顺便整理成一份能拿去汇报的 PPT。这个需求其实很典型既要一套能落地的检测系统又要一份讲得清楚的方案文档。这篇文章就围绕Python 基于改进 YOLOv5 的烟叶病害检测系统这个标题展开把改进点怎么选、数据集怎么标、模型怎么训、PPT 怎么讲这几件事串起来。适合两类人一类是刚入门 Python 和 YOLOv5、想拿一个完整项目练手的同学另一类是已经跑过官方 demo、但不知道改进到底改哪里、汇报时讲不出重点的从业者。下面从选型理由开始一步步落到能复现的命令和参数。2. 改进 YOLOv5 到底改什么烟叶病害场景的三个真实痛点2.1 为什么原版 YOLOv5 在烟叶病害上会翻车先说要解决的问题。烟叶病害检测和通用目标检测有几个明显差异直接拿 COCO 预训练的 YOLOv5s 去跑大概率会遇到三类翻车现场。第一类是小目标密集。烟叶上的病斑尤其是早期赤星病、黑胫病的斑点在整张田间照片里可能只占几十个像素。YOLOv5 的 P3 特征图 stride 是 8对小目标本身就不算友好病斑一密集就容易粘连成一个框。第二类是背景干扰强。田间照片里有土壤、杂草、反光叶片、甚至其他健康叶片颜色和纹理跟病斑接近。原版模型的注意力容易被这些区域分走导致误检。第三类是类别不均衡。实际采集时健康叶片和常见病害样本多稀有病害样本少训练时模型会偏向多数类稀有类召回率上不去。这三点决定了改进不是随便加个模块就行得针对性地补。常见的改进方向有三条换更细粒度的检测头、加注意力机制、改损失函数处理不均衡。下面分别说清楚选型理由。2.2 三个改进方向的选型对比改进方向具体做法解决痛点代价增加小目标检测层在 P2 层加一个检测头stride4小病斑漏检显存涨约 30%推理变慢引入注意力机制在 Backbone 末端加 CBAM 或 SE背景干扰、误检参数量小幅增加替换损失函数用 Focal Loss 或带类别权重的 BCE类别不均衡需要调超参收敛变慢我一般的做法是先加 P2 检测头再加 CBAM最后视情况换损失。原因是小目标漏检是最影响业务指标的先解决它收益最大注意力机制改动小、风险低适合第二步损失函数改动影响训练稳定性放最后调。提示不要三个改进一起上。我见过有人一次性全加结果训练 loss 震荡、mAP 反而下降最后连是哪个改动导致的都排查不出来。改进要一个一个加每加一个跑一次 baseline 对比。2.3 改 P2 检测头的具体配置YOLOv5 的模型结构定义在models/yolov5s.yaml里。原版有三个检测头对应 P3/P4/P5。加 P2 检测头需要改两处Backbone 里增加一个更浅的特征输出Head 里增加对应的检测分支。# models/yolov5s-p2.yaml 关键改动 backbone: # ... 前面层保持不变 [[-1, 1, Conv, [64, 3, 2]], # P2 层stride4 [-1, 1, Conv, [128, 3, 2]], # P3 # ... 后续层 ] head: [[-1, 1, Conv, [256, 3, 2]], # 新增 P2 分支 [[-1, 6], 1, Concat, [1]], # 与 Backbone P2 层拼接 [-1, 3, C3, [256, False]], # 输出 P2 检测特征 # ... 原有 P3/P4/P5 分支 [[15, 18, 21, 24], 1, Detect, [nc]], # 四个检测头 ]逻辑说明Detect层的输入从三个变成四个nc是类别数烟叶病害常见分 5 到 8 类按实际标注填。参数上P2 分支的通道数我一般设成 P3 的一半避免显存爆掉。改完后用python models/yolo.py --cfg models/yolov5s-p2.yaml检查结构是否能正常构建这一步能提前发现维度不匹配的问题。2.4 注意力模块加在哪里最有效CBAM 由通道注意力和空间注意力两部分组成加在 Backbone 的 C3 模块之后效果比较稳。我试过加在 Neck 部分提升不如加在 Backbone 末端明显原因是 Backbone 末端特征语义强、空间信息还没完全丢失注意力能同时利用两者。# models/common.py 中新增 CBAM class CBAM(nn.Module): def __init__(self, c1, reduction16): super().__init__() self.channel_att nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Conv2d(c1, c1 // reduction, 1), nn.ReLU(), nn.Conv2d(c1 // reduction, c1, 1), nn.Sigmoid() ) self.spatial_att nn.Sequential( nn.Conv2d(2, 1, 7, padding3), nn.Sigmoid() ) def forward(self, x): ca self.channel_att(x) x x * ca sa torch.cat([x.mean(1, keepdimTrue), x.max(1, keepdimTrue)[0]], dim1) return x * self.spatial_att(sa)逻辑说明通道注意力用全局平均池化压缩空间信息学每个通道的权重空间注意力在通道维度上做均值和最大值拼接学每个位置的权重。reduction16是压缩比通道数少的时候可以调到 8避免信息损失过多。加完后记得在 yaml 里对应位置插入CBAM层通道数要和前后层对齐。3. 数据集准备从田间照片到 YOLO 格式的完整流程3.1 烟叶病害数据采集与标注规范数据集质量直接决定模型上限这一步偷懒后面全是坑。采集时我一般要求单张照片里病斑清晰可见光照均匀避免正午强光直射同一病害至少覆盖早中晚三个发病阶段健康叶片也要采作为负样本降低误检。标注用 LabelImg 或 X-AnyLabeling格式选 YOLO。标注规范要提前定死病斑边界框紧贴病斑边缘不包含健康组织多个相邻病斑如果连成一片标成一个大框单个叶片上病斑超过 20 个的考虑裁图后再标否则小目标太密。类别命名建议用英文加编号比如brown_spot、black_shank、mosaic避免中文路径在训练时出编码问题。标注文件里每行格式是class_id x_center y_center width height坐标都是归一化到 0 到 1 的值。3.2 目录结构与数据划分脚本YOLOv5 要求的数据集目录结构是固定的我一般这样组织dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/划分脚本按 7:2:1 分注意要保证同一张原图裁出来的子图分到同一集合否则验证集里出现训练集见过的病斑指标会虚高。import os, random, shutil def split_dataset(img_dir, label_dir, out_dir, ratios(0.7, 0.2, 0.1)): files [f for f in os.listdir(img_dir) if f.endswith((.jpg, .png))] random.seed(42) # 固定种子保证可复现 random.shuffle(files) n len(files) n_train int(n * ratios[0]) n_val int(n * ratios[1]) splits { train: files[:n_train], val: files[n_train:n_train n_val], test: files[n_train n_val:] } for split, fs in splits.items(): for sub in [images, labels]: os.makedirs(os.path.join(out_dir, sub, split), exist_okTrue) for f in fs: shutil.copy(os.path.join(img_dir, f), os.path.join(out_dir, images, split, f)) label_f os.path.splitext(f)[0] .txt src_label os.path.join(label_dir, label_f) if os.path.exists(src_label): shutil.copy(src_label, os.path.join(out_dir, labels, split, label_f)) split_dataset(raw/images, raw/labels, dataset)逻辑说明random.seed(42)固定随机种子保证每次划分结果一致方便对比实验。ratios参数按数据集规模调样本少于 1000 张时验证集比例可以提到 0.25避免验证指标波动太大。脚本只复制有对应标注文件的图片防止出现无标签样本干扰训练。3.3 data.yaml 配置与类别数核对# data/leaf_disease.yaml path: ../dataset train: images/train val: images/val test: images/test nc: 6 names: [brown_spot, black_shank, mosaic, healthy, powdery_mildew, bacterial_wilt]nc必须和标注文件里的最大 class_id 加一一致names顺序要和标注时的类别顺序完全对应。我踩过一次坑标注时类别顺序改了但 yaml 没同步训练 loss 一直不降排查了半天才发现是标签错位。核对方法很简单跑一行脚本统计所有 label 文件里出现过的 class_idcat dataset/labels/train/*.txt | awk {print $1} | sort -u输出应该是 0 到 nc-1 的连续整数缺号或多号都说明标注有问题。4. 训练与调参让改进后的模型真正收敛4.1 从预训练权重起步的训练命令改进后的模型结构变了但 Backbone 大部分层和原版一致所以还是从官方预训练权重起步能省很多收敛时间。命令如下python train.py \ --weights yolov5s.pt \ --cfg models/yolov5s-p2-cbam.yaml \ --data data/leaf_disease.yaml \ --epochs 200 \ --batch-size 16 \ --img-size 640 \ --hyp data/hyps/hyp.scratch-low.yaml \ --device 0参数说明--weights加载预训练权重结构不匹配的层会自动跳过并随机初始化--batch-size根据显存调16 是 8G 显存的安全值显存够可以上 32--img-size烟叶病害建议用 640小目标多的话可以试 800但显存和速度要权衡--hyp用 low 增强配置因为病害数据本身不多强增强容易过拟合。4.2 超参数怎么调学习率、锚框与增强YOLOv5 的超参都在hyp.scratch-low.yaml里。针对烟叶病害我一般调三个地方。学习率lr0默认 0.01改进后模型加了新层我通常降到 0.005让新层稳定收敛。lrf是最终学习率比例保持 0.01 即可。锚框anchors如果数据集里病斑尺寸和 COCO 差异大建议用 k-means 重新聚类。YOLOv5 自带python utils/autoanchor.py可以在训练前自动检查并调整开启--autoanchor就行。数据增强方面mosaic对小目标有帮助保持默认 1.0mixup在病害数据上容易把病斑和背景混得看不清我一般关掉或设 0.1hsv_h和hsv_s可以适当调大模拟不同光照下的叶片颜色变化。注意调参不要一次改多个。我习惯先固定其他参数只动学习率跑 50 epoch 看 loss 曲线确定学习率合适后再调增强。一次改一堆最后涨了跌了都不知道归因到哪。4.3 训练过程监控与早停判断训练启动后重点看三个指标box_loss、obj_loss、mAP0.5。正常情况下 box_loss 和 obj_loss 应该平稳下降如果出现剧烈震荡多半是学习率太大或 batch size 太小。mAP0.5 在验证集上的曲线如果连续 20 个 epoch 不涨就可以考虑早停了。YOLOv5 自带--patience参数设成 30 比较稳妥。另外要关注每一类的 AP如果某一类 AP 明显低于其他类说明该类样本太少或标注质量差回去补数据比继续训更有效。# 训练结束后用验证集评估 python val.py \ --weights runs/train/exp/weights/best.pt \ --data data/leaf_disease.yaml \ --img-size 640 \ --task val输出里会给出每一类的 P、R、mAP0.5、mAP0.5:0.95。烟叶病害检测一般 mAP0.5 能到 0.85 以上就算可用稀有类如果低于 0.7建议单独做数据增强或加类别权重。5. 避坑与排查烟叶病害检测训练中最容易踩的五个坑5.1 现象训练 loss 正常下降但 mAP 一直很低原因大概率是标注文件和图片没对上或者类别顺序错位。YOLOv5 不会报错只会默默用错标签训练。解决跑一遍标签核对脚本确认每个 label 文件都有对应图片且 class_id 在合法范围内。另外检查 data.yaml 里names的顺序和标注时是否一致。5.2 现象小病斑检测框粘连成一片原因P2 检测头没加或者加了但锚框尺寸没适配小目标。解决确认 yaml 里 Detect 层输入是四个特征图用 autoanchor 重新聚类锚框如果还不行把输入尺寸从 640 提到 800 再试。5.3 现象验证集指标高但实际部署漏检严重原因训练集和验证集来自同一批照片分布太接近模型没学到泛化能力。解决划分数据集时按采集批次或地块分不要随机分。验证集最好包含不同光照、不同生长阶段的照片。有条件的话留一个独立测试集只用一次。5.4 现象加了 CBAM 后训练变慢且 mAP 没提升原因CBAM 加的位置不对或者通道压缩比设得太小导致信息损失。解决CBAM 加在 Backbone 末端 C3 之后不要加在浅层reduction从 16 调到 8 试试如果还没提升说明该数据集背景干扰不严重注意力机制收益有限可以去掉。5.5 现象显存不足batch size 只能设很小原因P2 检测头增加了特征图尺寸显存占用明显上升。解决用--img-size 512先跑通流程开启混合精度训练--amp或者用梯度累积模拟大 batch。如果都不行考虑换 YOLOv5m 以下的模型规模。6. 把系统讲成一份能过评审的 PPT结构、图表与演示技巧6.1 PPT 的章节骨架怎么搭技术汇报 PPT 最忌讳堆代码和公式。我一般按问题—方案—验证—落地四段来搭对应到烟叶病害检测系统就是第一段讲人工巡检的痛点和病害识别的业务价值第二段讲改进 YOLOv5 的三个改动点和选型理由第三段放对比实验数据原版 vs 改进版的 mAP、推理速度、显存占用第四段讲部署形态和实际检测效果截图。每段控制在 3 到 5 页总页数 20 页以内。评审的人没耐心翻长 PPT重点是把为什么改和改完效果如何讲清楚。6.2 必须放的三张图第一张是改进前后的网络结构对比图。不用画全部层只画 Backbone、Neck、Head 三段标出新增的 P2 分支和 CBAM 位置。这张图能让人一眼看懂你改了什么。第二张是检测效果对比图。左边原版漏检或误检的图右边改进后的结果用红框标出差异。这种图比任何指标都有说服力。第三张是指标对比表。列清楚 mAP0.5、mAP0.5:0.95、参数量、推理时间四项原版和改进版各一行。表格比柱状图更直观评审能直接看到数字。6.3 演示时的两个技巧一是准备一个现场推理 demo。用detect.py跑一张新拍的田间照片实时出结果比放录屏更有冲击力。命令很简单python detect.py \ --weights runs/train/exp/weights/best.pt \ --source demo_images/ \ --img-size 640 \ --conf-thres 0.4 \ --save-txt--conf-thres演示时可以调到 0.4比训练时的默认值低一点让更多病斑被框出来视觉效果更好。--save-txt会输出每个框的坐标和类别方便后续做统计。二是提前准备被问到的问题。评审最常问的三个改进后推理速度降了多少、能不能部署到边缘设备、数据集规模够不够。前两个用实测数据回答第三个如实说当前规模并给出扩充计划比硬撑更可信。6.4 我自己的一个习惯每次做完一个检测项目我都会把训练配置、数据集版本、指标结果整理成一个 markdown 文件跟代码放一起。原因是有一次汇报完三个月有人问当时用的什么学习率我翻遍聊天记录才找到。从那以后配置和结果必须落盘PPT 里的每个数字都能追溯到具体的实验记录。这个习惯看起来麻烦但省下的后悔药时间远超投入。烟叶病害检测这个方向技术栈不算新但把数据、模型、部署、汇报串成一条线还是需要不少实操细节。希望上面这些步骤和踩坑记录能帮你少走点弯路。本文还有配套的精品资源点击获取