玉米叶片缺陷检测数据集实战:单类别YOLOv5训练与验证避坑指南

发布时间:2026/10/9 2:42:22
玉米叶片缺陷检测数据集实战:单类别YOLOv5训练与验证避坑指南
简介这份资源面向从事农业视觉检测、目标检测算法学习与落地的开发者提供玉米叶片缺陷检测的YOLOv5格式数据集解决病害识别中样本获取与标注成本高的问题。数据按YOLOv5标准目录组织包含训练集与验证集可直接投入训练无需额外转换。压缩包共约2000个文件以txt标注文件为主另附一个可视化py脚本整体大小约298.96MB训练集含1558张图片及对应标签验证集含667张图片及对应标签图像为2000至3000像素的大分辨率RGB图边界框标注清晰、图像完整类别为infected单类。可视化脚本随机传入一张图片即可绘制并保存边界框无需修改即可运行便于快速核验标注质量。目前已有165人学习下载适合需要现成数据开展玉米叶缺陷检测实验、模型训练与效果验证的读者。1. 玉米叶片缺陷检测数据集1 类别、训练集与验证集到底怎么用玉米叶片缺陷检测这个方向真正卡住大多数人的从来不是模型结构而是数据。你拿到手的往往是一批田间拍的叶片照片标签只有一类——缺陷没有细分病斑类型也没有像素级掩码就是框出有问题的区域。这种单类别数据集看起来简单实际用起来坑不少正负样本极度不均衡、背景干扰大、叶片重叠导致框粘连。标题里说的「1 类别包含训练集、验证集」意味着这是一个已经切分好的目标检测数据集直接对应 YOLOv5 的训练格式省掉了你自己标注和划分的环节。适合谁用做农业视觉巡检的、搞植保无人机巡检的、以及想拿一个真实场景数据集跑通 YOLOv5 全流程的工程师。下面从数据组织、训练配置、验证策略到避坑一步步拆开讲。2. 单类别玉米叶片数据集的组织方式与 YOLOv5 格式对齐2.1 为什么单类别数据集反而更容易翻车单类别目标检测在标注上省事但在训练动态上比多类别更敏感。YOLOv5 的损失函数里分类分支只有一类正样本的置信度目标恒为 1负样本为 0。问题在于玉米叶片缺陷区域往往面积小、边缘模糊如果锚框匹配策略没调好正样本数量会少得可怜。常见做法是先用kmeans重新聚类锚框而不是直接套用 COCO 的预设。另外单类别下nc1YOLOv5 会自动把分类损失权重降低但不会帮你平衡正负样本所以hyp里的cls和obj权重需要手动微调。数据集目录结构必须严格对齐 YOLOv5 的要求否则训练脚本会在第一轮就报No labels found。标准布局是corn_leaf_defect/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamlimages/train和labels/train里的文件名必须一一对应只是扩展名不同。标签文件是.txt每行格式为class_id x_center y_center width height全部归一化到 0~1。单类别下class_id恒为 0。2.2 从原始标注到 YOLO txt转换脚本与边界检查如果你拿到的原始标注是 VOC XML 或 LabelMe JSON需要转成 YOLO 格式。下面这个脚本处理 VOC 转 YOLO同时做边界裁剪防止坐标越界导致训练时AssertionError。import xml.etree.ElementTree as ET import os from PIL import Image def voc_to_yolo(xml_dir, img_dir, out_dir, class_map): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) with Image.open(img_path) as im: w, h im.size lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_map: continue cls_id class_map[cls_name] bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 边界裁剪防止越界 x1 max(0, min(x1, w - 1)) y1 max(0, min(y1, h - 1)) x2 max(0, min(x2, w - 1)) y2 max(0, min(y2, h - 1)) if x2 x1 or y2 y1: continue xc (x1 x2) / 2.0 / w yc (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out_file os.path.join(out_dir, os.path.splitext(xml_file)[0] .txt) with open(out_file, w) as f: f.write(\n.join(lines)) voc_to_yolo( xml_dirraw_annotations, img_dirraw_images, out_dircorn_leaf_defect/labels/train, class_map{defect: 0} )逻辑说明先读 XML 拿到原图宽高再把 VOC 的左上右下坐标转成 YOLO 的中心点加宽高全部除以宽高做归一化。边界裁剪那几行是关键田间拍摄的叶片经常有标注框超出图像边缘的情况不裁剪的话 YOLOv5 的 dataloader 会直接抛异常。class_map里只保留defect一类其他类别直接跳过保证单类别纯净。参数说明xml_dir是 VOC 标注文件夹img_dir是原图文件夹out_dir是输出标签文件夹。class_map根据你的标注名称改如果标注里写的是「病斑」就改成{病斑: 0}。归一化保留 6 位小数足够YOLOv5 内部会再处理。2.3 data.yaml 的五个必填字段与路径陷阱YOLOv5 通过data.yaml定位数据和类别。单类别数据集最容易写错的是names列表和nc的对应关系。path: /home/user/corn_leaf_defect train: images/train val: images/val nc: 1 names: [defect]path是数据集根目录train和val是相对路径。注意val指向的是图像目录YOLOv5 会自动去同级labels目录找同名 txt。如果验证集图像和标签不在同级目录训练时验证阶段会报No labels found。常见错误是把val写成绝对路径但path又写了相对路径导致路径拼接后找不到文件。建议全部用绝对路径或者全部用相对路径并确认工作目录正确。提示names列表里字符串不要带空格或特殊字符单类别直接写[defect]即可。如果后续要扩展类别nc和names必须同步改且标签文件里的class_id要重新映射。3. 用 YOLOv5 训练单类别玉米叶片缺陷模型参数怎么设、日志怎么看3.1 从预训练权重到自定义数据集的迁移训练命令YOLOv5 官方仓库提供了train.py单类别数据集不需要改网络结构只需要指定data.yaml和nc。下面这条命令是我在 6GB 显存上跑 640 尺寸的常用配置python train.py \ --weights yolov5s.pt \ --data corn_leaf_defect/data.yaml \ --img 640 \ --batch-size 16 \ --epochs 200 \ --hyp data/hyps/hyp.scratch-low.yaml \ --optimizer SGD \ --lr0 0.01 \ --lrf 0.01 \ --cache ram \ --device 0 \ --project runs/train \ --name corn_defect_v1逻辑说明--weights yolov5s.pt加载 COCO 预训练权重单类别数据量通常不大从预训练迁移比从头训收敛快很多。--img 640是输入尺寸玉米叶片缺陷区域如果偏小可以提到 1024但显存占用会翻倍。--batch-size 16在 6GB 显存下比较稳如果报 OOM 就降到 8。--cache ram把图像缓存到内存加速数据加载但要求内存足够数据集超过 10GB 就别开。--hyp选hyp.scratch-low.yaml是因为单类别下分类损失简单低增强策略能减少过拟合。参数说明--lr0初始学习率SGD 下 0.01 是常用值如果 loss 震荡就降到 0.005。--lrf是最终学习率因子余弦退火到lr0 * lrf。--epochs 200对单类别通常够用看mAP0.5在验证集上是否还在涨不涨就可以停。3.2 单类别下超参数 hyp 的微调重点YOLOv5 的hyp.scratch-low.yaml里几个关键参数对单类别影响很大参数默认值单类别建议原因box0.050.05~0.08缺陷区域边界模糊框回归权重可略高cls0.50.3~0.5单类别分类简单过高反而干扰obj1.01.0保持默认正负样本平衡靠数据fl_gamma0.00.0单类别不建议开 focal lossmosaic1.00.5~1.0田间背景复杂mosaic 增强有帮助mixup0.00.0~0.1单类别 mixup 容易产生无意义样本调整方式是在data/hyps/下复制一份改名为hyp_corn.yaml然后--hyp data/hyps/hyp_corn.yaml。改完不用动源码YOLOv5 会自动读取。3.3 训练日志里必须盯住的四个指标训练启动后控制台每轮输出一行重点看这四个box_loss框回归损失正常从 0.08 左右降到 0.02 以下。如果一直不降检查标签归一化是否正确。obj_loss目标置信度损失单类别下这个值通常比多类别高因为负样本比例大。降到 0.01 以下算收敛。mAP0.5验证集上的平均精度单类别下就是该类别的 AP。0.85 以上算可用0.9 以上算好。Precision和Recall精确率和召回率。如果 Recall 低但 Precision 高说明模型漏检多可以降低conf-thres或增加正样本。日志里出现nan通常是学习率太大或标签有非法值比如宽高为 0。出现No labels found是路径问题。出现CUDA out of memory就降 batch 或 img-size。注意单类别数据集如果验证集里没有负样本全是缺陷叶片mAP会虚高。建议验证集里混入 10%~20% 无缺陷叶片否则模型上线后会把正常叶片也框出来。4. 验证集评估与推理单类别模型的指标解读和误检排查4.1 val.py 跑评估命令与输出解读训练完用val.py在验证集上跑一次完整评估python val.py \ --weights runs/train/corn_defect_v1/weights/best.pt \ --data corn_leaf_defect/data.yaml \ --img 640 \ --batch-size 16 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --task val \ --device 0逻辑说明--conf-thres 0.25是置信度阈值低于这个值的框直接丢弃。--iou-thres 0.45是 NMS 的 IoU 阈值单类别下如果叶片重叠严重可以降到 0.3 减少框粘连。--task val表示只评估不保存预测图如果要看可视化结果改成--task test并加--save-txt。输出里all那一行就是整体指标。单类别下mAP0.5和mAP0.5:0.95差距大是正常的因为缺陷区域边界模糊高 IoU 阈值下匹配困难。如果mAP0.5高但mAP0.5:0.95很低说明框的位置不够准可以尝试提高box损失权重或增加标注精度。4.2 误检和漏检的排查路径单类别模型上线后最常见的两个问题把正常叶片纹理当成缺陷误检或者小病斑没框出来漏检。排查顺序如下先看验证集的可视化结果用detect.py跑一批图python detect.py \ --weights runs/train/corn_defect_v1/weights/best.pt \ --source corn_leaf_defect/images/val \ --img 640 \ --conf-thres 0.25 \ --save-txt \ --project runs/detect \ --name val_check跑完去runs/detect/val_check看标注图。误检多的话检查训练集里是否混入了正常叶片但被标了框或者背景里有类似病斑的纹理。漏检多的话看小目标是否在img-size下被缩得太小可以尝试--img 1024重新训练。另外--conf-thres调低到 0.1 看能不能召回更多但会引入更多误检需要权衡。4.3 单类别数据集的划分比例与验证集独立性标题里说「包含训练集、验证集」但没给具体比例。常见做法是 8:2 或 7:3。单类别下验证集不能只放容易的样本要覆盖不同光照、不同叶片角度、不同缺陷程度。如果验证集和训练集来自同一批拍摄指标会偏高。我一般会按拍摄批次划分比如上午拍的做训练下午拍的做验证这样更能反映模型在新数据上的表现。验证集里必须包含负样本无缺陷叶片否则Precision会虚高。负样本不需要标签文件只要图像放在images/val下YOLOv5 在评估时会自动把没有对应labels/valtxt 的图像当作背景。但注意如果labels/val下有一个空的 txt 文件YOLOv5 会认为该图有标注但内容为空行为不一样。正确做法是负样本图像不要放对应的 txt 文件。5. 玉米叶片缺陷检测避坑5 条血泪经验5.1 现象训练 loss 正常下降但 mAP 始终为 0原因标签文件里的class_id不是 0或者data.yaml里nc写成了大于 1。单类别下nc必须是 1names长度必须是 1。如果标签里写了1作为类别 IDYOLOv5 会认为有第二类但names里没有导致所有预测都被过滤。解决检查所有 txt 文件第一列是否全为 0。用awk {print $1} labels/train/*.txt | sort -u快速查看。如果有非 0 值批量替换成 0。5.2 现象验证集 mAP 很高但实际推理时框出一堆背景原因验证集和训练集同分布且验证集里没有负样本。模型学会了「只要像叶片就框」而不是「只有缺陷才框」。解决验证集里混入 20% 无缺陷叶片重新评估。如果 mAP 下降明显说明模型泛化差需要增加训练集里负样本的比例或者在hyp里提高obj权重。5.3 现象训练到一半突然报 CUDA out of memory原因--cache ram把图像缓存到内存后如果数据集图像尺寸不一致YOLOv5 会在训练时动态 resize导致显存波动。另外mosaic增强会拼接 4 张图等效 batch 变大。解决关掉--cache或者把--batch-size降到 8。如果还不行把--img从 640 降到 512。单类别数据集通常不大关缓存对速度影响有限。5.4 现象推理时同一个缺陷被框了多个重叠框原因NMS 的iou-thres设得太高或者锚框尺寸和缺陷尺寸不匹配导致多个锚框都响应同一个目标。解决把--iou-thres从 0.45 降到 0.3。如果还不行用kmeans重新聚类锚框python utils/autoanchor.py --data corn_leaf_defect/data.yaml --img 640。单类别下锚框数量可以适当减少比如从 9 个降到 6 个。5.5 现象验证集指标波动大每次跑结果不一样原因单类别数据集样本量小随机划分验证集时如果某类难样本恰好分到验证集指标就会掉。另外--seed没固定数据加载顺序每次不同。解决固定随机种子--seed 42并且用分层抽样划分训练验证集确保缺陷程度分布一致。如果数据集本身小于 500 张建议用交叉验证而不是单次划分。6. 单类别检测的进阶技巧从能跑到好用单类别目标检测的进阶方向不是换更大的模型而是把数据质量和后处理做细。第一个技巧是难例挖掘用训练好的模型在训练集上跑推理把置信度在 0.1~0.3 之间的预测框对应的图像挑出来人工复核。这些是模型「犹豫」的样本重新标注后加入训练集通常能带来 3~5 个点的 mAP 提升。第二个技巧是测试时增强TTA在detect.py里加--augment对图像做翻转、缩放后分别推理再融合单类别下能提升召回率但速度会慢 2~3 倍适合离线批量处理。第三个技巧是锚框定制。YOLOv5 默认锚框是基于 COCO 的玉米叶片缺陷的宽高比和 COCO 目标差异大。用autoanchor重新聚类后把结果写回data/hyps/hyp_corn.yaml的anchors字段。我一般会跑三次autoanchor取best possible recall最高的那组。第四个技巧是推理时的conf-thres和iou-thres联合调参在验证集上跑一个网格搜索conf从 0.1 到 0.5 步长 0.05iou从 0.3 到 0.6 步长 0.05找 F1 最高的组合。这个组合往往和默认值差很远单类别下conf通常要降到 0.15~0.2 才能召回小病斑。最后一个习惯每次改完数据或超参数先跑 10 个 epoch 看 loss 曲线不要直接跑 200 轮。单类别数据集小10 轮就能看出趋势省下的时间用来检查标签质量。我踩过最大的坑就是标签里混了 30 张图把正常叶片标成了缺陷导致模型上线后误检率 40%回头查了两天才定位到。数据干净比模型大小重要得多。希望帮到你。本文还有配套的精品资源点击获取