ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

30种水果叶片病害YOLO数据集:从标签检查到训练避坑全指南

30种水果叶片病害YOLO数据集:从标签检查到训练避坑全指南 简介用于水果与植物叶片病害缺陷检测的YOLO数据集覆盖30个类别包含玉米叶枯病、苹果锈叶、番茄霉叶等常见病害也涵盖苹果、玉米、番茄、马铃薯、大豆、樱桃等多种作物并已按YOLOv5目录结构划分为训练集与验证集可直接投入目标检测模型训练。图像为600-2000分辨率的大尺寸RGB图片每张均含完整边界框标注标注采用YOLO相对坐标格式训练集2240张、验证集311张适合入门至进阶的检测项目使用。资源包共2000个文件以1999个txt标签文件含30个类别class文本为主附1个Python可视化脚本可随机读取图片并绘制边界框保存结果无需修改即可运行整体压缩包约422.01MB便于批量下载与解压部署。已有346人浏览学习对于需要快速获取带标签植物病害数据的开发者这份资源能省去采集与标注的重复劳动。1. 30种水果叶片病害缺陷数据集为什么拿到手就能直接训做农业视觉检测的工程师都体会过找一个标注干净、类别齐全的水果和植物叶片病害数据集比训练模型本身更费时间。这份资源把“数据准备”这一步做完了——30种水果、植物叶片病害缺陷检测包含划分好的数据集、class类别文件和一份数据可视化脚本。它最大的特点是“开箱即用”解压后目录就是YOLO标准布局train/val/test已经分好标签是txt格式的归一化坐标class文件直接对应训练要用的类别清单。价值不在算法而在时间——省掉清洗标签、对齐目录、调类别序号的那几天。适合刚接触检测想练手的新手也适合要做农业检测baseline的工程师。2. 标签体系与class文件先看清30类是什么再动手拿到数据集第一步不是训练是打开class.txt和几个标签文件确认三件事类别数、类别顺序、坐标格式。这一步做错了后面训练出来的模型全废。因为再好的可视化脚本也没法替你判断“类别和坐标有没有对齐”。2.1 从class.txt读类别清单不靠猜class.txt是文本文件一行一个类别名顺序就是标签文件里class_id的顺序。这份数据集涉及30类文件头大概长这样示意以你实际拿到的class.txt为准# 给类别清单加上行号行号减1就是标签文件里的class_id head -n 30 class.txt | nl输出形式1 apple_healthy 2 apple_scab 3 grape_black_rot 4 grape_esca 5 tomato_early_blight ... 30 corn_gray_leaf_spot逻辑说明nl给每一行编号编号减1就是label文件中class_id。比如apple_scab是第2行它对应的class_id就是1。很多人的坑就出在这一步——class文件里的顺序和训练用的dataset.yaml不一致模型把苹果黑星病当成苹果健康在学你还浑然不觉。所以第一步不是看准确率是先确认这个清单的顺序你能背下来。这类数据集的类别覆盖设计通常是水果苹果、葡萄、番茄、草莓、柑橘、桃、香蕉的果实缺陷和叶部病害混在一起再加大田作物玉米、水稻、小麦的叶片病斑凑出30个类。类似烟草病虫害数据集yolo的做法类别设计往往也是“作物名病害名”的命名方式方便训练完直接读混淆矩阵定位问题。来源类别示例典型病斑特征苹果apple_scab / apple_healthy叶面黑褐色圆形病斑边缘清晰葡萄grape_black_rot / grape_esca叶片边缘焦枯、紫褐色斑块番茄tomato_early_blight / tomato_healthy同心轮纹状坏死斑老叶先发柑橘citrus_canker / citrus_greening黄色晕圈凸起病斑叶背更明显大田作物corn_gray_leaf_spot / wheat_leaf_rust条状病斑、粉状孢子堆这张表只是常见类别形态的参考目的是让你对“30类长什么样”有个预期。实际类别名、病斑外观以包内class.txt和可视化脚本的输出为准不要拿这张表去对号入座。2.2 YOLO标签格式归一化坐标的边界坑YOLO格式标签是一个文本文件每行代表一个目标框五个字段class_id cx cy w h。前两段是中心点坐标后两段是宽高全都是相对图像的归一化值取值范围0到1。随便打开一个标签文件看看# 查看训练集某张图的标签文件名与图像jpg同名 cat datasets/train/labels/apple_scab_014.txt输出1 0.4832 0.5114 0.1267 0.1891 1 0.7215 0.8233 0.0854 0.1146逻辑说明第一列的1就是class.txt第2行对应的apple_scab后面4个小数全部是除以图像宽高后的归一化值。如果标签里的坐标出现大于1.0或者负数说明标注工具或转换脚本出了问题图像和标签没有对齐。这种问题训练时不会报错但loss会很难看val的mAP会一直上不去。参数说明实际训练时imgsz不一定等于原图尺寸YOLO在加载时会自动做letterbox所以归一化坐标的好处是分辨率随便改。但要注意不要手工把归一化坐标去乘不同的宽高后再存回txt。常见误用是“为了省显存先resize图片再改标签”如果宽高比不保持一致框就整体漂移。正确做法是保留原图原标签训练时靠imgsz参数做输入缩放。2.3 不看类别分布就训练等于盲跑30类里面样本数一定不是均匀的。叶部病害本身有季节性某个冷门类别可能只有一两百个框而apple_healthy这类背景类可能近千个框。开训前我习惯先做一次类别统计而不是等训练完看mAP才意识到某类彻底没学出来# 统计训练集标签里每个class_id的标注框数量找出尾部类 import os from collections import Counter label_dir datasets/train/labels counter Counter() for fname in os.listdir(label_dir): with open(os.path.join(label_dir, fname), r, encodingutf-8) as f: for line in f: # 每行第一个字段是class_id直接按int统计 counter[int(line.split()[0])] 1 for cls_id, cnt in sorted(counter.items()): print(fclass {cls_id}: {cnt} boxes)逻辑说明统计的是标注框数量而不是图像数量因为一张图里可能同时有多个病斑被多次框选框数才代表模型能看到多少正样本。如果发现grape_esca这类只有一两百个框后面模型对该类的召回率一定低——这是数据决定的不是模型决定的调参救不回来。参数与调整建议框数最少的几个类优先考虑“只对该类做离线增强”而不是全局改mosaic概率第四章会写具体怎么把增强限定在某个class_id上。另外统计结果也要和class.txt行号对照看class_id有没有断档——有些数据包删过类但没更新标签断档会让dataset.yaml里names列表长度和nc对不上。3. 数据可视化脚本先跑一遍确认图像和标签对得上很多人拿到数据包直接写训练命令翻车之后才回头查标签。我的习惯是解压后第一件事先跑一遍包里的可视化脚本把标注框画在图上扫一眼。这一步能拦下至少一半的“训练不收敛”问题。3.1 目录结构为什么“划分好的数据集”值钱常规YOLO数据集的目录是这样datasets/ ├── class.txt ├── data_visualize.py ├── images/ │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 └── labels/ ├── train/ # 与images/train一一对应的标签txt ├── val/ └── test/已划分好的含义是train/val/test三份数据在图像层面不重复图片文件名不会跨越集合重复labels目录严格镜像images目录。这比很多“只给一个总目录让你自己按8:1:1随机分”的数据包省心得多。按随机比例划分时同一张图的增强副本往往同时落到train和val验证集被污染指标虚高上线就露馅。集合文件夹作用训练集images/train模型学习标注框规律验证集images/val每个epoch后评估选best.pt测试集images/test训练结束后做最终盲测不参与选权如果你后续自己爬数据扩类也建议延用这套目录结构别新增一个“extra”文件夹往里面乱丢YOLO的train命令只认yaml里指定的路径目录不规范是训练报错的高发原因。3.2 可视化脚本跑起来参数与输出包内的data_visualize.py一般会接收数据根目录、输出目录、抽样数量三个参数典型命令# 从项目根目录执行抽查200张图生成带框预览 python data_visualize.py \ --data_root ./datasets \ --save_dir ./visualize_output \ --num_imgs 200 \ --show_label true逻辑说明脚本做的事是“读图片→解析同名txt→画矩形框→把类别名写到框上方→另存为带框的图”。200只是抽样上限如果目录里不足200张就全量画。运行完去visualize_output里翻图重点看有没有“框和病斑明显错位”、“同一张图两个框完全覆盖”、“某张图只有一个类别但图像里明显有两个病斑”这三种情况。参数说明--show_label true控制是否把类别名画在框顶建议保持true不然你没法肉眼核对类别--num_imgs越大检查越全面但肉眼检查时间也长。我一般先用200张扫一遍没有异常再全量出图全量出图不细看只看生成文件数量是否异常比如某类图像一张框都没画出来说明该类标签空了。3.3 可视化结果的三条判断标准打开visualize_output后我按三个标准判断这份数据能不能训。第一框应该紧贴病斑边缘而不是包含整个叶片。很多数据集的标注习惯是用大框包住整片叶子这种标签训练出来的模型“看到叶子就报警”换到真实场景误检率会高得离谱。第二同一个类别名的框目标外观要一致。apple_scab的框不应该有些在叶片、有些在果实上除非数据集设计时明确把果实和叶片分开标。第三随机翻看十几张图确认没有“图像上有明显病斑但标签为空”的情况——漏标比错标更隐蔽模型会把漏标区域当难例拖慢收敛。常见误用提醒可视化脚本不等于数据增强预览别指望它帮你提前看到训练中的mosaic效果它只负责验证“原图—标签”的对应关系。要看增强后的效果得用YOLO的plot训练日志功能不是这份脚本的职责。4. 按YOLO流程训练从yaml到命令行跑通自己的数据数据确认没问题接下来才是训练。以YOLOv8为例整套流程只需要一个yaml、一行训练命令。但“一行命令”的前提是yaml写对、权重选对、超参数没乱调。4.1 dataset.yamlnames顺序一个字符都不能错YOLO的yaml文件核心就5个字段path、train、val、test、nc、names。names必须是列表顺序必须和class.txt一致这是最容易出错也最不值得出错的地方。为了避免手抄出错我每次都是从class.txt生成yaml不手动写# 从class.txt生成dataset.yamlnames顺序与class文件严格一致 import os with open(class.txt, r, encodingutf-8) as f: names [line.strip() for line in f if line.strip()] with open(dataset.yaml, w, encodingutf-8) as f: f.write(fpath: {os.path.abspath(datasets)}\n) f.write(train: images/train\n) f.write(val: images/val\n) f.write(test: images/test\n) f.write(fnc: {len(names)}\n) f.write(fnames: {names}\n) print(len(names), classes written)逻辑说明直接把class.txt末尾的空行滤掉后写入names杜绝“手打类别名打错一个字母”的翻车。nc用长度自动计算不手填如果class.txt和标签实际class_id对不上下一步训练会报错这时候回头查第二章的统计脚本别硬改yaml里的nc数字去“骗”过校验。参数说明path那行必须是数据集的绝对路径或者相对于训练命令执行目录的路径。YOLO会把train/val拼接在path后面常见误用是写成train: ./datasets/images/train如果path又指向datasets实际路径就变成datasets/datasets/images/train直接报目录不存在。所以建议path用绝对路径train/val只写相对path的子路径。注意names里的逗号、引号、空格YOLO的yaml解析是能处理的但别在这个列表里混入中文标点解析器会直接挂。4.2 训练命令与怎么看训练日志环境配置按常规流程来conda建一个干净环境pip install ultralytics依赖会自动带上。然后从项目根目录启动训练# 在项目根目录执行数据路径全部走dataset.yaml yolo train \ datadataset.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0逻辑说明train是YOLO CLI的子命令data指向生成的yamlmodel指定预训练权重epochs是迭代轮数imgsz是输入分辨率batch根据显存调整。训练开始后日志会按epoch输出box_loss、cls_loss、dfl_loss这几个损失值前几轮快速下降是正常的如果从头到尾几乎不变说明标签或数据加载有问题回第三章可视化脚本里查别在参数上浪费时间。参数说明30类数据集我的常用取值参数我的建议值选择理由epochs100起30类较复杂一般70轮才过拟合100轮够选best权重imgsz640病斑多数是小目标太高显存压力大太低召回率崩batch168G显存/ 3212G太小BN不稳定loss波动大尾部类更难学lr00.01默认即可v8自带warmup和余弦退火前期不要手改mosaic1.0默认最后10轮自动关闭小病斑目标多mosaic能缓解样本不足损失函数那几个超参数box、cls、dfl的比例权重默认值在多数农业场景够用不建议一上来就调。我见过太多人在这类项目里先盯着loss调参数不如先把数据搞干净——loss是结果不是原因。4.3 预训练权重怎么选n/s/m还是从头训COCO预训练权重是这份资源能快速出结果的关键。YOLO系列官方发布页会有yolov8n.pt、yolov8s.pt、yolov8m.pt这类文件n是nano最小模型m是中等模型。农业病斑检测我的建议是显存8G用n或s显存12G以上直接m先跑通再考虑换大模型。m模型的mAP上限更高但训练时间约是s的2到3倍n模型适合快速验证流程不适合作为项目交付模型。不要从零训练——也就是说别不指定.pt权重文件直接给模型结构开训。农业数据集的量级从零训收敛慢而且精度大概率不如迁移学习。我在这里的固定做法是先用n跑一遍确认整个流程和数据没问题再用m或更大的权重做正式训练。两次训练用同一份dataset.yaml只换model字段这样第一次翻车成本最低。5. 避坑排查30类数据的五个翻车现场农业病害数据集训练翻车绝大多数不是模型问题是数据问题。我按踩过的坑从高到低列5条每条都是“现象→原因→解决”你也可以当成一份排查手册用。5.1 类别索引错位训练日志正常mAP卡死在0.1以下现象训练日志正常打印loss也在降但val的mAP50始终卡在0.1以下可视化结果里框全部画在错误物体上。原因class_id断档或错位。最常见的是class.txt被人为改了顺序而labels里还是旧的id另一种是删过类别但没删对应标签导致某几类在数据里消失names和实际对不上。解决重跑第二章的统计脚本把统计到的class_id集合与range(nc)逐一比对缺了就补多了就查哪个txt里出现了不该出现的id再用可视化脚本把错位类别逐类画框确认。这一步花半小时比训三天发现白训划算。5.2 训练中后段loss出现NaN不是模型问题是数据里混了脏文件现象epoch跑到六七十轮日志里box_loss突然变成nan之后所有指标全部失效只能重来。原因batch太小加上lr偏大BN在训练早期爆炸另一类更隐蔽——数据包里混入损坏图片0字节jpg、截断的PNG加载器读不出内容前向计算得到非法值。解决训练前先跑一遍图片格式检查遍历images/train统计文件大小0字节直接删掉并同步删对应标签再把batch提高到至少16v8默认会开AMP混合精度如果自己关了重新打开。5.3 val指标虚高现场一测全是误检现象val的mAP50到了0.9以上模型表现非常漂亮但拿手机去果园拍几张真实照片一测满屏误检框。原因划分数据时按文件随机抽没按物品隔离或者原始数据里就包含同一目标的不同裁剪、不同光照副本随机划分把相似副本分进了train和val模型在验证集上看到的几乎还是训练样本。解决这份资源已经是目录级划分好的理论上不存在这个问题后续自己扩数据时要保证“同一株/同一果实的多个视角只能进同一个集合”划分粒度按物品不是按文件。5.4 尾部类mAP远低于平均样本少不是借口要局部增强现象grape_esca、wheat_leaf_rust这类尾部类mAP只有个位数可视化里漏检一大片而apple_healthy这些头部类接近0.9。原因类别不平衡尾部类只有几百个框模型把它当成难例而不是正样本学到的是“不存在”而不是“存在”。解决只对样本少的class_id做局部增强。写脚本按class_id统计出框数最少的top-3类单独复制出来做5次mosaic或局部HSV扰动再合并回训练集。不要全局上调mosaic概率——那会让头部类的过拟合更严重。5.5 换机器结果对不上环境漂移是隐形杀手现象同一份数据换台显卡重新训练后之前best.pt在同样测试集上mAP掉了3个点以上你以为是玄学其实是环境不一致。原因ultralytics小版本之间默认增强、锚框逻辑有变化另外imgsz或batch不一致也会引起精度波动。解决固定环境、固定参数再对比。开训前把yolo version输出打到项目README里同一批次对比必须是同一份dataset.yaml、同样imgsz和同样epochs不能一次640一次1280就拿来比mAP。6. 混淆矩阵与新类别扩展把模型从“能跑”做到“能用”训练结束后不要只看train/val的loss曲线要在测试集上出混淆矩阵。YOLO自带plot功能跑一次val就能生成分好类的混淆矩阵PNG# 用best.pt在测试集上评估并生成混淆矩阵图 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) metrics model.val(datadataset.yaml, splittest, plotsTrue) print(fmAP50: {metrics.box.map50:.3f}) print(fmAP50-95: {metrics.box.map:.3f})逻辑说明验证结束后会在weights同目录生成confusion_matrix.png。看混淆矩阵的顺序是先看主对角线够不够亮这是准确率的主要来源再看非对角线哪两个类互相混。农业病害里最常见的混淆是“同一作物不同病害”比如苹果黑星病和苹果健康叶片早期病斑视觉差异本来就小这种混不可怕补数据就行“不同作物但同形态”的混淆比如两种作物的灰斑病互相混说明标注标准有问题要回头翻原始标签。新类别扩展也是这类数据集的常见需求。固定做法是拿到新数据比如烟草病虫害数据集先按第二章的统计脚本看类别分布把新类别名追加到class.txt末尾重新生成dataset.yaml然后基于best.pt继续训练而不是从头训。继续训练时指定modelbest.ptepochs设50左右用freeze10冻结前10层旧类别不会忘新类别几轮就能收敛。从那以后我每次拿到数据集无论多着急都强制自己先走一遍“class.txt核对标签格式→可视化脚本抽查→统计类别分布”这个流程三件事做完再谈训练调参。也正因为这套流程固化我在这类30类数据集上很少出现训完才发现标签错位的返工。希望这次拆解能帮你看清这份资源的边界和用法把它一次跑通少踩我当年踩过的坑。本文还有配套的精品资源点击获取
返回列表