简介本资源为茶叶病害目标检测数据集面向从事农业图像识别、深度学习模型训练的学生与算法工程师可用于分类与检测任务的模型训练、验证及竞赛练习。数据集采用Pascal VOC与YOLO双格式标注包含883张jpg图片及对应的883个xml和883个txt标注文件压缩包内共约2000个文件整体大小200.5MB另附有少量说明文本方便直接接入主流检测框架。标注覆盖8个类别包括炭疽病、藻斑病、鸟眼斑病、褐斑病、灰斑病、健康叶片、红叶斑病与白斑病总框数884个每张图片仅含单片叶子适合单目标检测场景。目前已有887人学习下载读者可获得开箱即用的标注数据、清晰的类别分布以及规范的labelImg标注结果能有效减少数据采集与清洗成本快速投入模型迭代与效果对比实验。1. 茶叶病害数据集 VOCYOLO 格式 883 张 8 类别一份能直接开训的检测数据该怎么用茶园里真正难的不是把模型跑起来而是拿到一批标注干净、类别对得上、格式不用来回折腾的图。这份「茶叶病害数据集 VOCYOLO 格式 883 张 8 类别」正好卡在这个痛点上883 张图、8 个病害类别、同时给了 VOC 的 XML 和 YOLO 的 txt 两套标注。对做农业视觉、智慧种植、边缘端病害巡检的人来说它省掉的不是下载时间而是格式转换和类别对齐这两段最容易翻车的活。这篇文章不聊虚的就按一线做法把这份数据集从「拿到手」到「跑出第一版 mAP」讲透目录怎么摆、YOLO 的 txt 怎么读、8 类怎么配、训练参数怎么设、小样本下哪些坑必踩。适合刚入门 yolo 目标检测的新手也适合手里有模型但缺农业场景数据的熟手。2. 先搞懂 VOC 与 YOLO 两套标注到底差在哪2.1 VOC 的 XML 与 YOLO 的 txt坐标体系完全不同VOC 格式的标注是一个图对应一个 XML 文件里面用object记录每个目标坐标是绝对像素值写成xmin, ymin, xmax, ymax。YOLO 格式则是一个图对应一个 txt每行一个目标格式是类别索引 中心x 中心y 宽 高而且这四个值全部是相对整图宽高的归一化值范围 0 到 1。这两套东西看着只是数字不同实际差在三个地方一是坐标系原点VOC 用左上角绝对像素YOLO 用归一化中心点二是类别表达VOC 写类别名字符串YOLO 写从 0 开始的整数索引三是文件组织VOC 的 XML 通常和图片分开放YOLO 的 txt 一般和图片同名同目录或镜像目录。正因为差在这三处很多人拿到「VOCYOLO 双格式」的数据集反而懵到底用哪套我的建议是训练直接用 YOLO 那套 txtVOC 的 XML 留着做校验和回溯。原因很直接主流 yolo 训练框架读的就是 YOLO txt你再去转一道纯属给自己加戏。但 XML 别删后面排查「某个框是不是标歪了」时XML 里的绝对像素比归一化值直观得多。2.2 883 张 8 类别意味着什么小样本多类别的现实约束883 张图分 8 个类别平均下来每类不到 110 张这是典型的小样本多类别场景。它带来的直接后果是类别不均衡几乎必然存在某些病害样本可能只有几十张而健康叶片或常见病害可能上百张。第二个后果是模型很容易在样本多的类上过拟合在样本少的类上直接躺平。第三个后果是验证集如果随机切很可能某个类在验证集里只有个位数样本mAP 波动大到没法看。所以拿到这份数据第一件事不是急着训而是先统计每个类的框数量和图片数量。常见做法是写个脚本遍历 labels 目录把每个类别的实例数打出来。如果发现某类少于 30 个实例就要提前想好对策要么用数据增强重点补这类要么在损失里给这类加权要么接受它在初期 mAP 偏低、靠后续迭代慢慢拉。别指望 883 张能训出工业级精度它的合理定位是「快速验证 pipeline 农业场景预训练起点」。2.3 为什么双格式数据集更适合做格式转换的练手样本很多人学 yolo 卡在第一步自己的数据是 VOC不知道怎么转 YOLO。这份数据集两套都给恰好可以拿来反向验证你的转换脚本对不对。做法是拿它自带的 XML 跑一遍你自己的 VOC 转 YOLO 脚本再和它自带的 txt 逐行对比。如果坐标对得上、类别索引对得上说明你的脚本没问题以后处理自己的数据就放心了。如果对不上差异点就是你脚本的 bug 所在。这比空看教程有用得多因为你有标准答案可以比对。下面是一个最小可用的 VOC 转 YOLO 脚本逻辑就是读 XML、算归一化中心点和宽高、按类别映射写 txtimport os import xml.etree.ElementTree as ET # 类别名到索引的映射顺序必须和训练时的 data.yaml 一致 classes [class0, class1, class2, class3, class4, class5, class6, class7] class_map {name: i for i, name in enumerate(classes)} def convert(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 if name not in class_map: continue # 跳过未定义类别避免索引错乱 cls_id class_map[name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化中心点与宽高 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines))这段代码里img_w和img_h必须传真实图片尺寸不能写死 640因为归一化用的是原图尺寸。class_map的顺序是命门它决定了 txt 里第一列的数字一旦和 data.yaml 里的 names 顺序不一致训练时类别就全错位了模型会把 A 病害认成 B 病害而且 loss 还能正常下降属于最隐蔽的翻车。:.6f保留六位是常见做法够用且不会因为精度丢框。3. 把 883 张数据喂进 YOLO目录、配置与训练命令3.1 目录结构怎么摆才不会在训练时报找不到标签YOLO 训练框架对目录结构有约定最常见的是 images 和 labels 平行且内部再分 train 和 val。推荐这样摆dataset/ images/ train/ (约 700 张) val/ (约 183 张) labels/ train/ (与 train 图片同名的 txt) val/ (与 val 图片同名的 txt)关键点是 labels 下的 txt 必须和 images 下的图片同名只换扩展名。比如images/train/leaf_001.jpg对应labels/train/leaf_001.txt。如果名字对不上训练时框架会认为这张图没有标签直接跳过或报空标签警告。另一个坑是图片和标签数量不一致比如你复制图片时漏了几张或者转换脚本中途报错少写了 txt训练不会立刻崩但会静默丢掉那些样本你以为在训 883 张实际可能只用了 800 张。所以切分完先跑一遍数量核对。3.2 data.yaml 里 8 个类别的顺序为什么是命门data.yaml 是 YOLO 训练的入口配置核心就几行path: /abs/path/to/dataset train: images/train val: images/val nc: 8 names: 0: class0 1: class1 2: class2 3: class3 4: class4 5: class5 6: class6 7: class7nc是类别数这里必须是 8。names的顺序必须和 txt 里第一列的数字严格对应。我一般会把真实的 8 个病害名字按字母或按样本量从多到少排好然后这个顺序在转换脚本、data.yaml、后续推理的类别映射里三处保持一致。只要有一处顺序变了模型输出的类别名就全乱。这个错误不会让训练报错只会让结果看起来「精度还行但预测全是错的」属于血泪经验级别的坑。path建议写绝对路径相对路径在不同工作目录下启动训练时容易找不到。3.3 一条能跑通的训练命令与关键参数假设用的是常见的 YOLO 训练框架一条基础命令大致是这样yolo detect train \ data/abs/path/to/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/tea \ nameexp1参数逐个说model选 nano 版是因为 883 张属于小样本大模型参数量多过拟合风险高nano 或 small 起步更稳。epochs100是起点不是终点配合patience20做早停验证指标 20 轮不涨就停省时间。imgsz640是通用默认如果茶叶病害的斑点很小可以试 800 或 960但显存和速度要重新权衡。batch16在单卡 8G 显存下一般能跑爆显存就降到 8。lr00.01是常见初始学习率小样本可以降到 0.005 更稳。project和name决定结果存哪建议按实验编号命名方便回溯。训练启动后重点看三个东西一是 loss 是否稳定下降如果一开始就 nan多半是学习率太大或标签有非法值比如坐标超过 1二是验证集的 mAP50 走势小样本下前期波动正常看趋势不看单点三是每个类别的 AP如果某类一直是 0回去查这个类的标签是不是有问题。3.4 训练前用三行代码做标签合法性体检在正式训之前我习惯先做一次标签体检把坐标越界、空文件、类别越界这三类问题提前揪出来import os label_dir dataset/labels/train for fn in os.listdir(label_dir): p os.path.join(label_dir, fn) with open(p) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: print(f字段数异常 {fn}:{i}) continue cls_id int(parts[0]) vals [float(x) for x in parts[1:]] if cls_id 0 or cls_id 7: print(f类别越界 {fn}:{i} - {cls_id}) if any(v 0 or v 1 for v in vals): print(f坐标越界 {fn}:{i} - {vals})这段逻辑很直白每行必须是 5 个字段类别索引在 0 到 7 之间四个坐标都在 0 到 1 之间。任何一条不满足训练时要么报错要么静默学歪。坐标越界常见于转换时用了错误的图片尺寸比如图片实际是 1280 宽但你按 640 归一化算出来的值就会大于 1。空 txt 文件也要留意它代表这张图没有目标有些框架允许有些会警告最好确认一下是不是漏标。4. 小样本 8 类别训练避坑这些现象背后是什么4.1 某个类别 AP 长期为 0先查标签再查样本量现象是训练几十轮后7 个类别的 AP 都在涨唯独某一类始终是 0。原因通常有两个一是这个类的标签在 txt 里根本不存在比如转换时类别名没匹配上被跳过了二是这个类样本太少比如只有十几张模型还没学会就被早停截断。解决顺序是先统计这个类的实例数如果为 0回去查转换脚本的类别映射如果只有个位数先关掉早停多训几十轮或者对这个类做针对性增强旋转、裁剪、亮度扰动再不行就在损失里给稀有类加权。别一上来就怀疑模型结构小样本问题九成出在数据侧。4.2 验证集 mAP 忽高忽低切分方式比模型更影响结果现象是同一份数据换个随机种子重新切分mAP 能差十几个点。原因是 883 张分 8 类验证集本来就只有一百多张某些类在验证集里可能只有两三张一两个框预测对错就能让 AP 大幅跳动。解决办法是切分时做分层抽样保证每个类在训练集和验证集里的比例接近而不是纯随机切。如果某类总实例太少考虑用交叉验证把数据分成 K 折轮流做验证最后看平均指标比单次切分可信得多。这个坑不解决你会一直在调参上浪费时间其实问题在评估方式。4.3 训练 loss 正常但预测框全偏归一化尺寸用错了现象是训练 loss 一路下降看着很健康但推理时框的位置整体偏移或大小不对。原因多半是转换时归一化用的图片尺寸和实际不符比如图片被预处理 resize 过但标签还是按原图算的。另一种可能是训练时的 imgsz 和推理时的 imgsz 不一致YOLO 内部会做 letterbox 缩放如果两边缩放逻辑不同框就会偏。解决方法是固定一套预处理流程训练和推理用同一个 imgsz标签归一化严格用原图宽高推理后处理按同样的 letterbox 参数还原。这个坑的隐蔽性在于 loss 不报错只有可视化预测结果才能发现。4.4 显存爆了不一定是 batch 太大先看 imgsz 和缓存现象是 batch 设成 8 还是 OOM。原因可能是 imgsz 设太大比如 1280 的输入显存占用是 640 的四倍左右也可能是开了数据缓存把整个数据集加载进内存或显存。解决顺序是先降 imgsz 到 640 试再关掉 cache 相关选项最后才降 batch。另外多尺度训练如果开了也会让显存峰值变高。小样本数据集本身不大缓存带来的速度提升有限关掉换稳定更划算。4.5 类别名对不上导致预测结果全错位现象是模型能出框置信度也不低但框上的类别名全是错的比如把健康叶认成病斑。原因就是 data.yaml 的 names 顺序和 txt 里的类别索引不一致或者推理时的类别映射表和训练时不同。这个坑最坑的地方在于训练指标看起来正常因为模型学的是一套自洽的索引只是你解读时用错了名字。解决办法是训练前把 data.yaml 的 names、转换脚本的 class_map、推理代码的类别列表三处打印出来逐行比对确认完全一致再开训。我一般会把这份映射存成一个单独的 json训练和推理都读它从源头杜绝不一致。5. 把 883 张用到极致增强策略与效果验证的具体技巧小样本数据集的胜负手不在模型在你怎么把 883 张用出 2000 张的效果。我的习惯是先做一轮基线训练不加任何增强记录每个类的 AP找出最弱的那两三个类然后只对这些类做针对性增强而不是全量乱加。茶叶病害的形态特点是斑点、变色、边缘枯萎所以几何增强里旋转和缩放最有用因为叶片在自然拍摄中角度和距离本来就多变颜色增强里亮度和对比度扰动要适度因为病害本身靠颜色区分扰动太猛会把病斑特征抹掉。翻转可以用但垂直翻转要谨慎因为叶片正反面纹理不同翻过来可能变成不真实的样本。具体做法是在训练配置里开增强参数常见的有degrees旋转角度、scale缩放比例、hsv_h/hsv_s/hsv_v色调饱和度亮度扰动、fliplr/flipud水平垂直翻转。我的起点是degrees15、scale0.5、hsv_v0.4、fliplr0.5、flipud0.0先跑一轮看弱类 AP 有没有起来再微调。增强不是越多越好加过头会让模型学到不真实的模式验证集指标反而掉。验证增强有没有用不能只看总 mAP要看弱类的 AP 变化和混淆矩阵。如果弱类 AP 涨了但强类掉了说明增强伤到了强类特征要收一收。如果所有类都涨说明增强方向对。另一个验证手段是拿几张真实茶园照片做推理肉眼看框和类别对不对这比数字更直接。我一般会留 10 到 20 张完全不参与训练的图做最终目测它们不进入任何评估指标只用来做「人眼验收」。还有一个容易被忽略的技巧把 VOC 的 XML 利用起来做标签一致性抽查。随机抽 20 张图把 XML 里的绝对坐标画成框再把 YOLO txt 还原成绝对坐标画一遍两套框叠在一起看是否重合。重合说明转换无损不重合说明某一步算错了。这个检查花不了十分钟但能避免你带着错误标签训一整天。最后说投入判断这份数据集的价值不在于它能训出多高的精度而在于它让你用最低成本跑通「农业病害检测」的完整链路——格式转换、类别配置、小样本训练、增强调优、结果验证。跑通之后你可以把这套流程平移到自己的茶园数据上那才是真正产生价值的地方。我自己做农业视觉项目时习惯是先拿一份小样本公开数据把 pipeline 跑顺再换自己的数据这样出问题时能快速定位是数据问题还是代码问题。希望帮到你。本文还有配套的精品资源点击获取