简介面向目标检测任务与农业病害识别场景提供一份玉米叶片缺陷检测数据集共1个类别infected已按YOLOV5标准格式整理为训练集与验证集可直接用于模型训练与评估。压缩包共2000个文件其中1999个txt为边界框标注与类别信息1个py为可视化脚本整体包体约298.96MB。训练集包含1558张图片及对应标签验证集包含667张图片及对应标签图像为2000-3000分辨率的高清RGB图片标注清晰、背景完整适合培养农业图像检测实操能力。此外附带可视化脚本可直接读取任意图片并绘制边界框省去繁琐转换步骤便于快速检查标注效果。目前已有164人学习适合具备一定深度学习基础的开发者用于玉米叶缺陷检测算法研究、模型训练或毕设项目实验。1. 玉米叶片缺陷检测先别急着改模型拿到一份 YOLOv5 数据集很多人第一反应是打开data.yaml看一眼类别数就开训练结果 loss 降不下去、mAP 上不来最后怪模型不好。这份玉米叶片缺陷检测数据集单类别infected训练集 1558 张、验证集 667 张原始图像分辨率在 2000-3000 像素级别真正考验你的不是网络结构而是数据管线大分辨率图像如何缩放、标注框在小目标上的损失控制、以及可视化验证标注是否真的干净。对于做过目标检测但没碰过农业场景的工程师这份数据能让你把「数据质量决定模型上限」这句话落到实处对于刚开始用 YOLOv5 的新手它也是一个不需要做格式转换、直接能跑的入门级单类别项目。下面我按数据检查、训练配置、排错到推理可视化的顺序把每一步拆开讲。2. 数据结构与标注格式YOLOv5 目录约定和 txt 标签的真相2.1 目录结构为什么说「无需额外处理」YOLOv5 对数据集的组织方式有明确约定大多数开源项目能直接跑起来靠的就是目录名和文件摆放符合datasets的标准布局。这份玉米叶片数据集压缩后 298MB内部结构是datasets/ ├── images/ │ ├── train/ # 1558 张 jpg/png │ └── val/ # 667 张 jpg/png ├── labels/ │ ├── train/ # 1558 个 txt │ └── val/ # 667 个 txt ├── show.py └── 20200701_*.txtimages和labels下的train、val一一对应每张图片的同名.txt文件就是它的标注。根目录下那些20200701_080200.txt之类的文件看命名像是拍摄时的元数据或时间戳记录不是训练必需的标签文件训练时记得让 YOLOv5 只读取labels目录避免路径解析混乱。show.py是作者提供的可视化脚本随机传入一张图片就能把边界框画出来并保存到当前目录。我建议在你做任何训练之前先把这个脚本跑一遍不是为了看效果而是为了确认标注框和图像是否对齐——大分辨率图片在标注时容易发生坐标偏移这类问题只有可视化才能暴露。2.2 txt 标签的真实格式类别 ID 归一化坐标每个 txt 文件内容形如0 0.4825 0.3160 0.1240 0.0880 0 0.7102 0.5844 0.0931 0.0655这是一个多行文本每行代表一个目标框五个数值依次是类别ID、中心点x坐标、中心点y坐标、框宽w、框高h。注意这里全部是归一化坐标也就是实际像素坐标除以图像宽高后的比例值范围在 0~1 之间。这个数据集只有infected一个类别所以每行开头的数字永远是 0。如果你用 LabelImg 或 labelme 打开这些 txt会发现坐标是小数这并不表示标注精度低而是 YOLO 格式的固定要求。归一化坐标的优点是无论图像尺寸是多少模型输入时都可以直接使用不需要在数据加载阶段再做坐标换算。2.3 检查标签合法性的两个命令很多数据集下载下来会有空标签文件、类别 ID 越界或坐标归零的问题。训练前我习惯先做一次全量检查用 bash 一行命令就能完成# 检查 labels 目录下所有 txt 文件的行数是否有空文件 find datasets/labels/train -name *.txt -exec wc -l {} \; | awk $10{print $2} | head -20 # 检查是否有类别 ID 超过 0 的情况单类别数据集中不应出现其他 ID grep -R ^[1-9] datasets/labels/train | head -20第一条命令找出空文件如果某个 txt 里没有任何标注那这张图在训练时会被当作背景图大量空文件会导致模型偏向输出低置信度。第二条命令检查类别 ID如果出现数字 1说明标注工具导出了错误类别需要重新处理。对于这份玉米叶片数据集正常情况两条命令都不应该有任何输出。3. 训练配置大分辨率图像下的 batch、imgsz 和锚框策略3.1 数据配置文件 data.yaml 的写法YOLOv5 训练前需要一个data.yaml指向训练集和验证集的图片路径并声明类别列表。这份数据集没有提供现成的 yaml需要自己创建。常见做法是放在数据集根目录下内容如下# data.yaml train: datasets/images/train val: datasets/images/val nc: 1 names: [infected]train和val的路径可以是相对路径也可以是绝对路径。如果你把数据集放在和 YOLOv5 项目同级的目录下datasets/images/train这种相对路径在运行train.py时就能解析。nc表示类别数这里为 1names是类别名列表顺序必须和 txt 中的类别 ID 一一对应即第 0 位对应infected。3.2 训练命令中的关键参数大分辨率图像是本数据集的显著特点。2000-3000 像素的原始图如果直接送入 YOLOv5 默认的imgsz640相当于把宽高缩放到原来的四分之一到五分之一。玉米叶片上的缺陷区域本身在整幅图中占比就小缩放后可能只剩几个像素模型很难学到有效的特征。我建议根据标注框的尺寸分布选择imgsz。先统计一下所有标注框的相对尺寸# 统计标注框尺寸分布 import os import numpy as np label_dir datasets/labels/train all_wh [] for f in os.listdir(label_dir): with open(os.path.join(label_dir, f)) as fp: lines fp.readlines() for line in lines: parts line.strip().split() if len(parts) 5: w float(parts[3]) h float(parts[4]) all_wh.append([w, h]) all_wh np.array(all_wh) * 2000 # 按 2000 像素估算实际框尺寸 print(框宽中位数:, np.median(all_wh[:, 0])) print(框高中位数:, np.median(all_wh[:, 1])) print(最大框尺寸:, all_wh.max(axis0))如果中位数框宽高在 100-200 像素之间说明目标相对较大用imgsz1280训练能保留细节如果中位数在 50 像素以下就需要考虑imgsz1536甚至更高但显存消耗会急剧上升。对于这份数据我实测在单张 24GB 显存的显卡上imgsz1280配合 batch size 8 是可以跑的。训练命令参考python train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 8 --epochs 100 --device 0 --name corn_defect参数说明--img是输入图像尺寸YOLOv5 会按这个值做等比缩放并用灰边填充而不是直接拉伸--batch是每次迭代的样本数大分辨率下显存是主要瓶颈可以先从 4 开始试观察显存余量再往上加--epochs对于小数据集一般 100 轮足够超过 150 轮容易过拟合--weights yolov5s.pt是预训练权重使用 COCO 上的预训练模型做迁移学习能显著加快收敛。--name指定实验名输出的模型和日志会保存在runs/train/corn_defect下。3.3 锚框自动调整不要让默认锚框拖后腿YOLOv5 默认的锚框尺寸是在 COCO 数据集上统计得到的COCO 包含 80 类物体小目标多锚框偏小。对于玉米叶片缺陷这种目标可能尺寸跨度大的场景我强烈建议开启自动锚框计算。在训练命令中加一行--noautoanchor # 不要加这个参数默认情况下 YOLOv5 会在训练前自动用 k-means 算法重新聚类你的标注框生成适合当前数据集的锚框。在训练日志中你会看到类似AutoAnchor: 6.24 anchors/target, 0.995 Best Possible Recall的输出Best Possible Recall接近 1 表示锚框设置合理。只有一种情况需要手动干预如果自动锚框计算出的召回率低于 0.9说明你的数据集目标尺寸分布太不均匀此时建议手动将锚框分为两组分别针对大框和小框。在models/yolov5s.yaml中可以看到默认锚框anchors: - [10,13, 16,30, 33,23] # P3/8 - [30,61, 62,45, 59,119] # P4/16 - [116,90, 156,198, 373,326] # P5/32P3/8表示这一组锚框作用于 8 倍下采样的特征层适合小目标P5/32作用于 32 倍下采样的特征层适合大目标。训练时如果发现 mAP 偏低可以检查runs/train/corn_defect/opt.yaml中的锚框是否已被更新没有更新说明你的 YOLOv5 版本默认关闭了自动锚框。4. 训练过程监控与过拟合处理loss 曲线、验证指标和早停策略4.1 训练日志中真正需要关注的指标训练开始后终端会每一轮打印一组指标比如Epoch gpu_mem box obj cls labels img_size 1/100 6.21G 0.0732 0.0421 0 17 1280对单类别检测clsloss 一直是 0 是正常的因为你只有一个类别分类分支没有区分压力。真正需要关注的是boxloss 和objloss。boxloss 下降说明边界框回归在收敛objloss 反映目标置信度如果这个值在训练后期震荡大概率是正负样本不平衡——背景区域太多阳性目标太少。验证集指标会在每个 epoch 结束后的验证阶段输出Validating... 0.516 mAP0.5, 0.413 mAP0.5:0.95mAP0.5是 IoU 阈值 0.5 时的平均精度对于缺陷检测任务这个值在 0.75 以上算是可用mAP0.5:0.95是更严格的指标要求预测框和真实框的重合度从 0.5 到 0.95 平均。两者差距过大比如 0.8 vs 0.3通常说明框的位置不够精确需要调高iou损失权重或增加训练轮数。4.2 提前停止与模型选择YOLOv5 支持早停机制配置在训练命令中python train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 8 --epochs 200 --patience 20 --device 0--patience 20表示如果连续 20 个 epoch 验证集的mAP0.5:0.95都没有提升训练自动终止。对于这份玉米数据集我遇到过在第 70 轮左右 mAP 达到峰值继续训练反而下降的情况。所以不要盲目跑到 200 轮早停能节省大量时间。训练结束后YOLOv5 会在runs/train/corn_defect/weights/下保存两个文件best.pt和last.pt。best.pt是根据验证集 mAP 选出的最优权重后续验证和推理都用这个文件。4.3 大分辨率训练时常见的显存溢出与解决方法--img 1280 --batch 16在 24GB 显存上可能直接报CUDA out of memory。这时不要急着换小模型有几个更有效的思路。启用梯度累积模拟更大的 batchpython train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 4 --epochs 100 --device 0 --nbs 16--nbs是名义 batch sizeYOLOv5 会自动计算梯度累积步数accumulate nbs / batch这里16/44即每 4 步累积一次梯度等效于 batch size 16 的效果。代价是训练时间变长但能保持 batch 统计量的稳定性。另一种方案是开启--multi-scale让模型在训练时随机缩放输入尺寸python train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 8 --multi-scale --device 0--multi-scale会让图像尺寸在imgsz * 0.5到imgsz * 1.5之间随机变化相当于数据增强的一种也能间接缓解显存压力不过如果原本已经接近显存上限依然会溢出。建议先把--img降到 960看看 mAP 损失是否在可接受范围内。5. 可视化验证一个完整技巧把推理结果叠加到原始大图上检查定位精度5.1 使用训练好的模型生成可视化结果训练完成后不要急着用detect.py跑完就结束。我习惯写一个独立的验证脚本将模型输出的预测框坐标映射回原始分辨率并和真实标签画在同一张图上这样能直观看出模型在哪类样本上漏检、在哪类样本上虚检。下面是一个基于 YOLOv5 官方 API 的脚本# visualize_predictions.py import torch import cv2 import numpy as np from pathlib import Path model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/corn_defect/weights/best.pt, force_reloadTrue) model.conf 0.25 # 置信度阈值 model.iou 0.45 # NMS IoU 阈值 img_path datasets/images/val/20200701_094816.jpg img cv2.imread(str(img_path)) orig_h, orig_w img.shape[:2] # 模型推理返回结果对象 results model(img_path, size1280) # 获取预测框的归一化坐标再映射回原图 pred results.pred[0].cpu().numpy() # [x1, y1, x2, y2, conf, cls] for box in pred: x1, y1, x2, y2 box[:4].astype(int) conf box[4] cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(img, finfected {conf:.2f}, (x1, max(0, y1-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) # 读取真实标签绘制绿色框 label_path Path(img_path).with_suffix(.txt) label_path Path(datasets/labels/val) / label_path.name with open(label_path) as f: for line in f.readlines(): parts line.strip().split() cx, cy, w, h map(float, parts[1:]) x1 int((cx - w/2) * orig_w) y1 int((cy - h/2) * orig_h) x2 int((cx w/2) * orig_w) y2 int((cy h/2) * orig_h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(comparison_result.jpg, img) print(Saved to comparison_result.jpg)这段代码的逻辑分为三步加载训练好的权重对指定图片做尺度为 1280 的推理将预测框和真实框分别用红绿两色绘制最终保存对比图。注意results.pred[0]的坐标已经在内部被映射回输入图像的原始分辨率因此可以直接叠加到用 OpenCV 读取的原图上无需手动缩放。绿色和红色重叠的部分是检测正确的位置只有绿色缺少红色的区域是模型的漏检只有红色没有绿色的区域则是虚检。5.2 根据可视化结果调整 conf 和 iou 阈值如果发现漏检较多可以把model.conf降到 0.15这时检测框数量会增加同时也会带来更多误检如果虚检较多则调到 0.4。一般情况下conf0.25、iou0.45是 YOLOv5 的默认组合但对于缺陷检测场景缺陷通常要求尽量少漏检我会把conf放宽到 0.2iou保持 0.45。在可视化对比图上还有一个更实用的用法把预测框和真实框的 IoU 低于 0.5 的样本单独收集起来这些是模型最困惑的样本。收集一批这样的图像重新标注或调整数据增强策略往往比盲目增加训练轮数更能提升 mAP。比如玉米叶片图像中叶片边缘的阴影常被误检为缺陷处理方式是增加一些包含阴影的负样本或者在hyp.yaml中调高hsv_h、hsv_s的增强幅度让模型对颜色变化更鲁棒。hyp.yaml中关于颜色增强的参数hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4调高hsv_s到 0.9可以让模型在训练时看到更多饱和度变化不过同时也会增加训练难度需要观察 mAP 变化来决定是否保留。本文还有配套的精品资源点击获取