资讯动态

4900张YOLO叶片病害数据集:从采集标注到训练部署全流程

发布时间:2026/10/15 8:38:25 来源:尧图企业网站定制
做智慧农业方向久了你会发现一个很现实的问题模型结构其实不难找代码跑通也不难真正卡住人的反而是数据集。尤其像植物叶片病害检测这类任务公开数据集要么类别太老、场景太干净要么和田间地头的真实情况差距太大训练出来的模型一到现场就“水土不服”。这段时间我刚好整理了一套4900张的YOLO智慧农业数据集覆盖了多种作物叶片的常见病害和健康状态从采集、清洗、标注到训练、调优、部署都走了一遍踩了不少坑也有了一些可以复用的经验。这篇文章就把整个过程展开讲讲想入坑智慧农业目标检测的朋友可以直接照着参考。开门见山说结论这套数据集的目标不是做一个“论文精度”的演示而是解决“企业能不能用起来”的问题。所以我的整体设计思路是——用YOLO做叶片层面的目标检测把病害区域定位出来而不是单纯做整片叶子的分类。这样模型在田间场景下才有实用价值能告诉农户“这片区域的叶片有异常”也能配合喷药设备做精准对靶。1. 项目整体设计与数据策略1.1 为什么选择YOLO而不是直接在叶片层面分类很多人上手植物病害第一反应是用ResNet这种分类网络做叶片分类输入一张叶片照片模型输出“健康”还是“某某病”。这种方案在PlantVillage这类干净背景数据集上表现不错但真拿去在田里拍光照、角度、遮挡、泥土背景一上来分类模型的准确率会掉得非常快。根本原因在于分类模型学的是“全局特征”它对图像的整体语义做判断一旦背景占据了大部分画面模型的注意力就会被带偏。目标检测模型则天然适合解决这个问题它需要在空间上找出“哪里有问题”本质上是在做细粒度定位对背景干扰的鲁棒性要强不少。再有一个重要考量是落地。农业现场的硬件条件普遍有限你不可能在每个大棚里都放一台带高端GPU的服务器。YOLO作为单阶段检测器速度优势是双阶段检测器比如Faster R-CNN比不了的配合TensorRT或OpenVINO做推理加速在Jetson Nano或者Intel NUC这类边缘设备上也能跑实时。我实际测试过YOLOv8s的权重在Jetson Orin Nano上做FP16推理640分辨率的输入可以稳定跑到40帧以上这对巡检小车、智能喷药机这类场景来说完全够用。所以从算法可行性、部署成本和维护难度三个角度看YOLO都是现阶段最务实的选择。这套数据集的定位也很清楚不是要做成某个竞赛刷分的benchmark而是给智慧农业业务提供一份贴合真实场景的“弹药”。所以我对数据的要求不是“好看”而是“有用”——图像必须尽量贴近农户用手机、监控摄像头或者农业无人机拍到的真实画面标注必须能支撑目标检测模型学到真正有判别力的病害特征。后面的所有采集、清洗和标注规范都围绕这个定位展开。1.2 场景与类别设计不是越多越好最开始规划类别时我的想法是“把能想到的病害全放进去模型多学一点总没错”。但做了几百张初稿标注之后我就意识到这个思路的问题是致命的一是很多病害在叶片上的视觉特征高度相似比如早疫病和晚疫病前期都表现为褐色斑块没有显微镜级别的细节根本分不开强行建模只会让模型在类别之间反复横跳二是每个类别都要有足够多的有效样本模型才学得动类别一旦铺开单类样本量就会被摊薄整体精度反而下降。所以我把类别设计原则定为两句话大类有限、类间差异大。结合当前智慧农业场景的实际产业价值这套数据集最终保留了常见的苹果、葡萄、番茄三类作物每类下面对应三到四种典型病害状态。表格列出来大概是这样的作物类别标签病害/状态说明标注数量张苹果Apple_healthy健康叶片350苹果Apple_scab黑星病叶面褐黑色斑580苹果Apple_rot黑腐病大面积坏死斑420葡萄Grape_healthy健康叶片330葡萄Grape_black_rot黑腐病圆形坏死点610葡萄Grape_esca轮斑病黄化条带斑纹540番茄Tomato_healthy健康叶片380番茄Tomato_early_blight早疫病同心轮纹褐斑600番茄Tomato_late_blight晚疫病边缘水渍状斑510这九类是这套数据集的主体占全部样本的80%以上。剩余样本用于补充复杂场景比如多病共存、多叶片重叠、逆光低照度等边界情况。这些样本不单独拆类别而是统一归到对应作物的已有类别下目的是让模型在“正常分类”之外也能学会处理真实环境中必然存在的遮挡和光线问题。你可能会问为什么番茄晚疫病和早疫病我最终还是都放进去了因为虽然它俩在语义上容易混淆但在实际农业生产中是两种不同的防治方案如果你做的是面向农户的诊断系统区分这两者恰好是核心卖点。为了把这两个类别分开我在采集和标注阶段特别增加了叶片背面的样本因为晚疫病早期在叶片背面的水渍状边缘比正面更清晰。这一点后面讲采集规范时再展开。1.3 4900张样本如何分配训练、验证与测试策略4900张听起来不少但如果均匀铺到九个类别里每个类别也就500多张对YOLO这种需要大量样本的模型来说只能算“小规模私有数据”。所以分配策略必须精打细算。我最终采用的比例是训练集70%、验证集20%、测试集10%并且严格保证按“图像来源”而不是按“单张图像”来切分。什么意思如果同一块地里同一株果树连拍的三张叶片图两张进了训练集一张进了验证集那验证集的评估指标就会虚高因为模型已经“见过”很接近的图像了。所以在切分脚本里我会为每个采集批次生成一个唯一ID按批次ID做分层抽样确保来自同一拍摄批次的图像要么全留在训练集要么全划分到验证/测试集。具体到数量分布训练集约3430张验证集约980张测试集约490张。验证集不参与任何训练测试集更是只在最终评估时候用一次。数据增强了之后训练集的实际投入训练量会在3430张的基础上翻四五倍这点放到后面的增强部分细说。我建议所有做自己数据集的同学都保留一个清晰的数据目录最好是这种结构leaf_disease/ ├── images/ │ ├── train/ # 3430张 │ ├── val/ # 980张 │ └── test/ # 490张 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml └── split_by_batch.pylabels目录和images目录结构一一对应每个图像文件名对应的TXT标注文件必须同名。这个约定在后续训练时能省非常多时间。2. 数据采集与预处理从田间到训练集的必经之路2.1 采集设备与拍摄规范数据集的源头永远要比算法更值得投入。这套数据集的图像来源分两路一路是公开的PlantVillage等学术数据集中符合我们“真实田间”标准的图像另一路是我们自己在试验田和合作农场拍摄的实景图像。两条路都要经过严格筛选不是拿过来就能用。一手图像采集时我总结了三个关键控制点。第一拍摄设备以普通手机和入门级相机为主。为什么不用专业单反因为最终用户端的图像大概率就是手机拍的如果训练数据全是高清晰度、完美构图的专业图推理阶段碰到手机随手拍的图像就会崩。用“更差一点”的设备拍摄其实是在给模型做对抗训练。当然我也没有故意拍模糊只是不回避自然抖动和自动白平衡带来的轻微质感损失。第二拍摄姿态要“乱”。标准俯拍当然要有但实际应用中用户可能从侧面、斜上方、甚至逆光方向拍叶片。所以我要求采集人员每张叶片至少拍三个角度多叶重叠的场景更是额外多拍几张。逆光、阴影、露水、泥土背景这些“脏”场景均予以保留只有完全无法辨认叶脉纹理的图像才直接删除。第三拍摄时间分布要拉开。同一块田早上、中午、黄昏的光照颜色和阴影方向截然不同。病害斑点的表观颜色也会随着光线变化而变化。我刻意把拍摄时间均匀分布在上午、正午和傍晚三个时段避免模型只学会“某种特定光照下的病害长这样”。如果你赶时间只能拍一个时段也至少要保证图像里有大量阴影和反光差异否则模型的泛化能力会很差。2.2 图像清洗的四个检查项图像拍回来之后不能直接标注必须先过清洗流程。这一步很多人会偷懒但省掉它的代价极为昂贵——你可能花了三天时间标注了一大堆最终要扔掉的坏图浪费了时间还污染了模型。我的清洗脚本里固定做四项检查清晰度检查用Laplacian算子计算图像方差。方差低于设定阈值的图像判定为模糊直接剔除。至于阈值我是在一批图像上先人工看一遍把“看起来模糊但勉强能标”和“根本没法标”的图分开计算这两种图的方差分布取分界值作为阈值。不同相机拍出来的图像方差分布会差很多不建议直接照搬网上给的固定值。去重检查利用感知哈希算法计算图像之间的汉明距离距离小于5的图像视为重复。连拍是采集过程中最容易产生重复数据的动作连拍几乎一定会造成重复图像混入数据集而这种重复会导致训练集和验证集边界被无意中侵蚀。尺寸合规检查所有图像最终统一缩放到640x640或1280x1280具体取决于训练需求。清洗阶段先不缩放只标记。因为标注坐标需要归一化到原始分辨率过早缩放容易引入标注偏移。曝光检查利用直方图统计图像亮度均值。过曝和欠曝的图像如果不做处理就删掉导致数据集缺失大量低光照样本而这类样本恰恰是农业现场最常见的场景。正确的做法是把它们单独挑出来归入“低照度增强批次”在后面统一用图像增强手段去补偿。2.3 数据增强给模型“加训练量”前面提到4900张图对YOLO来说不算多数据增强是必须的。我的原则是“不改变病害本质特征的增强优先用强改变语义的增强慎用”。推荐从这几个增强组合入手水平/垂直翻转叶片病害没有明显的方向性翻转不会改变语义可以作为默认启用的增强。0到15度小角度旋转真实拍摄时叶片角度千变万化小角度旋转可以提升模型对姿态的鲁棒性但旋转超过30度会引入多余的图像边缘噪声建议谨慎。HSV通道微调亮度、对比度、饱和度的随机变化模拟不同天气、不同相机参数下的色彩差异幅度控制在±15%以内。Mosaic增强和MixUp增强YOLOv8官方训练配置里默认启用实测对提升模型的抗遮挡能力非常有效。Mosaic会把四张图拼成一张让模型不得不去学习小目标、遮挡目标间接提高了模型对复杂场景的鲁棒性。有一个增强我要提醒你别乱用——仿射变换里的大角度旋转叠加尺度缩放。叶片是柔性物体边缘会有不规则的弯曲如果你把整张图旋转90度再加150%缩放叶片形状会被扭曲到不自然模型学到的特征可能是扭曲后的纹理而不是真实的病害斑纹。我在调参过程中对比过小角度旋转HSV微调的组合比大角度旋转暴力缩放的组合在测试集上的mAP高了将近两个点。所以增强不是越猛越好贴近物理世界才是最好。3. 标注规范与质量控制3.1 标注规范框住什么、怎么框标注是这份数据集的核心也是最费时费力的环节。4900张图按每张平均1.8个目标框来算总框数接近9000个出错的代价极大。所以开工之前我专门写了一份标注规范全部团队按同一套标准执行。核心规则有这么几条目标框覆盖疾病的明显可见区域。如果一片叶子上有多个离散的病害斑块每个斑块独立成框而不是用一个大框把所有斑块包起来。这是因为单个框的定位有助于模型学习“病害局部的纹理特征”大框包含过多健康组织会干扰特征学习。肉眼难以判断是否属于目标的范围宁可不框不要硬框。比如叶片边缘颜色本来就偏黄和一个早期病害斑块肉眼分辨不出来就按其最可辨的核心区域来框如果连核心区域都不清晰那这张图放弃标注而不是让标注员去猜。当多个叶片重叠时每个可见叶片都单独标注但被遮挡超过50%的叶片不标。被挡住太多的叶片即便标了模型也学不到完整的特征反而会把“残影”学成病害特征。框必须紧贴目标边缘预留的边距不要超过目标宽度的2%。目标检测框不是画图不需要留白。此外我还固定了一个“类别争议”的处理流程任何人拿不准两个容易混淆的类别就拉一个“待确认”清单由有植保经验的同事集中复核。番茄早疫病和晚疫病的早期混淆就是这个流程处理的。3.2 标注工具选型工欲善其事必先利其器。数据集标注工具我用过好几款在这套数据集上最终留下的是X-AnyLabeling和Label Studio的组合。LabelImg是老牌工具界面简洁而且上手快但问题也明显功能太原始没有智能辅助没有自动保存提醒多人协作更是谈不上。如果你想快速完成几百张图的标注它够用但面对4900张的规模效率会让你怀疑人生。X-AnyLabeling是我目前的主力。它内置了YOLOv8等目标检测模型的推理接口可以先用预训练权重跑一遍自动标注然后人工修正。实测下来预标注能把每张图的标注时间从2分钟压缩到40秒左右而且人工只需要修正框的位置和类别标签精力集中在质量细节上。对于大叶片、轮廓清晰的目标预标注框偏差很小这是一个巨大的效率增益。Label Studio则用于后续的校验和二次审核。它有比较完善的多人协作和审核流可以看到每个标注任务的完成状态、被拒原因、修改记录。对团队协作来说很省心。具体的工作流是X-AnyLabeling做初标和人工修正导出为YOLO格式的TXT然后用Python脚本把TXT统一转换成Label Studio的JSON格式导入平台做抽查审核审核通过后再转回TXT。这套流程看起来绕了一圈但每一步的校验角色清晰多人协作时不至于出现“标注标准漂移”。3.3 双重检查与一致性标注完成后强制做两轮检查这是我和数据标注团队之间定的规矩任何人不能跳过。第一轮是完整性检查。用一个简单的Python脚本统计每个标注文件的行数对比对应的图像文件是否存在检查类别编号是否在合法范围内。这类检查能抓出漏标、错标、标签格式错误等低级问题。再进一步统计每个类别的标注框数量和面积分布如果某个类别的框面积明显偏小说明标注员可能只标了斑点的一部分需要抽查修正。第二轮是一致性检查。我随机抽取20%的标注结果由第二个人重新标注一遍比较两次标注框的IoU。如果IoU大于0.8视为标注一致小于0.6的进入人工复核。这个环节虽然费时但它确保了数据集的标注质量是有量化指标的而不是凭感觉说“差不多能行”。我用这套方法把标注的框级一致率从初始的76%提升到了92%。4. YOLO模型训练与关键参数配置4.1 目录组织与YAML配置数据准备好之后训练阶段首先要做的是把数据集的结构整理成YOLO能直接识别的格式。YOLOv8的Ultralytics框架要求图像和标注文件按images和labels两个目录分别存放每个目录下再分train和val子目录。测试集单独保留不在训练配置里引用只在最终评估脚本里面手动指定。对应的data.yaml文件内容如下# data.yaml path: /data/leaf_disease train: images/train val: images/val test: images/test names: 0: Apple_healthy 1: Apple_scab 2: Apple_rot 3: Grape_healthy 4: Grape_black_rot 5: Grape_esca 6: Tomato_healthy 7: Tomato_early_blight 8: Tomato_late_blight这里有个很容易踩的坑类别编号必须从0开始连续编号。YOLO标注文件中的class id是一个整数如果类别编号中间跳了一个模型训练时类别映射就会错位标注文件的类别序号和data.yaml里的names顺序不匹配会导致模型学完全错的目标。这种错误在训练时不会报任何异常只在最终混淆矩阵上暴露出来而且排查非常痛苦。所以写data.yaml的时候一定要逐行核对names顺序和标注txt里的class id保持一致。4.2 超参数推荐与调优思路模型结构方面我一开始在YOLOv8n和YOLOv8s之间犹豫。n参数少、速度快但作为一种轻量级检测头小目标病害斑点的定位精度会弱一些s参数多一倍精度有明显提升。考虑到叶片病害的早期斑点往往只有几十个像素大小最终选择YOLOv8s作为基线。如果你的设备资源极紧张n也能用就是要接受它容易漏检早期斑点的事实。最关键的训练参数我这边的推荐值如下参数推荐值说明imgsz640早期斑点若小于20像素可考虑1280epochs200配合Early Stopping无需死等batch16训练显存不够时就降到8区别不大lr00.01如果发散就降到0.005lrf0.01余弦退火最终学习率optimizerAdamW小数据集收敛比SGD稳定augmentTrue启动mosaic/hsv等内置增强patience30连续30轮没提升就停止训练时我不会傻等200个epoch。Ultralytics框架下开启Early Stoppingpatience设为30模型通常在120轮左右就能稳定收敛。看训练曲线注意一个点如果val_loss先降后升而train_loss一直在降这是典型的过拟合信号说明数据增强强度不够、模型容量过大或者数据量太少。遇到这种情况我会优先减少训练轮数、增强增强强度而不是换更大的模型因为农业数据集的扩充成本实在太高了。4.3 三个观察指标把关训练质量训练过程中我主要盯三个指标不看别的花哨图表。第一个是验证集mAP0.5。这个指标可以快速判断整体轮廓是否正常。叶片病害是“大目标小纹理”通常mAP0.5达到0.85以上模型才具备基本的可用性。如果卡在0.7附近上不去优先怀疑标注质量其次才是模型结构。第二个是mAP0.5:0.95。它反映的是模型定位精度的细腻程度。如果这个值和mAP0.5差距过大比如0.5 vs 0.35说明框的位置不够准病害识别大概是对的但边界框偏移严重。这时候可以在训练参数里把box_loss的权重稍微调高一点或者检查标注框的紧贴程度是否需要进一步严卡。第三个是每一类单独的AP。这比综合mAP重要得多。我一直认为综合mAP好看不算本事所有类别都拿得出手才算本事。如果某一类的AP明显低于平均值基本就是那类样本量不足或者类别间特征混淆。比如我早期发现Grape_esca的AP只有0.6排查后发现是标注时把叶脉的黄色条带纹误标成了轮斑病修正了约40个错误标注后该类别AP直接涨到了0.78。这个经验说明了数据问题永远比模型问题更值得优先排查。训练完成后用验证集跑一轮Confusion Matrix重点看哪些类别互相混淆。叶病检测中常见的混淆原因是“早疫病”和“晚疫病”的早期表现确实太像如果你做的是农户端诊断系统这两类搞混会让用药方案完全错掉。想彻底解决只能靠更多数据、更明确标注模型层面能做的有限。5. 实战中常见问题与排查技巧实录5.1 漏检多早期斑块面积小模型看不见我第一批模型跑出来后最头疼的问题是番茄早疫病的早期病斑漏检率特别高。原因很直接早期斑块只有十几像素YOLO在640分辨率下的最小检测单元其实是16x16像素比这更小的目标基本都会被当成背景。对策有三条一是提升输入分辨率到1280模型对小目标的感知能力立马上一个台阶代价是显存占用翻倍二是把病害的“初期状态”和“典型状态”作为同一个类别共同标注不要刻意区隔让模型学会从半透明的小斑块一路学到大型坏斑三是适当的裁剪增强对含小斑块的图像局部放大后再训练相当于在训练时帮模型“多看几遍”小目标。实测这三招组合使用早疫病小斑块的召回率从0.55提升到了0.78。5.2 误检背景模型把土壤和落叶当成病害另一个高频问题是模型在真实田间场景中频繁误检。一个让我挠头的case是模型把土壤颗粒识别成了Apple_rot因为数据集中那些带有深褐色坏死斑的苹果叶片和土壤颗粒在颜色纹理上高度相似。这就是典型的“数据没有覆盖到相似背景”问题。模型学到的可能不是“黑腐病的坏死纹理”而是“任何深褐色圆形区域”。解决方案是采集时特意增加了一批“背景与病害颜色相近但不属于病害”的图像比如布满褐色斑点的老化叶片、沾泥的叶片、枯黄落叶等全部标注成背景类。有人会问YOLO不是不接受背景类标注吗其实你可以不标任何框让它们作为负样本图像参与训练。YOLO在训练时会对无目标框的图像下发“此处无目标”的梯度信息模型会学到这些东西不该被检测。加了200张纯背景负样本之后田间误检率下降了约30%。5.3 类别不平衡有的病害样本多有的样本少九大类别的样本量做不到完全均等。苹果黑星病的图像实际拍摄容易样本量最多而番茄晚疫病早期样本需要特定时间窗口去拍数量明显不足。这导致模型对黑星病的AP很高但晚疫病的AP一直拖后腿。处理类别不平衡我试过三种方法第一种是过采样把样本少的类别在训练时重复输出让模型看到它的频率提高第二种是类别加权在损失函数里人工提高小样本类的权重第三种是生成合成样本用拼接增强的方式把小样本类的病斑贴到健康叶片背景上。实际效果最好的反而是最简单的过采样。YOLO的损失函数对每个目标框天然会分配梯度重复输出的框会让模型对这类目标的敏感度提升。当然这是在小样本数量不太离谱的前提下如果某各类只有几十张那再多的过采样也无济于事必须回到数据采集阶段补样本。5.4 部署侧的精度与速度平衡训练完模型之后大多数人会直接在服务器上跑推理但智慧农业的真实部署场景往往是边缘设备。我是用TensorRT导出的FP16模型放在Jetson Orin Nano上实测640分辨率的推理速度大概在35到45毫秒每帧能撑住实时检测但做多路视频流时CPU占用会比较高。如果你追求更高帧率可以从YOLOv8s切换到YOLOv8n然后做进一步蒸馏量化。我却建议你先冷静想一下业务到底需要多高的帧率——叶片病害检测不是自动驾驶对延迟的要求没那么苛刻30毫秒和60毫秒的区别农户完全感受不到M点精度带来的收益反而更实在。把资源花在提升准确率上比花在压榨那20毫秒的延迟上划算得多。最后再分享一个我做这套数据及后续扩展时的心得数据集永远是农业AI项目里最值钱的部分模型结构过两年会换更先进的但一份标注规范、覆盖全面、贴近场景的数据可以反复滋养你未来所有的模型迭代。如果你现在手头只有一两百张图别急着上模型先把采集规范和标注规范吃透把数据补到几千张再动手这个前期投入会在后续模型的每一次迭代里加倍还给你。

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

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

免费获取报价 →
↑