资讯动态

YOLOv5烟叶病害识别:从数据集构建到模型部署全流程

发布时间:2026/10/9 12:54:14 来源:尧图企业网站定制
简介面向大学生课程设计、期末作业与毕业设计场景的YOLOv5烟叶病害识别源码项目提供从数据预处理、模型训练、病害预测到结果后处理的完整工作流适合希望系统掌握目标检测落地流程的深度学习初学者。压缩包共378个文件以156个jpg图像样本、90个txt标注文件、36个py源码、28个yaml配置及3个pt权重为主另含演示视频和安装文档整体约782.55MB目录结构清晰便于按数据、模型与训练流程分别查阅。目前已有147人学习下载。借助这套资源可学会烟叶病害图像的数据标注、增强与划分理解YOLOv5的网络搭建与损失函数并通过附带的数据集完成从训练到推理的完整实验演示视频能直观展示运行效果安装教程则降低环境配置门槛帮助快速在本地复现项目为农业病害识别类课题提供可扩展的参考基线。1. 烟叶病害识别模型只是工具箱数据集才是上限烟叶病害识别这个方向说到底是把 YOLOv5 这样的目标检测模型训练到能在一张烟叶照片里同时圈出病斑位置、判断病害类别。听起来是个标准的目标检测落地项目但真正动手做过一轮的人都知道卡住你的往往不是模型结构而是数据烟叶病害没有现成的公开大数据集病斑边界模糊、叶片纹理复杂、不同生长期表现差异大同一个病害在不同地块拍出来可能完全不像同一个东西。这个标题给出的源码、数据集、演示视频和安装教程本质上是一套完整的复现链路——你拿到的不只是训练脚本而是从数据标注到模型部署的整套打法。这篇文章就按这条链路拆开讲数据集怎么构建、环境怎么搭不翻车、训练参数怎么设、哪些坑我替你踩过了。适合正在做农业检测项目、或者想把 YOLOv5 用到真实场景的开发者照着走一遍你就能在自己机器上跑通一个能用的烟叶病害识别模型。2. 烟叶病害数据集的构建与标注这一关过了后面都是水到渠成2.1 数据从哪来不要指望现成数据集自己拍是常态烟叶病害识别最大的门槛不是模型是数据。公开数据集里能找到的烟叶病害图片非常少而且大多是实验室环境拍的、背景干净、光照均匀拿到田间地头基本失灵。我自己的习惯是如果项目对精度要求不高比如只要区分健康叶和病叶先从田间自然光照下拍摄开始如果要细分到具体病害类别就得在几个不同地块、不同生长期分别采集。拍摄时注意三个点一是叶片要占画面主体别让背景抢了注意力二是同一片叶子的病斑要从不同角度、不同距离多拍几张增加样本多样性三是把健康叶片也拍进去作为负样本不然模型会倾向于“见到叶子就报病”。采集到的原始图片先做一轮筛选把模糊的、过曝的、叶片占比太小的删掉。我一般会控制在每张图 800×600 到 1920×1080 之间太大训练慢太小病斑细节丢失。数量上每个病害类别最少 300 张原图加上数据增强勉强够 YOLOv5s 这种小模型起步想训练到能实际用的水平每个类别 800 张以上才稳。2.2 用 LabelImg 标注框的边界决定了模型的“视力”标注工具用 LabelImg 就够安装很简单pip install labelimg labelimg # 打开图形界面打开后按 P 键切换到 PascalVOC 格式会生成 XML 文件或者直接默认 YOLO 格式生成 txt 文件。我推荐直接存 YOLO 格式省一步转换。操作上就是画框、选类别、保存没什么玄学真正的坑在标注规范上。烟叶病斑和通用目标检测的标注不太一样。通用场景里框人、框车目标边界清晰框稍微大一点小一点影响不大但烟叶病斑是渐变的病斑边缘从变色到正常组织是过渡的标的时候很容易凭感觉画。我的经验是病斑标注宁紧勿松框紧贴病斑的明显变色区域不要把外围的褪绿过渡区框进来。框大了模型学到的边界就是模糊的推理时会往外飘。另一个是遮挡问题两片叶子叠在一起只标看得见的部分不要脑补被遮住的病斑范围。标注完成后一定做一轮复查。我自己翻车过标了 600 张图训练出来 mAP 看起来很高但拿到新图上一测框全打在叶片边缘上后来发现是标注时有大概 50 张图的类别选错了模型被带偏了。复查方法很简单用 LabelImg 打开每张图过一遍重点看两个地方框有没有明显偏离病斑中心类别 ID 有没有选错。2.3 数据集目录组织与划分按地块分别按文件随机分YOLOv5 的训练脚本要求数据集按固定目录结构组织。我一般这样放datasets/ └── tobacco_disease/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 与图片同名的 txt 标注文件 │ └── val/ └── data.yaml # 数据集配置文件图片和标注文件必须同名一个 .jpg 对应一个 .txt。txt 里每行格式是类别ID 中心点x 中心点y 宽度w 高度h注意 x、y、w、h 都是相对图片宽高的归一化值范围 0 到 1。LabelImg 存 YOLO 格式时会自动算好这些值不需要手写。划分训练集和验证集时有一个很多人忽略的坑不要随机打乱文件再按比例切片。烟叶病害的图片往往是在同一时间、同一地块拍的背景、光照高度相似随机划分会把同一株烟叶的不同角度照片同时分到训练集和验证集导致验证集“泄漏”——模型其实见过这些样本了val mAP 虚高一到新地块就露馅。我一般按拍摄时间或地块编号来划分比如 A 地块和 B 地块的照片进训练集C 地块进验证集这样才能验证模型真正的泛化能力。2.4 数据增强YOLOv5 自带增强够用了别重复叠加YOLOv5 训练时默认开启 Mosaic、MixUp、随机仿射变换、HSV 扰动等增强对小数据集非常友好。我的建议是先用默认增强不要自己在预处理里再叠加一轮 OpenCV 变换。一个常见的翻车操作是自己先把图片做了水平翻转和亮度调整存到硬盘里又开 YOLOv5 自带的增强结果模型在增强后的重复样本上过拟合泛化反而更差。YOLOv5 的增强是线内实时做的每个 epoch 看到的增强结果都不同比你离线做几百张增强图高效得多。小数据集上唯一值得手动干预的是类别不平衡。如果某个病害类别样本特别少我一般会单独对这类图片做离线增强比如旋转 90 度、加高斯噪声、局部放大把数量补到其他类别的三分之一以上再交给 YOLOv5 训练。这样比单纯靠 Mosaic 硬撑要稳。3. YOLOv5 环境搭建版本对应关系不弄清楚装完就是黑匣子3.1 Python、PyTorch、CUDA 的版本匹配这是第一个劝退点YOLOv5 的依赖很敏感PyTorch 版本和 CUDA 版本不匹配装完跑起来各种报错玄学到让人怀疑人生。我用得比较稳的组合是 Python 3.8 PyTorch 1.8.1 CUDA 11.1这个组合也是 YOLOv5 官方早期版本测试最多的环境。如果你拿到的是新版本的 YOLOv5 源码也要先看 requirements.txt 里锁的 PyTorch 版本不要直接 pip install torch 装最新版。创建虚拟环境是必须的我一般这样操作conda create -n yolo python3.8 conda activate yolo pip install torch1.8.1 torchvision0.9.1 --index-url https://download.pytorch.org/whl/cu111注意--index-url后面指定的 cu111 表示 CUDA 11.1 对应的 PyTorch 版本。如果机器没有 NVIDIA 显卡可以装 CPU 版把 cu111 改成 cpu但训练速度会慢很多适合验证代码能不能跑通不适合真正训练。装完后到 Python 里验证一下import torch print(torch.__version__) # 查看 PyTorch 版本 print(torch.cuda.is_available()) # 是否检测到 GPU如果torch.cuda.is_available()返回 False大概率是 PyTorch 版本和显卡驱动不匹配或者装成了 CPU 版。这时候不要慌先nvidia-smi看一下驱动支持的 CUDA 版本再回到上一步选对应的 PyTorch 版本重新装。3.2 requirements.txt 里那些装了必踩的库YOLOv5 的 requirements.txt 里除了 torch 和 torchvision还有几个库值得单独说一下。opencv-python必须装但注意不要和opencv-contrib-python同时装两个一起装会互相覆盖导致 cv2 导入报错。matplotlib用于训练过程的可视化版本不要太老3.3 以上就行。pandas和seaborn是画混淆矩阵用的如果只做训练不画图可以注释掉少装两个依赖少两个风险。装依赖时有一个保守做法pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple用国内镜像源速度快但要注意镜像源同步可能有延迟如果某个库版本找不到就换成默认源。装完以后跑一下 YOLOv5 自带的检测脚本验证环境python detect.py --source data/images/bus.jpg --weights yolov5s.pt能正常输出检测结果环境就算通了。这里有个细节第一次跑会自动下载 yolov5s.pt 权重文件如果下载不动可以手动下载后放到项目根目录。权重文件属于官方预训练模型用的是 COCO 80 类可以直接拿来做迁移学习的起点。3.3 训练时的硬件要求没有 8G 显存就老实改参数烟叶病害识别不像自动驾驶那么吃显存但也不能太寒酸。YOLOv5s 是最小的模型在 640×640 分辨率下batch size 设为 16 时显存占用大概 6~8G这是最常用的配置。如果你的显卡只有 4G 显存有两条路一是把--img从 640 降到 416batch size 降到 8能跑但精度会掉二是换 YOLOv5nnano 版本模型更小更快显存占用可以压在 4G 以内但精度比 s 版本低一截。说个我的实测感受同一个烟叶病害数据集YOLOv5s 训练 100 轮val mAP 能到 0.82 左右换成 YOLOv5n同样的参数只能到 0.74 左右。如果你的目标是跑通流程YOLOv5n 就够了如果是做实际项目还是建议至少用 s 版本。显存不够不是世界末日但不要指望靠调参把 nano 模型调到 s 的精度天花板在那。4. 训练自己的烟叶病害模型配置文件、命令与三个必调参数4.1 数据配置 data.yaml类别名和路径一个都不能错数据集的 data.yaml 是训练脚本读取的第一个配置文件写错了全是白忙活。我见过最离谱的报错是在 YAML 文件里中文写路径导致训练时找不到图片。稳妥的做法是# datasets/tobacco_disease/data.yaml train: datasets/tobacco_disease/images/train val: datasets/tobacco_disease/images/val nc: 3 names: [brown_spot, tobacco_mosaic, powdery_mildew]train和val指向图片目录注意是图片目录不是 labels 目录YOLOv5 会根据图片目录自动找同名的 labels 目录。nc是类别数量和 names 列表长度必须一致不一致会在训练开始时报错。names 里的顺序要和标注时的类别 ID 对应上——标注时 brown_spot 是 0这里就必须是第一个不能按字母序重排。如果训练时提示图片路径找不到先检查是不是用了相对路径而当前工作目录不在项目根目录。我习惯把 data.yaml 里的路径写绝对路径一了百了。但绝对路径的问题在于换机器要改如果用相对路径就记住训练命令要在项目根目录下执行别在 datasets 目录里执行。4.2 训练命令最小可复现的那条命令环境装好、数据准备好就可以开始训练了。我用的是这条命令python train.py \ --data datasets/tobacco_disease/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --name tobacco_run1拆开解释每个参数。--weights yolov5s.pt是加载 COCO 预训练权重做迁移学习别小看这个参数从零训练的话100 轮可能刚起步加载预训练权重的话同样 epoch 数能收敛到可用精度。--img 640是把输入图片缩放到 640×640分辨率越高小病斑越容易检测到但显存和训练时间也线性涨。--batch 16是每轮迭代的批量大小显存不够就降到 8 或 4。--epochs 100是训练轮数小数据集 100 轮够用了加多了容易过拟合。--name tobacco_run1是给这次训练起个名字输出会写到 runs/train/tobacco_run1 目录下方便多个实验对比。训练开始后终端会打印每个 epoch 的 loss 值包含 box_loss、obj_loss、cls_loss 三项。我的经验是看趋势而不是看绝对值前 20 轮 loss 下降快是正常的到 60 轮以后趋于平缓。如果 loss 一直震荡不降先不要加 epoch而是回去查数据集标注质量或者学习率。4.3 学习率与超参数hyp 文件里动这两个就够YOLOv5 默认的学习率设置hyp.scratch.yaml对大多数数据集都适用不需要大改。如果一定要调我只动两个lr0初始学习率和momentum动量。默认 lr00.01、momentum0.937 是官方调过的如果你换了数据集后发现 loss 震荡特别剧烈可以把 lr0 调到 0.005 试试代价是收敛会变慢。反过来如果 loss 下降非常慢可以把 lr0 调回 0.01 或者 0.015。训练时还有个容易忽略的参数是--patience默认 100意思是连续 100 轮 val mAP 没有提升就提前停止训练。我第一次跑烟叶数据集时没注意这个参数训练到第 80 轮停了结果模型还没收敛完后来改成--patience 50让它在 100 轮的范围内多跑一截。小数据集上建议把这个值设小一点比如 30~50省时间。4.4 训练结果怎么看weights 目录和 result.png 里的门道训练结束或被提前停止后去runs/train/tobacco_run1/目录下看结果。weights/目录里有两个文件best.pt是 val mAP 最高的权重last.pt是最后一轮的权重。默认用 best.pt 做推理就行。results.png里画了 loss 曲线和 mAP 曲线重点看 mAP 曲线是不是还在上升——如果最后一轮 mAP 还在涨说明 100 轮不够可以加--epochs 150续跑如果 mAP 曲线涨到一半掉头向下说明过拟合了应该减少 epoch 或者增强数据多样性。还有一个只看数字发现不了的问题如果 val mAP 很高比如 0.85 以上但在新图片上效果很差百分之八九十是数据划分泄漏也就是验证集和训练集太像了。这时候回头检查第 2 章说的按地块划分方法重新划分后再训练。5. 烟叶病害识别常见坑与排查记录5 条血泪经验5.1 训练 loss 变成 NaN先查学习率再查标注数据现象训练跑到第 20 轮终端打印的 loss 突然变成 nan之后每轮都是 nan模型废了。原因最常见是学习率太大导致梯度爆炸其次是标注文件里有空文件或者坐标值超过 0~1 范围。我用 640 分辨率配默认 lr00.01 没出过这个问题但把 img 改成 1280 后出现过一次原因是分辨率涨了梯度尺度变了学习率没跟着降。解决优先把 lr0 降到 0.005batch size 减半。如果还是 nan就去检查 labels 目录下的 txt 文件用脚本把所有标注文件的坐标值筛一遍看有没有大于 1 或者小于 0 的。筛完删掉坏文件重训。5.2 验证集 mAP 虚高新图上一测就翻车现象训练结束看 val mAP 有 0.85自我感觉良好结果拿手机拍一张烟叶照片测框全偏了甚至把叶脉当成病斑。原因几乎可以断定是训练集和验证集数据划分不规范。同一片叶子、同一个背景只是换个角度拍验证集里有一部分样本在训练集里都有“近亲”模型记住了背景而不是病斑特征。解决按地块或按拍摄批次重划数据集确保验证集图片在拍摄时间、地点上和训练集完全没有重叠。重新划分后 mAP 会掉一些但那个数字才是真实水平。5.3 显存不足OOM 报错现象训练一开始就报RuntimeError: CUDA out of memory。原因batch size 设置超过了显存容量或者 img 分辨率太高。4G 显存强行跑 640 分辨率加 batch 16 必炸。解决先nvidia-smi看显存总量按显存大小倒推配置。4G 显卡用--img 416 --batch 8 --weights yolov5n.pt6G 显卡用--img 640 --batch 8 --weights yolov5s.pt8G 及以上可以放开跑 640 加 batch 16。还有一个技巧是加--cache参数把图片缓存到内存显存不变但能减少磁盘 IO 瓶颈。5.4 检测框乱飘框的位置和病斑对不上现象推理时模型能标出类别但框的位置明显偏离病斑甚至框在叶片外。原因训练时正样本数量太少模型没学够病斑的位置特征。另一个可能性是标注时框画得太松把病斑周围的叶片正常区域也框进去了模型学到的是“叶片区域”而不是“病斑区域”。解决先检查标注质量把框和病斑边缘的贴合度提高再把该类别的图片数量补到 500 张以上最后考虑用--augment参数开启测试时增强推理时对同一张图做多种变换再合并结果能稍微缓解框偏的问题但治标不治本根子还在数据。5.5 训练到一半mAP 突然掉到 0现象训练曲线好好地往上走到第 70 轮 mAP 突然归零之后又慢慢恢复。原因数据集里有一张图片的标注文件损坏坐标值是 nan 或者格式错乱训练时 loss 爆炸但没中断把权重带崩了后面几轮又自己恢复。这个比较隐蔽因为不是每轮都会采样到那张坏图。解决训练前写一个脚本遍历 labels 目录检查所有 txt 文件的格式和数值范围。我习惯把这个检查做成数据预处理的一部分每次新数据集进来先跑一遍格式化数据本身就是在给训练兜底。6. 推理部署与进阶验证从 detect.py 到移动端的最后一步6.1 用 best.pt 做单张图和视频推理训练完成后常用的是 best.pt。推理命令python detect.py \ --source data/smoke_test.jpg \ --weights runs/train/tobacco_run1/weights/best.pt \ --conf-thres 0.25 \ --iou-thres 0.45--conf-thres 0.25是置信度阈值低于这个值的检测结果会被过滤掉。烟叶病害场景里如果误报多把正常叶判成病叶我一般往上调到 0.35如果漏报多病斑没被圈出来就调到 0.15。--iou-thres 0.45是 NMS 阈值控制重叠框的合并力度默认 0.45 够用不建议乱动。如果--source传视频文件路径YOLOv5 会逐帧检测并输出标注后的视频。实际项目里我很少直接用 detect.py 做视频推理它只是验证工具真要落地还是要导出模型后自己写推理脚本。6.2 导出 ONNX 模型脱离 PyTorch 跑推理的第一步训练好的模型要部署到生产环境一般先导出 ONNXpython export.py \ --weights runs/train/tobacco_run1/weights/best.pt \ --include onnx \ --img 640导出后的 onnx 文件可以给 ONNX Runtime 或者 TensorRT 调用不再依赖 PyTorch 环境。我实测过在 GPU 上 ONNX Runtime 的推理速度比 PyTorch 快 20%~30%在 CPU 上差距更明显。导出过程一般不会报错如果报错大多是 torch 版本和 onnx 版本不兼容升级 onnx 到最新版就好。导出后用onnxruntime跑一眼输出和 PyTorch 差值确定精度没掉再进部署。6.3 进阶验证扩展类别到其他作物病害一个参数都不用改烟叶病害的标注和训练流程换到其他作物上完全通用。我后来把同一套数据流程迁移到茶树病害上改的只有 data.yaml 里的 nc 和 names训练命令和参数一点没动。这就是 YOLOv5 这类框架的好处它把通用目标检测的能力封住了你聚焦在数据上就行。但有一个边界要承认YOLOv5 对小目标的检测能力一般烟叶上的早期病斑如果只有几个像素大它大概率会漏这是模型本身的局限不是你的数据问题。要突破这个局限得换 YOLOv8 或者检测头带注意力机制的模型那就是另一个话题了。做了一轮烟叶病害识别下来我最大的教训是不要急着调模型、调参数先把数据集的划分和标注做干净模型训练只是水到渠成的事。这个方向值不值得做如果你手头有农业检测的项目非常值得——它的链路短、可复现性强、迁移成本低。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑