资讯动态

Python改进YOLOv5烟叶病害检测系统:小目标病斑与工程复现

发布时间:2026/10/25 6:19:44 来源:尧图企业网站定制
简介这份PPT围绕基于改进YOLOv5的烟叶病害检测系统展开面向计算机视觉、深度学习目标检测方向的学习者以及需要完成课程设计、毕业设计或项目汇报的读者重点回应烟叶病害识别中传统人工诊断不及时、准确率有限的问题。整包仅含1个pptx文件约10.34MB页面以研究背景、方法流程、实验设置与结果展示为主便于直接用于汇报或二次整理。内容从烟草病害对烟叶质量与农业生产的影响切入依次梳理传统诊断方法的局限、嵌套式YOLOv5的数据采集标注训练与系统整合思路并展示病害种类、位置和数量的标注效果同时涉及labelimg标注、环境搭建、训练识别、Adam与SGD优化器选择、激活函数与损失函数对比、网络结构改进等知识点。已有3131人学习可为目标检测改进、农业视觉应用及论文选题提供较完整的参考框架。1. 从一张病斑图到答辩PPTPython改进YOLOv5烟叶病害检测系统到底解决什么问题如果你手里有一批烟叶病斑图还要把检测结果做成一份能讲清楚的PPT这套Python基于改进YOLOv5的烟叶病害检测系统就不是“跑个模型”那么简单。它要解决的是三件事病斑在叶片上尺度小、背景杂乱时容易漏检训练指标好看但演示时翻车PPT里只有mAP曲线讲不清数据、改进点和误检边界。适合做农业视觉课题的开发者、需要交付课程设计或技术方案的同学也适合想把检测流程固化成可复现工程链的一线人员。下面按数据、改进、评估、避坑和PPT验证顺序拆开讲。2. 烟叶病害数据从田间到YOLO标签采集、清洗与格式转换的四个边界烟叶病害检测的第一道门槛不是模型而是数据。病斑可能只有几十个像素叶片堆叠、反光、阴影和土壤背景都会干扰标注。常见做法是先固定采集协议再做清洗和格式转换。这里不要一上来就调网络数据口径不统一后面改进YOLOv5的收益会被噪声吃掉。2.1 田间采集的四个硬指标光照、背景、病级与重复样本采集时我一般盯四个指标。光照上避免正午直射和闪光灯强反光会让病斑边缘消失背景上叶片要尽量平铺但也要保留一部分堆叠和土壤背景否则模型到了现场容易把“干净背景”当成先验。病级上早期斑点和晚期大面积枯斑要分开记录不能只标“有病/无病”否则检测头学到的是叶片整体颜色而不是病斑形态。重复样本上同一片叶子连续拍十几张要控制比例不然训练集和验证集看似随机划分实际仍然高度相似。一个可执行的清洗规则是按叶片编号分组划分训练集、验证集和测试集而不是按图片随机打散。这样验证集才能暴露真实泛化问题。常见做法是训练集占70%验证集20%测试集10%但同一片叶子的不同角度只能落在同一个集合。若某个类别少于200个标注框先别急着做复杂改进优先补数据或做针对性增强。提示病斑类别名称一旦确定后续标签转换、data.yaml和PPT图表都沿用同一套英文名不要中途改中文名再映射。2.2 用Python把标注转成YOLOv5可读的txt标签常见标注工具导出的是VOC XML而YOLOv5需要每张图对应一个txt每行格式为“类别id 中心x 中心y 宽 高”且全部归一化到0到1。下面脚本做转换、边界裁剪和空框过滤。类别顺序必须和后面data.yaml里的names完全一致。import os import xml.etree.ElementTree as ET # 类别顺序必须与data.yaml中的names一致 CLASSES [healthy, brown_spot, mosaic, bacterial_blight] def voc_to_yolo(xml_path, txt_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASSES: continue cls_id CLASSES.index(name) 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) # 裁剪到图像边界防止标注越界导致归一化异常 xmin max(0.0, min(xmin, img_w)) xmax max(0.0, min(xmax, img_w)) ymin max(0.0, min(ymin, img_h)) ymax max(0.0, min(ymax, img_h)) w xmax - xmin h ymax - ymin if w 1 or h 1: continue xc (xmin xmax) / 2.0 / img_w yc (ymin ymax) / 2.0 / img_h nw w / img_w nh h / img_h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {nw:.6f} {nh:.6f}) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) if __name__ __main__: xml_dir datasets/raw_xml txt_dir datasets/labels_all os.makedirs(txt_dir, exist_okTrue) # 实际使用时从图片读取宽高这里用示例尺寸说明参数位置 img_w, img_h 1920, 1080 for name in os.listdir(xml_dir): if not name.endswith(.xml): continue stem os.path.splitext(name)[0] voc_to_yolo( os.path.join(xml_dir, name), os.path.join(txt_dir, stem .txt), img_w, img_h )这段代码的关键参数是CLASSES和img_w、img_h。CLASSES顺序决定类别id不能随意调换img_w和img_h必须来自对应图片真实尺寸批量处理时建议用Pillow逐张读取而不是写死。脚本还做了边界裁剪解决标注框超出图像边缘的问题宽高小于1像素的框直接丢弃避免归一化后出现零面积目标。转换完成后抽查几张图把txt画回原图看框是否贴合病斑。血泪经验是不要只检查文件数量框偏移半片叶子的问题在训练损失里不一定立刻暴露。2.3 数据集划分与data.yaml的必填字段转换完标签后按叶片编号分组划分目录。目录结构可以保持YOLOv5常见的images/train、images/val、labels/train、labels/val。data.yaml只写必要字段路径尽量用相对路径换机器时少改一处。path: datasets/tobacco_leaf train: images/train val: images/val test: images/test nc: 4 names: [healthy, brown_spot, mosaic, bacterial_blight]path是数据集根目录train/val/test写相对path的图片目录YOLOv5会按同名规则去找labels下的txt。nc必须等于names长度names顺序必须和转换脚本里的CLASSES一致。常见错误是names里多一个空格或中文逗号训练能启动但类别映射错位评估时混淆矩阵会显示得莫名其妙。划分脚本建议单独保存划分清单把每张图的叶片编号、集合归属写进csv后面做PPT的数据分布图也直接复用这份清单。检查项合格标准常见翻车点标签格式每行5列归一化到0到1写成像素坐标类别顺序转换脚本与data.yaml一致中途增删类别划分方式按叶片编号分组同一叶片跨集合空标签无病斑图保留空txt或单独整理空txt被误删导致错位3. 改进YOLOv5的落点小目标病斑、遮挡与轻量化的取舍改进YOLOv5不要为了“改进”而堆模块。烟叶病害检测的主要矛盾是小目标病斑、叶片遮挡和背景干扰。常见有效的落点是在特征融合前加轻量注意力、提高小目标检测层的输入分辨率、控制模型宽度避免演示端跑不动。下面给一个可复现的轻量注意力模块和训练配置重点看参数为什么这样设。3.1 为什么原版YOLOv5在烟叶病斑上会漏检原版YOLOv5的检测头对大中目标更友好早期病斑只有几十像素经过多次下采样后特征响应很弱。叶片边缘和叶脉的纹理又和病斑接近模型容易把纹理当成目标。另一个问题是数据里健康叶片占比高背景类别不均衡置信度阈值一调高就漏检一调低就误检。改进时优先做三件事保留更高分辨率的浅层特征、在通道维度上抑制背景响应、用更严格的病斑级评估而不是只看整图mAP。注意力模块不是越复杂越好。烟叶图像颜色分布集中通道注意力比空间注意力更稳如果数据里病斑位置分布很散再加入轻量空间分支。下面这个SEBlock结构简单插入到Backbone末端或检测头前都容易改显存压力小适合课程设计和单卡演示环境。3.2 加一个轻量注意力模块的代码实现import torch from torch import nn class SEBlock(nn.Module): def __init__(self, channels, reduction16): super().__init__() hidden max(8, channels // reduction) self.pool nn.AdaptiveAvgPool2d(1) self.fc nn.Sequential( nn.Linear(channels, hidden, biasFalse), nn.SiLU(inplaceTrue), nn.Linear(hidden, channels, biasFalse), nn.Sigmoid() ) def forward(self, x): b, c, _, _ x.shape y self.pool(x).view(b, c) y self.fc(y).view(b, c, 1, 1) return x * y # 使用示例假设输入特征通道为256 if __name__ __main__: x torch.randn(2, 256, 40, 40) block SEBlock(256, reduction16) y block(x) print(y.shape)channels必须和插入位置的输出通道一致reduction控制压缩比例16是常见起点通道数很小的时候用max(8, channels // reduction)兜底避免隐藏层过窄。forward里先全局平均池化得到通道描述再经过两层线性层和Sigmoid生成权重最后逐通道相乘。它不改变特征图尺寸所以插入后不需要改检测头锚框。实际修改时常见做法是在models/common.py里注册模块再在模型yaml的某个C3后替换或追加。别一次改三处先加一处做A/B对比否则涨点也说不清是哪来的。3.3 训练命令与超参数配置从预训练权重到冻结策略训练命令要能复现参数要写进实验记录。下面是一条常见的单卡训练命令预训练权重用YOLOv5常见的小模型权重具体文件名按本地已有权重替换。python train.py \ --img 640 \ --batch 8 \ --epochs 100 \ --data data/tobacco.yaml \ --weights yolov5s.pt \ --project runs/tobacco \ --name exp01_se \ --cache \ --workers 4 \ --freeze 10--img 640是输入分辨率病斑特别小时可以试800但显存和推理耗时都会上升--batch 8适合单卡显存有限的场景显存够可以加到16--epochs 100是起点看验证集mAP连续多轮不涨再停--data指向2.3的yaml--weights是预训练权重空字符串表示从零训练一般不推荐--project和--name决定输出目录方便对比实验--cache把图片缓存到内存数据量大时注意内存--workers是数据加载线程--freeze 10冻结前10层小数据集上能减少过拟合数据量足够时可以不加。参数建议起点调整依据img640病斑像素小于20时试800batch8显存占用和梯度稳定性lr00.01冻结层多时适当降低lrf0.01控制末期学习率conf-thres0.25演示漏检多时降到0.2再评估iou-thres0.45病斑密集时试0.5训练时不要只看loss下降。每10轮抽一批验证图做可视化重点看病斑框是否贴合、有没有把叶脉框进去。改进模块如果让mAP涨了0.5个点但推理慢了一倍要判断演示环境能不能接受。轻量化不是越轻越好烟叶病害检测系统最终要落在可解释的工程链上PPT里能讲清“为什么加、加了之后哪类病斑变好”比单纯堆指标更有说服力。4. 训练完别急着做PPTmAP之外的评估、可视化与误检归因训练日志里的mAP只能说明整体重叠度不能直接回答“早期病斑漏没漏”“背景误检多不多”。做PPT前先把评估做厚病斑级召回、置信度分布、混淆矩阵和误检案例。否则答辩现场被问一句“这个mAP对病害分级有什么用”很容易卡住。4.1 看mAP之外还要看什么病斑级召回与置信度分布病斑级召回的做法是对每张验证图按真实标注框逐个判断是否被同类别预测框以一定IoU命中统计每个类别的召回率。整图mAP会把大斑和小斑混在一起病斑级召回能暴露小目标问题。置信度分布则把真正例和假正例的分数分开画如果假正例集中在0.3到0.5说明阈值附近不稳定演示时换一张背景图就可能翻车。我一般会输出三张表每个类别的 Precision/Recall、不同置信度阈值下的漏检数、误检案例清单。误检清单要带图片名和预测框坐标后面做PPT的“失败案例分析”直接引用。注意测试集不要反复调阈值调参阶段用验证集最终报告用测试集。4.2 用Python画PR曲线和混淆矩阵的落地脚本YOLOv5训练目录下会生成results.csv列名可能随环境有细微差异先打印列名再画图。下面脚本读取训练记录画mAP曲线并保存方便放进PPT。import pandas as pd import matplotlib.pyplot as plt csv_path runs/tobacco/exp01_se/results.csv df pd.read_csv(csv_path) df.columns [c.strip() for c in df.columns] print(df.columns.tolist()) plt.figure(figsize(8, 5)) plt.plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) plt.plot(df[epoch], df[metrics/mAP_0.5:0.95], labelmAP0.5:0.95) plt.xlabel(epoch) plt.ylabel(metric) plt.legend() plt.tight_layout() plt.savefig(ppt_assets/map_curve.png, dpi200)csv_path指向实验输出目录metrics/mAP_0.5和metrics/mAP_0.5:0.95是常见列名如果列名带空格先strip。dpi 200保证PPT里不糊。混淆矩阵不建议自己手画常见做法是运行验证脚本并保存混淆矩阵图再和病斑级召回表一起放进PPT。图表下的结论要具体例如“brown_spot召回从0.72提升到0.79但mosaic在强光样本上仍然偏低”不要只写“效果良好”。4.3 误检翻车现场怎么归因背景、标注与尺度误检归因按三步走。先看背景把预测框周围裁剪出来判断是不是叶脉、土壤反光或相邻叶片边缘。再看标注有些“误检”其实是漏标尤其是密集小斑标注员只标了大的。最后看尺度统计误检框的宽高分布如果集中在极小框说明小目标分支或输入分辨率不够如果集中在大框可能是类别定义不清把健康黄化也标成了病害。导出TorchScript并跑单张图片推理是验证“训练环境之外能不能用”的最小闭环。常见导出命令如下python export.py \ --weights runs/tobacco/exp01_se/weights/best.pt \ --include torchscript \ --img 640--weights指向最佳权重--include torchscript表示导出TorchScript--img与训练分辨率保持一致。导出后不要直接做PPT先在另一台机器上加载导出的模型跑一张图确认预处理、归一化和输出解析一致。推理前后处理对不上是演示翻车的常见原因模型本身不背这个锅。5. 烟叶病害检测系统避坑从标注到演示的5类翻车记录这一章按“现象→原因→解决”记录常见坑。烟叶病害检测系统的坑很少集中在网络结构更多在数据口径、阈值和演示环境。下面5条是我更愿意在训练前就检查的。5.1 数据与标注的坑病斑框越画越大之后现象训练loss正常下降但验证图里病斑框明显偏大小斑点被框进整片叶脉。原因标注规范只写了“框住病斑”没有规定是否包含晕圈。不同标注员对边缘理解不同模型学到的是平均后的模糊边界。解决在标注规范里加两条框只包含病斑主体不包含明显健康组织边缘模糊时以可见变色区域为准。转换脚本里加面积过滤对宽高超过叶片面积一定比例的框人工复核。PPT里放一张标注规范对比图比放十张训练曲线更能说明数据质量。现象验证集mAP很高测试集一换试验田就掉得很厉害。原因按图片随机划分同一片叶子的不同角度同时进了训练集和验证集验证集泄漏。解决按叶片编号或采集批次分组划分划分清单落csv。测试集至少保留一个独立采集日期的数据PPT里明确写出划分口径。5.2 训练与推理的坑验证集涨点、现场却漏检现象加了注意力模块后mAP涨了但演示时早期小斑仍然漏。原因改进模块作用在中后期特征小目标浅层信息没有被充分利用同时置信度阈值沿用了默认值小斑分数普遍偏低。解决先做病斑级召回统计确认漏检集中在小框还是特定类别再考虑提高输入分辨率或在浅层特征上加轻量分支。阈值在验证集上按类别扫一遍不要一套阈值走天下。现象训练环境推理正常换一台机器加载模型报错或结果全空。原因预处理不一致训练时用了归一化和RGB顺序推理时用了BGR或没归一化导出模型和权重加载方式混用。解决把预处理写成一个固定函数训练、验证、导出推理共用导出后跑固定测试图和原权重输出做数值对比。演示前至少在两台机器上各跑一次。5.3 演示与PPT的坑换台电脑就翻车现象答辩现场上传图片后界面卡住或者检测框位置整体偏移。原因演示端没有锁定依赖环境图片被前端压缩后尺寸变化后端仍按原图尺寸映射框。解决演示环境提前装好固定依赖准备离线权重和示例图前后端约定好原图尺寸传递框坐标按原图归一化再回写。PPT里不要只放成功案例留一页误检和漏检边界现场被问到时能接住。现象PPT里改进点讲得很热闹被问“这个模块为什么适合烟叶”时答不上来。原因实验只做了涨点对比没有做消融和可视化改进理由停留在“别人也这么加”。解决补一组消融原版、加模块、加模块并调阈值固定数据划分和训练轮数再补注意力热力图或特征图对比。PPT只讲一条主线问题是什么、改哪里、哪类病斑变好、代价是什么。6. 把系统讲成可复现的工程链PPT最后一页的验证清单与进阶技巧最后一页别放“谢谢聆听”放一张可复现验证清单。我的习惯是把PPT技术页分成四块数据口径、改进落点、评估边界、演示环境。每块只留一个可验证数字例如“按叶片分组划分测试集独立采集日期”“注意力模块插在检测头前消融固定100轮”“brown_spot病斑级召回0.79mosaic强光样本仍偏低”“演示端锁定预处理函数两台机器输出一致”。这样别人照着清单能复现也能看出边界。验证项最低通过标准记录位置标签回画抽查20张框贴合病斑数据检查记录数据划分同一叶片不跨集合划分csv消融实验原版与改进同口径对比实验记录表导出推理另一台机器单图结果一致演示检查表误检案例至少5张带归因PPT失败案例页进阶技巧是给每个类别单独记录一个“演示阈值”不要在全系统共用0.25。做法是在验证集上按类别扫0.15到0.5选召回和误检折中的点再把阈值写进配置文件。另一个技巧是把误检案例按背景、标注、尺度打标签PPT里只放最具代表性的三张剩下的放附录。这样现场追问时有据可查不会陷入“模型玄学”的解释。我自己踩过的最深坑是训练指标很好看演示时却因为预处理不一致整体偏移后来养成了导出后先在另一台机器跑固定测试图的习惯。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑