简介:这份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 层加一个检测头,stride=4 | 小病斑漏检 | 显存涨约 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 层,stride=4 [-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, reduction=16): 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, padding=3), nn.Sigmoid() ) def forward(self, x): ca = self.channel_att(x) x = x * ca sa = torch.cat([x.mean(1, keepdim=True), x.max(1, keepdim=True)[0]], dim=1) return x * self.spatial_att(sa)逻辑说明:通道注意力用全局平均池化压缩空间信息,学每个通道的权重;空间注意力在通道维度上做均值和最大值拼接,学每个位置的权重。reduction=16是压缩比,通道数少的时候可以调到 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_ok=True) 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_id:
cat 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.0;mixup在病害数据上容易把病斑和背景混得看不清,我一般关掉或设 0.1;hsv_h和hsv_s可以适当调大,模拟不同光照下的叶片颜色变化。
注意:调参不要一次改多个。我习惯先固定其他参数,只动学习率跑 50 epoch 看 loss 曲线,确定学习率合适后再调增强。一次改一堆,最后涨了跌了都不知道归因到哪。
4.3 训练过程监控与早停判断
训练启动后重点看三个指标:box_loss、obj_loss、mAP@0.5。正常情况下 box_loss 和 obj_loss 应该平稳下降,如果出现剧烈震荡,多半是学习率太大或 batch size 太小。
mAP@0.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、mAP@0.5、mAP@0.5:0.95。烟叶病害检测一般 mAP@0.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 位置。这张图能让人一眼看懂你改了什么。
第二张是检测效果对比图。左边原版漏检或误检的图,右边改进后的结果,用红框标出差异。这种图比任何指标都有说服力。
第三张是指标对比表。列清楚 mAP@0.5、mAP@0.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 里的每个数字都能追溯到具体的实验记录。这个习惯看起来麻烦,但省下的后悔药时间远超投入。
烟叶病害检测这个方向,技术栈不算新,但把数据、模型、部署、汇报串成一条线,还是需要不少实操细节。希望上面这些步骤和踩坑记录,能帮你少走点弯路。
本文还有配套的精品资源,点击获取