棉花叶病害检测数据集VOC+YOLO格式977张22类训练避坑指南

发布时间:2026/10/5 16:28:39
棉花叶病害检测数据集VOC+YOLO格式977张22类训练避坑指南 简介本资源为棉花叶子病害检测数据集面向从事农业图像识别、作物病害分类与目标检测的算法工程师、研究生及竞赛选手可用于训练和验证YOLO或VOC格式的检测模型。压缩包共约2000个文件包含977张jpg图片、977个VOC格式xml标注文件、977个YOLO格式txt标注文件及少量说明文件整体约47.86MB图片分辨率统一为640x640标注类别达22类覆盖多种棉花叶部病害场景。目前已有317人学习下载适合需要快速获取标注数据、验证模型效果或开展对比实验的读者。数据集同时提供VOC与YOLO两套标注省去格式转换步骤可直接接入主流检测框架类别丰富且分辨率统一便于评估模型在多类别小目标上的表现也可用于数据增强与迁移学习研究。1. 977 张棉花叶病害图22 类标注到底能训出什么拿到一个农业病害数据集第一反应往往不是「能不能用」而是「22 类是不是太碎了」。棉花叶子病害检测数据集 VOCYOLO 格式 977 张 22 类别这个组合乍看有点反直觉977 张图要分 22 个类别平均每类不到 45 张放在通用目标检测里几乎算「小样本中的小样本」。但棉花叶部病害的实际场景就是这样——枯萎、黄化、叶斑、霉变、虫害痕迹很多类别在视觉上高度相似靠人眼分都费劲更别说让模型去学。这份数据集的价值不在于刷高 mAP而在于它把真实田间拍摄的 640×640 图像和双格式标注VOC XML YOLO TXT打包好了省掉最耗时的标注环节。适合做农业视觉落地的工程师、想验证小样本多分类检测方案的研究者以及需要快速搭一个棉花病害 demo 的开发者。977 张不是让你直接上产线而是让你先把 pipeline 跑通、把类别混淆矩阵看清楚再决定要不要扩标。2. VOC 与 YOLO 双格式拆解977 张图怎么对齐标注2.1 两种格式的文件组织与字段含义这份数据集的核心卖点之一是同时提供 Pascal VOC 和 YOLO 两种标注格式。VOC 格式每张图对应一个 XML 文件里面用object节点记录类别名和边界框的xmin/ymin/xmax/ymax像素坐标YOLO 格式每张图对应一个 TXT 文件每行是class_id x_center y_center width height全部归一化到 0~1 之间。977 张 jpg、977 个 xml、977 个 txt数量一一对应说明标注是完整对齐的没有漏标或多余文件。常见做法是先把压缩包解压后按以下结构整理# 解压后建议整理成标准目录避免路径混乱 mkdir -p cotton/{images,labels_voc,labels_yolo} # 假设解压出来的 jpg/xml/txt 混在一起 for f in *.jpg; do mv $f cotton/images/; done for f in *.xml; do mv $f cotton/labels_voc/; done for f in *.txt; do mv $f cotton/labels_yolo/; done这段脚本做的是物理分离逻辑很简单YOLO 训练时只认images和labels两个目录VOC 的 XML 留作备份或转 COCO 用。参数上唯一要注意的是文件名必须严格一致——firc_cotton_625.jpg对应firc_cotton_625.xml和firc_cotton_625.txt少一个后缀都会在训练时被跳过。我一般会先跑一遍文件名比对确认没有孤儿文件再往下走。2.2 22 类标签映射与类别不平衡检查22 个类别意味着 YOLO 的nc22但类别名不会自动从 XML 里读出来需要自己生成classes.txt或data.yaml。VOC XML 里的name字段是类别名的唯一来源建议用脚本抽取并排序保证class_id和类别名一一对应且稳定。import os, xml.etree.ElementTree as ET # 从 VOC XML 中抽取所有类别名生成 YOLO 的 classes.txt names set() for xml_file in os.listdir(cotton/labels_voc): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(cotton/labels_voc, xml_file)) for obj in tree.findall(object): names.add(obj.find(name).text) names sorted(names) with open(cotton/classes.txt, w, encodingutf-8) as f: f.write(\n.join(names)) print(f共 {len(names)} 类:, names)逻辑说明用set去重后排序保证每次生成的 id 顺序一致否则重新生成标签时 id 会漂移。参数上classes.txt的行号就是 YOLO 的class_id第 0 行对应 id 0以此类推。跑完这一步顺手统计每个类别的框数量如果某类少于 20 个框训练时几乎必然被淹没需要在data.yaml里考虑过采样或加权。from collections import Counter counter Counter() for txt_file in os.listdir(cotton/labels_yolo): if not txt_file.endswith(.txt): continue with open(os.path.join(cotton/labels_yolo, txt_file)) as f: for line in f: counter[int(line.split()[0])] 1 for cid, cnt in sorted(counter.items()): print(fclass {cid} ({names[cid]}): {cnt} boxes)这段统计是判断数据集能不能直接用的关键。977 张图 22 类如果某些类只有个位数框别指望模型能学好要么合并相似类要么补标。我见过太多人跳过这步训完发现混淆矩阵里某几类全是 0回头查才发现标注本身就少得可怜。3. 从 VOC 到 YOLO转换脚本与 640×640 适配3.1 XML 转 TXT 的坐标归一化实现虽然数据集已经带了 YOLO TXT但实际项目中经常需要自己重转一遍——比如改了类别顺序、过滤了某些类、或者要把 VOC 的difficult标记处理掉。转换的核心是把像素坐标归一化公式是x_center (xmin xmax) / 2 / widthy_center (ymin ymax) / 2 / heightw (xmax - xmin) / widthh (ymax - ymin) / height。注意 VOC 的坐标是 1-based 还是 0-based 在不同工具里有差异这份数据集分辨率统一 640×640直接用图像实际宽高做分母最稳。import os, xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map, out_path): tree ET.parse(xml_path) root tree.getroot() # 用实际图像尺寸避免 XML 里 size 字段不准 with Image.open(img_path) as im: w, h im.size lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue # 过滤不需要的类别 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) # 裁剪到图像边界防止标注越界导致归一化后超出 0~1 xmin, xmax max(0, xmin), min(w, xmax) ymin, ymax max(0, ymin), min(h, ymax) xc (xmin xmax) / 2 / w yc (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{class_map[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))逻辑说明class_map是类别名到 id 的字典从classes.txt读入即可。裁剪到边界这步很多人省掉结果训练时 YOLO 报normalized coordinates out of range警告虽然不一定崩但会静默丢弃异常框。保留 6 位小数是 YOLO 官方推荐精度再高没必要。参数上如果原图不是 640×640这里用实际尺寸归一化后训练时再 resize 到 640不会丢信息但这份数据集本身就是 640×640所以归一化和直接除以 640 等价。3.2 640×640 分辨率下的训练配置与增强策略分辨率统一 640×640 对 YOLO 系列非常友好因为 YOLOv5/v8 的默认输入就是 640。直接拿这份数据训不需要改imgsz但要注意小目标问题——棉花叶病害的斑点有时候只占几十个像素640 下经过 32 倍下采样后特征图只剩几个格子容易漏检。常见做法是开mosaic和copy_paste增强但mosaic对密集小目标有时会引入噪声我一般先关掉对比一轮。# data.yaml 示例路径按实际调整 path: ./cotton train: images/train val: images/val nc: 22 names: [class0, class1, ...] # 与 classes.txt 顺序一致训练命令以 YOLOv8 为例yolo detect train datacotton/data.yaml modelyolov8s.pt epochs150 imgsz640 batch16 patience30参数说明imgsz640匹配数据集原生分辨率不要改成 1280否则小目标没变多反而显存翻倍batch16在 8G 显存卡上比较稳显存不够降到 8patience30是早停22 类小数据集很容易过拟合早停能省时间。如果验证集 mAP 在 50 轮后还在抖多半是类别不平衡导致回去看第 2 章的框数统计。4. 避坑排查22 类小样本数据集最容易翻车的五处4.1 类别 id 错位导致全图预测成同一类现象训练 loss 正常下降但推理时所有框都标成同一个类别或者验证集 mAP 极低。原因classes.txt的顺序和生成 TXT 时的class_map不一致比如先按字母序生成 classes后来手动改了顺序但没重转标签。解决固定一份classes.txt所有转换脚本都从它读class_map转完标签后随机抽 10 张图用可视化脚本画框核对确认类别名和框对得上再开训。4.2 XML 中 size 字段与实际图像不符现象转换后的 YOLO 坐标大量超出 0~1训练时报归一化越界。原因部分 VOC XML 的size里写的宽高和实际 jpg 不一致可能是标注工具导出时写错。解决转换时不要信 XML 的 size直接用 PIL 打开图像读im.size并在转换后加断言0 xc 1不满足就打印文件名人工检查。4.3 空 TXT 文件被当成负样本现象训练时提示某些标签文件为空或者验证集出现大量误检。原因有些图确实没有目标转换后生成空 TXTYOLO 会把空文件当负样本但比例过高会拉低召回。解决统计空 TXT 数量如果超过总数 5%考虑把这些图从训练集移除或单独处理如果只是个别保留无妨但要在data.yaml里确认路径没写错导致读不到标签。4.4 640×640 下小目标被 mosaic 增强切碎现象训练 mAP 尚可但推理时小斑点漏检严重。原因mosaic 把四张图拼成一张原本就小的病害区域被进一步缩小特征更弱。解决先关掉 mosaicmosaic0.0训一轮基线再开mosaic0.5对比如果小目标 recall 下降明显改用copy_paste或只做随机缩放别硬上 mosaic。4.5 验证集划分泄漏导致指标虚高现象验证集 mAP 很高但换一批新图推理效果断崖式下跌。原因同一片叶子或同一植株的多张图被分到了训练和验证集模型记住了背景而不是病害特征。解决按文件名前缀或拍摄批次做分组划分确保同一来源的图只出现在一个集合里。这份数据集文件名是firc_cotton_数字如果数字连续段对应同一批拍摄就按段切分别用随机切分。5. 进阶验证用混淆矩阵和单类 AP 判断数据集真实上限训完一轮别只看总 mAP22 类小数据集的总指标会被大类主导真正要盯的是混淆矩阵和单类 AP。YOLOv8 训练完会在runs/detect/train/下生成confusion_matrix.png和results.csv前者能直接看出哪两类在互相误判后者可以画单类 AP 曲线。import pandas as pd import matplotlib.pyplot as plt # 读取 YOLOv8 的 results.csv画单类 mAP 对比 df pd.read_csv(runs/detect/train/results.csv) df.columns df.columns.str.strip() # 假设列名里有 metrics/mAP50-95(B) 和各单类 AP按实际列名调整 plt.figure(figsize(12, 5)) plt.plot(df[epoch], df[metrics/mAP50-95(B)], labeloverall mAP50-95) plt.xlabel(epoch) plt.ylabel(mAP) plt.legend() plt.savefig(map_curve.png, dpi150)逻辑说明results.csv的列名在不同 YOLO 版本里有差异先strip()去空格再取列。如果只想看单类YOLOv8 的验证输出里会有per_class_ap可以导出成表格。参数上重点看 AP 低于 0.2 的类这些类要么样本太少要么和别的类视觉重叠严重。我一般会把低 AP 类的验证图单独抽出来看如果人眼都分不清那就不是模型问题是标注定义问题得回去合并类别或重新定义标注规范。另一个实用技巧是用yolo detect val加save_jsonTrue导出 COCO 格式预测结果再用 pycocotools 算每类的 AP 和 AR比 YOLO 自带的更细。跑完这套你就能判断这份 977 张 22 类的数据集到底能撑到什么程度——如果大部分类 AP 在 0.3 以上说明标注质量过关可以在此基础上扩标如果一半类 AP 接近 0别急着加数据先查标注一致性。从那以后我每次拿到多类小样本数据集都强制先跑一遍类别框数统计和混淆矩阵基线再决定要不要投入训练资源。希望帮到你。本文还有配套的精品资源点击获取