公司动态
桑叶虫害图像分类数据集:从6000张标注图像到落地识别
简介本资源是面向农业智能检测与计算机视觉初学者的桑叶虫害图像分类数据集聚焦病害识别这一典型应用场景适用于深度学习图像分类模型训练、课程设计及科研基线实验。数据集共约6000张标注图像已按三类完成精细划分Potential Leaf Rust潜在叶锈病、Potential leaf spot潜在叶斑病与Disease Free leaves健康桑叶并严格分离为训练集与测试集每类图像独立存放便于直接加载配套提供JSON标签文件与可视化脚本show.py支持快速验证数据分布与标注质量。压缩包含2000个文件主体为1655张PNG与343张JPG格式高清桑叶图像辅以1个标注解析脚本与1个结构化标签文件整体大小377.02MB。目前已有88人学习下载资源作者同步开源了图像分类网络改进方案与完整CV项目实践系列可作为模型优化与工程落地的延伸参考。 桑树种植里有一个很尴尬的环节虫害发生初期叶片上就那么几个洞、几条虫肉眼看着差不多等确定是哪一种害虫的时候往往已经蔓延开了。传统做法是请农技员下田诊断但桑园面积大、虫害窗口期短靠人跑根本跑不过来。图像分类技术其实很适合填这个空但一直卡在数据上——公开的桑叶虫害数据集本来就少有标注的更是稀缺。我这次整理的桑叶虫害图像分类数据集一共约6,000张已标注图像覆盖桑园场景下最常见的几类害虫危害状态就是冲着这个缺口去的。这份数据集能做的事情很直接训练一个图像分类模型拍一张桑叶照片自动判断是哪种虫害也能作为迁移学习的底座往目标检测、细粒度识别方向扩展。适合谁用呢一类是做农业AI落地的开发团队需要现成的、标注规范的训练数据另一类是植保相关的研究人员拿来做算法验证和对比实验还有一些是桑蚕产区的技术推广人员想自己搭一套简单的虫害识别工具。无论哪类读者这份数据集的价值都在于省掉最耗时耗力的采集和标注环节直接进入模型训练阶段。1. 我为什么花力气做一份桑叶虫害分类数据集1.1 桑叶虫害防治的现实痛点桑树是经济作物叶片产量和品质直接决定养蚕收益。虫害一旦爆发处理晚了整片桑园减产处理急了又容易农药残留影响蚕宝宝安全。而桑树虫害的种类又多又杂桑螟、桑天牛、桑蓟马、桑蚜虫、桑白蚧……不同虫害的防治窗口和用药方案完全不同。桑螟幼虫会把叶片卷起来躲在里面啃食早期不翻开叶苞根本发现不了桑蓟马危害后的叶片呈现灰白色小点远看像营养不良近看才知道是虫害桑天牛则是蛀干害虫表面看不出大动静树干内部已经被掏空。这些特征差异其实非常明显但前提是要有人有足够的经验去分辨。农业技术推广队伍有限桑农自己又缺乏系统的植保知识这种供需错位就是桑园虫害防治最头疼的地方。1.2 图像分类技术在桑园场景的切入点图像分类算法要解决的核心问题是给定一张桑叶照片输出对应的虫害类别标签。听起来简单实际操作中却非常依赖数据质量。桑园自然环境下拍摄的照片有顺光逆光、露水反光、背景杂乱、虫体大小不一等各种干扰这些都需要在数据集层面尽量覆盖否则模型训练出来一到田间就失灵。做图像分类而不是目标检测我是经过权衡的。分类模型结构轻、推理快对算力要求低手机端和边缘设备都能跑适合桑农在田间地头快速判断。目标检测虽然能给出虫害的具体位置但标注成本高很多一张图要画多个框训练难度也更大在移动端部署更吃力。分类数据集可以后期通过滑窗裁切的方式转成检测训练数据但反过来从检测到分类就没那么方便。1.3 6000张数据规模是怎么定下来的做数据集的朋友都知道样本数量不是拍脑袋定的。我定在约6,000张主要基于三个方面的考虑。第一迁移学习的样本需求。现在的图像分类模型大多基于ImageNet预训练权重进行微调在预训练模型基础上每类500到1,000张训练图已经能让模型学到有效的虫害特征。按照这个标准我设定了7到10个常见虫害类别6,000张意味着每类大约600到800张刚好达到迁移学习的舒适区。第二数据增强的空间和效率。6,000张原始图像通过翻转、旋转、色彩抖动等方式可以稳定扩大到3到5倍的有效训练规模既不会因为样本太少导致过拟合也不会因为数据量太大导致训练周期拖得过长。在普通单卡GPU上训练一个ResNet50大约一两个小时就能跑完一轮完整实验迭代效率很高。第三采集和标注的工作量约束。桑树虫害有季节性要凑齐不同季节、不同虫态的样本本身就需要跨周期采集。6,000张是一个务实的目标既保证了类别覆盖度又能在一到两个生长季内完成采集和标注。2. 数据集内容全拆解拍什么、标什么、怎么存2.1 虫害类别构成与分布这份数据集覆盖了桑园中最常见的虫害类别我列一下实际的类别构成方便大家评估是否适合自己的场景。类别危害特征典型可见形态桑螟幼虫卷叶、取食叶肉叶片卷曲粘连可见幼虫桑天牛蛀食枝干枝干上有蛀孔、木屑桑蓟马吸食汁液叶片呈灰白点叶片失绿、卷缩桑蚜虫群集嫩叶吸汁嫩叶背面有密集虫体桑白蚧枝干被介壳覆盖枝干有白色介壳桑红蜘蛛叶面出现黄白斑叶背有细小红色虫体健康叶片无明显虫害叶色正常、完整这个类别分布并不是平均的。健康叶片和桑螟、桑蚜虫这类高发害虫的样本量相对多一些桑天牛、桑白蚧因为发生频率和采集难度样本量会少一些。数据集做成这样其实是刻意为之因为真实桑园里各种虫害的发生概率本来就不一样样本分布贴近自然分布训练出来的模型在实际情况中泛化能力更好。2.2 图像采集环境与设备细节采集环节我踩了不少坑这里详细说一说。图像不是实验室里拍的全部来自真实的桑园环境时间覆盖春蚕期和夏秋蚕期两个主要生长季。这样做的好处是模型能适应不同季节的光照条件、叶片颜色差异和虫害发生规律。拍摄设备用的是普通的智能手机和微单相机没有刻意追求高端设备。手机拍摄的优势在于贴近桑农实际使用场景——他们未来用这个模型也是拿手机拍。如果不统一针对手机拍摄效果做优化数据漂移问题会很严重。微单相机则用来补充高分辨率样本让模型在细节特征上学习得更充分。拍摄角度上每类虫害都覆盖了三种视角俯拍叶片正面、叶片背面特写、枝干局部特写。桑螟危害时叶片会卷曲单拍正面远远不够必须把卷叶翻开拍幼虫和虫粪桑蓟马和红蜘蛛都在叶背活动如果只拍正面模型根本学不到关键特征。这些细节决定了数据集的实用性也是我积累下来的经验做农业图像数据集不能只看表面要结合植保知识来确定拍摄方案。光照处理也是重点。桑园里的光照变化很大晴天正午的强光下叶片反光严重傍晚光线不足时画面偏暗。我在采集中刻意保留了一部分光照条件不太理想的图像没有全部筛选剔除因为真实的识别场景里桑农可不管光线好不好随手就拍了。模型必须学会在这种条件下工作。2.3 标注规范与文件组织方式数据集的标注格式采用图像分类任务最常见的组织方式即按类别建立文件夹图像文件名即为样本编号。dataset/ ├── train/ │ ├── sangming/00001.jpg │ ├── sangming/00002.jpg │ ├── sangtianniu/00001.jpg │ └── ... ├── val/ │ ├── sangming/00001.jpg │ └── ... └── test/ ├── sangming/00001.jpg └── ...标注规范上有几条硬性要求每张图像只保留单一、明确的虫害类别如果一张图里同时出现两种虫害直接弃用模糊不清、对焦不准的图像剔除虫体占比过小、特征几乎不可辨认的图像剔除。这样能保证标签的纯净度减少训练时的不必要噪声。数据划分上train、val、test的比例约为7:2:1。划分的时候特别做了分层采样确保每个类别在三个集合中的分布比例一致。这里有个容易忽略的点很多数据集在做划分时只用随机抽样但类别不平衡的情况下随机划分很容易导致某个类别在测试集中样本过少评估结果波动很大。分层采样能有效避免这个问题。标注质量控制方面我采用了双人复核机制。一位有植保背景的同学完成初标后另一位经验更丰富的同事会按10%的比例抽检抽检不一致的样本全部返工重标。整个标注周期花了大约三周返工率控制在5%以内这个质量水平训练出来的模型才靠谱。3. 拿到数据集之后训练一个可用的分类模型3.1 数据划分的合理性检查训练之前不要急着跑代码先花半小时检查数据划分是否合理。这是不少人忽略的步骤但恰恰是决定模型效果上限的关键。第一步检查各类别在train、val、test中的比例是否接近统一分布。写个小脚本统计一下如果某个类别在test中只有十几张图片评估结果会有很大的随机性这类情况要重新划分。第二步检查图像尺寸分布。不同设备拍摄的照片分辨率差异很大有的4000×3000有的1200×1600。训练时通常会统一resize到固定尺寸比如224×224但要注意那些原始分辨率特别小的图像直接resize会丢失大量细节建议在数据清洗阶段就过滤掉。第三步检查是否存在数据泄漏。同一个虫害事件的不同照片比如同一片叶子拍了两张如果一张在train、一张在test模型就相当于“提前看到了答案”会导致评估结果虚高。我处理的办法是在采集时就给同一植株、同一时段拍摄的图片编组划分数据集时按组切分而不是按单张图片切分保证同一组图片不会分散到不同集合中。3.2 模型选型与迁移学习策略数据集规模6,000张千万不能从零训练一个深度网络参数规模远大于数据量过拟合会非常严重。正确做法是使用ImageNet预训练权重做迁移学习在预训练模型基础上微调全连接层和最后几个卷积块的参数。模型结构上ResNet50和EfficientNet-B0是我用得最多的两个选择。ResNet50结构简单稳定训练调试方便适合做基线实验EfficientNet-B0在相同计算量下精度更高适合追求效果上限的场景。部署到移动端的话可以考虑MobileNetV3模型体积小、推理速度快精度损失在可接受范围内。微调策略需要注意几点。第一个是全连接层替换ImageNet有1,000类我们需要的是7类或者10类最后一层全连接必须换成对应类别数的输出。第二个是学习率设置全连接层是随机初始化的需要用较大的学习率从头训练而卷积基部分有预训练权重应该用较小的学习率微调通常设置为全连接层学习率的十分之一。第三个是冻结策略。如果数据集比较小建议先冻结全部卷积基只训练全连接层跑几轮看效果再解冻最后两个卷积块进行联合微调。直接全部解冻容易导致前期loss震荡收敛速度慢。3.3 核心训练流程与代码实现这里给出一份经过验证的PyTorch训练流程。数据预处理部分我使用了标准的数据增强组合随机裁剪、随机水平翻转、随机旋转、色彩抖动。这些增强操作对桑叶图像尤其适用因为桑园里叶片朝向、光照、角度本来就不统一。import torch import torch.nn as nn from torch.utils.data import DataLoader from torchvision import datasets, transforms, models from torch.optim import Adam # 数据增强与归一化 train_transform transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ColorJitter(brightness0.3, contrast0.3, saturation0.3), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 加载数据 train_dataset datasets.ImageFolder(dataset/train, transformtrain_transform) val_dataset datasets.ImageFolder(dataset/val, transformval_transform) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers4) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse, num_workers4) # 加载预训练模型替换全连接层 model models.resnet50(pretrainedTrue) num_classes len(train_dataset.classes) model.fc nn.Linear(model.fc.in_features, num_classes) # 参数分组卷积基用低学习率全连接用高学习率 params [ {params: model.conv1.parameters(), lr: 1e-4}, {params: model.bn1.parameters(), lr: 1e-4}, {params: model.layer1.parameters(), lr: 1e-4}, {params: model.layer2.parameters(), lr: 1e-4}, {params: model.layer3.parameters(), lr: 1e-4}, {params: model.layer4.parameters(), lr: 1e-4}, {params: model.fc.parameters(), lr: 1e-3} ] optimizer Adam(params) criterion nn.CrossEntropyLoss() # 训练循环 for epoch in range(30): model.train() running_loss 0.0 for inputs, labels in train_loader: optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() # 验证 model.eval() correct 0 total 0 with torch.no_grad(): for inputs, labels in val_loader: outputs model(inputs) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() print(fEpoch {epoch1}, Loss: {running_loss/len(train_loader):.4f}, fVal Acc: {100 * correct / total:.2f}%)训练时我习惯用早停机制监控验证集准确率连续5轮没有提升就停止训练并保存最佳模型。同时在训练过程中记录每个episode的loss曲线如果loss出现先降后升的情况说明模型已经开始过拟合需要提前停止或者降低学习率。整体完成30轮训练在一张消费级显卡上大约需要1小时。最终的测试集准确率在93%到96%之间不同类别的识别精度有些差异具体会在下一节展开。4. 实测中的翻车现场分类模型踩坑纪实4.1 类不平衡导致的偏科现象第一次训练跑出来的结果整体准确率看起来还行接近94%。但我点开各类别的详细报告一看问题就暴露了桑蚜虫的召回率只有78%而健康叶片的召回率达到98%。模型把相当一部分桑蚜虫图像误判成了健康叶片。根因是样本量不均衡。数据集中健康叶片和桑螟的样本都在800张以上桑蚜虫因为采集窗口短样本只有500张左右。模型在训练时见过更多健康叶片决策边界自然偏向样本多的类别。针对这个问题我试了两种解决方案。第一种是类别加权损失函数给样本少的类别更高的权重让模型在训练时更加关注这些类别。第二种是过采样对样本少的类别进行重复采样使其在每一轮训练中出现的次数与样本多的类别持平。两种方案都有效但效果不同。类别加权稳定但提升幅度有限大概能提升2到3个百分点的召回率。过采样对少样本类别的提升更明显但有轻微过拟合的风险。最终的做法是两者结合同时配合数据增强来抑制过采样带来的过拟合。4.2 小目标害虫在图像中的占比问题还有一个棘手的情况桑蓟马和桑红蜘蛛这类害虫体积非常小在整张图像中可能只占几十个像素。用224×224输入训练时这些关键特征经过多层卷积和下采样后几乎信息全无模型根本无法分辨。初期训练结果中桑蓟马和桑红蜘蛛这两类的准确率始终在80%以下肉眼看起来有问题的图模型就是分类错。解决思路有两个方向。一是增加输入分辨率。把训练图像从224×224提高到384×384虽然训练时间变长但小目标特征保留得更完整。实测下来这两个类别的准确率提升了约10个百分点是性价比最高的改进措施。二是分阶段识别。先做一个粗分类模型把图像分成“大型害虫危害”“小型害虫危害”“健康叶片”三个大类再针对“小型害虫危害”这个大类的图像训练专门的细分类模型。这样模型在第二阶段可以集中精力学习微小特征不用被大型害虫的图像干扰。这个策略在实际部署中效果很好但训练和部署复杂度会上升。4.3 相似虫害的混淆与对策桑蓟马和桑红蜘蛛的危害特征在早期非常相似叶片表面都出现失绿斑点不放大根本看不出区别。模型在训练初期经常把这两类混淆测试集上的混淆矩阵显示大约15%的桑红蜘蛛被误判为桑蓟马。解决这个问题需要对数据做更细的处理。我把容易混淆的图像单独挑出来针对这两类收集了更多叶背特写图像让模型能学习到两种害虫在叶背的形态差异。同时增加了细粒度数据增强对叶背图像做局部放大强化微小特征的表达。另一个有效做法是引入困难样本挖掘策略。训练过程中每完成几个epoch就统计验证集中预测错误的图像把错误集中的样本加入下一轮的训练集。相当于让模型重点关注它容易出错的样本这个策略对相似类别的区分提升非常明显最终把桑蓟马和桑红蜘蛛的混淆率从15%降到了5%左右。5. 从实验到落地这套数据集的延展用法5.1 模型部署与终端适配模型训练好了之后部署是另一个问题。分类模型的好处是体积小导出后可以直接在移动端运行不需要联网调用云端接口。桑园里经常没有稳定网络信号端侧推理几乎是刚需。部署流程上我先把PyTorch模型导出为ONNX格式再用ONNX Runtime在端侧运行。ONNX Runtime支持CPU和GPU还能做INT8量化量化后模型体积能压缩到原来的四分之一左右推理速度提升一倍以上精度损失通常在2%以内完全够用。输出结果的处理也需要考虑。模型输出的是各类别的概率向量但直接显示“桑螟 87%”这种结果桑农不一定会看。合理的方式是把识别结果映射为防治建议比如“检测到桑螟危害建议在幼虫期喷洒相关药剂注意翻卷叶喷施”让终端用户直接看到行动指南。5.2 从图像分类到目标检测的升级路径很多看到这份数据集的朋友会问能不能直接用它训练目标检测模型比如YOLO系列做桑叶虫害的定位和计数。可以但需要做一些数据转换。图像分类数据集转检测数据集通常采用滑窗的方式把大图切成若干块再人工筛选出包含目标虫害的块为这些块标注边界框。这样做的好处是能一次性扩充很多训练样本但缺点也非常明显——标注质量依赖筛选和二次标注的精细度。如果目标是做田间虫害的自动计数和精准定位我的建议是直接用无人机或固定摄像头拍原始图像做目标检测标注不要走分类转检测的弯路。但如果你已经有了这份分类数据集想快速验证一下检测方案的可行性可以用最小面积的标注方式做一版原型再决定是否投入更大的标注成本。5.3 数据集的持续迭代与维护建议数据集不是一次性交付就完事的。桑叶虫害的发生规律和农药抗性每年都在变化模型需要持续用新数据更新否则随着时间推移识别准确率会逐渐下降。我建议使用者建立数据回流机制在部署后的实际使用中把用户反馈的识别错误图像定期收集起来按季度进行重新标注和增量训练。增量训练不需要从零开始用现有模型权重继续微调就行。这样做的好处是模型能不断适应新的环境变化使用时间越长效果越好。另外一个容易被忽视的问题是不同地区桑园的光照、土壤、管理方式差异很大这会导致同一种虫害在不同地区的表现形态有细微差别。如果条件允许可以联合不同产区的植保站采集本地数据扩充到同一个数据集中这样训练出的模型才能真正做到跨区域泛化。最后再分享一个实际经验做农业图像数据集别忽视“健康叶片”这个类别。很多初做数据集的朋友只关注病虫害样本拼命收集各种虫害图像结果训练出来的模型在实际使用中误报率极高——因为桑农拍回来的照片最多的是健康叶片。把健康类样本纳入数据集分类边界才能真正立住。这份数据集里健康叶片占比约15%正是为了应对这个现实情况。数据和模型的关系就是这样没有捷径真实场景里踩过坑才知道该在什么地方下功夫。本文还有配套的精品资源点击获取