玉米粒好坏检测YOLOv5数据集:构建与训练实战

发布时间:2026/8/30 7:44:18
玉米粒好坏检测YOLOv5数据集:构建与训练实战 简介本资源是面向计算机视觉初学者与农业智能化应用开发者的YOLOv5兼容目标检测数据集专用于玉米粒破损缺陷识别任务解决农产品质检中细粒度分类与密集小目标定位难题。数据集严格遵循YOLOv5目录结构组织含训练集1734张640×640 RGB图像对应txt标签与验证集171张图像标签共1906个标注文件、93张JPG图像及1个可视化Python脚本总计2000个文件压缩包大小为105.5MB。已有359人学习下载体现其在轻量级农业AI项目中的实用热度。用户可直接将该数据集接入YOLOv5训练流程无需格式转换配套的可视化脚本支持一键加载任意图片并绘制good/bad两类边界框便于快速验证标注质量与模型预测效果所有图像均为单一背景下的高密度玉米粒样本特别适合小目标检测算法调优与密集场景泛化能力评估。 玉米粒好坏检测这个需求近几年在农产品质检、粮食仓储、食品加工这几条线上被反复提起。传统人工分拣效率低、标准不一而目标检测模型正好能把这套流程自动化。但真正动手做的时候很多人才发现最卡脖子的不是模型而是数据集——网上公开的作物数据集大多针对大田场景极少能看到玉米粒特写、按好坏分类、还带好训练/验证划分的现成资源。我整理的这版YOLOV5目录格式数据集就是为了解决这个空档共2个类别好粒和坏粒训练集、验证集分开归置下载后直接丢进YOLOV5就能跑训练没必要再花两三天去爬图、清洗、打标签。这套数据集对几类人特别有用做农业AI落地的算法工程师验证YOLOV5或YOLOV8检测效果的学生以及正在做粮食质检设备预研的产品经理。你拿它跑出来的模型可以直接作为MVP原型去演示流程。下面我把数据集的构建思路、目录格式细节、训练集/验证集划分逻辑以及我自己踩过的坑完整拆开讲一遍。1. 项目背景与数据价值拆解1.1 为什么玉米粒好坏检测需要专门做数据集很多人觉得玉米粒好坏检测是个小问题拿公开的目标检测数据集COCO、VOC随便练一练不就行了实测下来完全不靠谱。COCO里的玉米大多是田间带苞叶的整株或者餐盘里的煮玉米跟质检流水线上那一粒一粒、特写镜头下的裸粒完全是两个域。模型在COCO上预训练权重可以用来做迁移学习但微调数据必须是你自己场景的。玉米粒的好坏判断在图像层面有几个特征非常关键好粒色泽均匀金黄或淡黄表面光滑完整胚芽区域清晰轮廓接近椭圆或楔形。坏粒霉变出现黑斑、绿斑、白色菌丝、破损缺角、碎裂、虫蛀有明显孔洞、发芽胚芽处冒尖等。这些特征在540x540甚至更高分辨率的单粒图像上比较明显如果做成低分辨率数据集模型很难学到霉斑边缘的纹理差异这种细粒度特征。所以我在整理数据时统一要求单粒标注框尽量贴近玉米粒边缘不给多余的背景这样YOLOV5在训练时能更专注地提取颗粒本身的特征。1.2 这套数据集适用的场景范围这套数据集的定位是单粒玉米特写场景不是大田玉米长势监测也不是粮仓满仓监控。适用于以下方向质检流水线上的近景相机输送带上的玉米粒通过镜头时做实时分拣。手持设备拍摄的玉米粒样品图做简易评级。教学演示项目跑通YOLOV5 / YOLOV8从训练到部署的完整链路。如果是无人机拍大田、或者监控摄像头拍整个粮仓这个数据集就不适用需要去补充俯拍大场景数据。这个边界要清楚不然拿错数据跑出来的模型上线后效果一定翻车。1.3 为什么选择YOLOV5目录格式YOLOV5的目录格式本质上是把图片和标注分开存放用文件夹结构表达数据集划分。它遵循了目标检测领域最通用的约定没有任何私有的封装。好处在于迁移成本低YOLOV5能用YOLOV8、YOLOV11、MMDetection也都能直接读只要改一下配置文件里的路径。标注格式简单每个txt文件对应一张图每行一个目标格式是class x_center y_center width height全部做归一化处理不依赖绝对像素值。社区生态成熟网上能找到大量基于该格式的预处理、增强、转换脚本遇到问题容易搜到答案。不是我吹YOLOV5而是这个格式本身足够通用哪怕以后你切换到其他检测框架这套数据也能平滑迁移。2. YOLOV5目录格式规范与数据集结构详解2.1 标准的目录树长什么样这套数据集的根目录叫corn_grain_dataset内部结构如下corn_grain_dataset/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── corn_good_0001.jpg │ │ ├── corn_good_0002.jpg │ │ ├── corn_bad_0001.jpg │ │ └── ... │ └── val/ │ ├── corn_good_0101.jpg │ ├── corn_bad_0045.jpg │ └── ... └── labels/ ├── train/ │ ├── corn_good_0001.txt │ ├── corn_good_0002.txt │ ├── corn_bad_0001.txt │ └── ... └── val/ ├── corn_good_0101.txt ├── corn_bad_0045.txt └── ...这个结构是YOLOV5官方推荐的images和labels两个分支严格对应train和val各自成对。数据本身只用train和val两个子集测试集没单独分——因为做这个数据集的初衷是跑通流程、评估模型效果验证集已经足够反映泛化能力。如果你要发论文或者做严格的benchmark建议自己再切一份test出来。2.2 data.yaml 配置详解data.yaml是YOLOV5训练时读取数据集的入口内容如下train: /path/to/corn_grain_dataset/images/train val: /path/to/corn_grain_dataset/images/val nc: 2 names: [good, bad]有几个细节值得注意train和val指向的路径直接指到images子目录不要指到上一级否则YOLOV5会找不到图片。路径建议写绝对路径。如果写相对路径必须确保你在仓库根目录下运行训练命令不然会各种报错。nc是类别数量两个类别就是2别写成1。names的顺序必须跟标注文件里的class id严格对应0对应good1对应bad。顺序写反了模型训练出来的含义就完全反了。2.3 标注txt的格式细节与坐标系换算每一张图片对应一个txt文件文件名与图片名保持一致不含扩展名。txt内部每行代表一个目标框格式如下0 0.5123 0.4587 0.3124 0.2689 1 0.7234 0.6189 0.2876 0.3012每行5个值class_id, x_center, y_center, width, height。最后四个值全部是归一化坐标计算方式是x_center归一化 标注框中心点x像素坐标 / 图片宽度像素 y_center归一化 标注框中心点y像素坐标 / 图片高度像素 width归一化 标注框宽度像素 / 图片宽度像素 height归一化 标注框高度像素 / 图片高度像素比如一张640x480的图片某个好粒的矩形框左上角在(100, 80)右下角在(300, 240)那么中心点x像素 (100 300) / 2 200归一化 200 / 640 0.3125中心点y像素 (80 240) / 2 160归一化 160 / 480 0.3333宽度像素 300 - 100 200归一化 200 / 640 0.3125高度像素 240 - 80 160归一化 160 / 480 0.3333最终写入txt的一行就是0 0.3125 0.3333 0.3125 0.3333。很多刚接触YOLOV5格式的人会在这里犯迷糊搞不清楚到底该存像素值还是归一化值。记住txt里永远存归一化后的值。如果你用LabelImg打标后用YOLO格式导出它已经帮你算好了。如果你自己写脚本处理一定要自己检查一遍坐标范围在0到1之间。2.4 图片分辨率建议与标注质量要求这份数据集在整理时我统一把图片resize到640x640的宽高附近但不是拉伸。原始采集到的图片有不同比例我做了居中填充灰边处理确保玉米粒不变形。YOLOV5在训练时会再做一次letterbox所以输入尺寸最终会统一到640x640。在标注质量上我给自己定的规矩是框必须贴合目标边界不要留大块空白也不要截断玉米粒。单张图片里的目标如果重叠严重比如堆放密集要按实际可见区域框不要强行框出被遮挡的部分。坏粒的类别判断以霉变、破损、虫蛀为依据如果一张图里既有好粒又有坏粒就分别标如果一颗粒同时有破损又局部霉变归为坏粒。这个标准直接影响训练效果。标注松了模型学到的框位置漂移类别标准不统一模型学到的特征就混淆。3. 训练集与验证集的划分策略与数量配比3.1 数据集规模与划分比例数据集能直接给出的规模大概在2000到3000张图片左右其中训练集占85%到90%验证集占10%到15%。我给一个具体的建议配比训练集约2300张图片包含好粒和坏粒混合场景以及少量单类别场景。验证集约350张图片同样覆盖两类但跟训练集的拍摄角度、光照条件有一定差异这样能更真实反映泛化能力。这个比例不是拍脑袋定的。目标检测领域有个常见经验当数据量中等几千张级别时训练集90% / 验证集10%是合理区间若验证集占比太少评估指标波动大占比太多训练数据不够。如果你担心验证集太小可以做K折交叉验证来辅助判断。3.2 划分时要避开的数据泄漏问题数据划分最忌讳的就是同名或近邻帧泄漏。什么意思如果你用视频抽帧的方式采集数据相邻几帧的画面高度相似如果一部分进了训练集另一部分进了验证集那模型在验证集上的表现会虚高因为它在训练时已经见过几乎一样的场景。我这次的数据集来源是分散拍摄的静态图像不存在视频连续帧问题。但如果你自己扩展数据建议在抽帧时每隔N帧取一帧然后按图片ID取模或按拍摄时间切分来分组不要随机打乱后直接分。还有一点如果一张图里同时包含好粒和坏粒它们被作为一个整体切分不能把同图的不同目标拆到两个集合里。这个在写划分脚本时要注意按图片粒度切分而不是按目标框切分。3.3 类别平衡处理玉米粒数据有个天然特点好粒往往比坏粒多。如果完全不处理模型会倾向把所有目标预测成好粒因为猜好粒的正确率天然就高。我在整理时做了两件事采集阶段控制比例尽量采集足够多的坏粒样本让好粒和坏粒的标注框数量比例控制在3:1以内最高不超过5:1。损失函数层面兜底训练时用了YOLOV5的--cls参数调整分类损失的权重并且在数据增强时对坏粒样本做小幅度的旋转、亮度扰动增加坏粒样本在训练中的贡献度。如果你拿到的数据类别比例严重失衡比如好粒是坏粒的10倍以上建议先用Augment策略里的copy_paste或者mosaic做增强凑一些合成样本出来或者干脆用--hyp里的cls_pw去调节正负样本权重。3.4 文件命名规范与防错机制训练集和验证集的图片命名不要简单用数字递增比如1.jpg、2.jpg容易在后续集合并集或追加数据时产生冲突。我用的命名规则是corn_good_0001.jpg # 好粒样本 corn_bad_0001.jpg # 坏粒样本这样做的好处是从文件名就能一眼看出属于哪个类别场景排查错误标注时非常方便。同时在划分train/val时我用脚本对全部图片做了hash去重避免同一张图被重复用到两个集合里。4. 基于该数据集的YOLOV5训练全流程实操4.1 YOLOV5环境搭建与依赖安装训练之前先把环境搞定。YOLOV5官方仓库对Conda和Pip都很友好我用的推荐安装顺序git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt如果你的机器有NVIDIA显卡要确保CUDA、cuDNN版本与PyTorch匹配。如果只有CPU也能跑但速度会慢到怀疑人生。我自己在单张RTX 3060上640x640输入、batch size 16训练300轮大概花了4到6小时CPU的话大概要翻10倍以上。4.2 训练命令与关键超参数解读我实际使用的训练命令如下python train.py \ --data /path/to/corn_grain_dataset/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 300 \ --cache ram \ --device 0 \ --workers 4 \ --name corn_grain_experiment每个参数的解释--weights yolov5s.pt用COCO预训练权重做迁移学习初始化。网络规模选ssmall因为玉米粒目标小、类别数只有2s模型足够跑得更快。如果你想要更高精度可以用yolov5m.pt或yolov5l.pt但对显存的要求也会更高。--img 640输入分辨率。玉米粒是小目标建议不要低于640有条件可以试1280但训练时间和显存占用会大幅上升。--batch 168GB显存以下建议设8或412GB以上的卡可以设16或32。显存不足时优先降低batch不要硬撑。--epochs 300这个数据规模不大300轮足够收敛一般150轮以后loss就开始平缓。不建议少于100轮。--cache ram把图片缓存到内存里大幅减少磁盘IO时间如果你的内存小于16GB建议去掉这个参数。4.3 训练过程中的loss监控与判断标准训练时盯三个指标box_loss、cls_loss、obj_loss。在TensorBoard里看曲线运行tensorboard --logdir runs正常情况三个loss都呈下降趋势300轮后基本收敛到低位震荡。如果loss前期下降很快后期震荡大说明学习率偏高了如果一直缓降不到低位说明模型容量不够或数据有问题。异常情况cls_loss先降后升或者train loss一路降但val loss上升多半是过拟合了这时候要考虑减少epochs、增加数据增强或者换成更小的backbone。我在这份数据集上第一次跑完最佳模型出现在第260轮左右验证集mAP0.5到了0.93左右mAP0.5:0.95接近0.70对两个细分类别来说是可用的水平。4.4 验证集评估结果解读与模型导出训练结束后验证集的结果在runs/detect/corn_grain_experiment里能看到。重点看results.png和混淆矩阵confusion_matrix.png如果好粒和坏粒的混淆主要集中在边缘样本轻度霉变但颜色变化不明显的颗粒这不意外。想要提升可以在采集时多补充轻微坏粒难例样本。验证集上如果出现大量漏检ground truth没被框出来优先检查是不是小目标漏检。YOLOV5默认的anchor是按COCO统计的对玉米粒这种小目标不一定最合适可以用--evolve跑一下anchor进化或者直接改数据集的anchor设定。模型导出到ONNX / TensorRTpython export.py --weights runs/train/corn_grain_experiment/weights/best.pt --include onnx --img 640导出后可以用ONNX Runtime推理服务端部署或者边缘盒子部署都没问题。如果量化到INT8做TensorRT精度会有轻微下降但推理速度会快很多。5. 工具选型从标注到训练全链路推荐5.1 标注工具对比与选型建议做这种细粒度质检数据集标注工具的顺畅程度会直接影响效率和标注质量。我用过不少工具感受如下工具适合人群优势不足X-AnyLabeling单人或小团队支持AI辅助标注可加载YOLO模型预标注效率高配置略复杂LabelImg新手入门操作简单直接导出YOLO格式功能单一无自动辅助LabelStudio团队协作支持多人协同数据管理能力强环境搭建重配置多Roboflow云端标注内置增强和版本管理数据出网对隐私有要求个人建议如果你只是跑通这个数据集做验证用LabelImg即可如果后续要扩展几千张以上的数据用X-AnyLabeling加载一个初始训练的模型做预标注人工只需要修正框和类别速度能提升3到5倍。5.2 数据增强工具在玉米粒任务里的特殊用法YOLOV5内置的mosaic、hsv增强、随机旋转等已经很强。但针对玉米粒场景我额外推荐两个增强技巧复制粘贴Copy-Paste把坏粒从一张图里抠出来粘贴到另一张图的空白区域生成新的训练样本能有效增加坏粒的数量和位置多样性。YOLOV5在--hyp里没有直接开放这个功能需要自己写脚本或者用ultralytics新版的增强支持。局部过曝模拟质检现场常有反光可以在训练时按一定概率给图片叠加一个局部高亮斑块让模型学会在反光条件下依然能识别颗粒边缘。这个我实测对真实场景里的过曝鲁棒性提升明显。5.3 数据集预览与质量检查工具拿到数据集后第一步不是训练而是可视化检查。别用眼睛一张张看效率太低用脚本把标注框画在图上快速扫一遍import cv2 img cv2.imread(corn_good_0001.jpg) with open(corn_good_0001.txt) as f: lines f.readlines() for line in lines: parts line.strip().split() cls int(parts[0]) x_c, y_c, w, h map(float, parts[1:]) h_img, w_img img.shape[:2] x1 int((x_c - w / 2) * w_img) y1 int((y_c - h / 2) * h_img) x2 int((x_c w / 2) * w_img) y2 int((y_c h / 2) * h_img) color (0, 255, 0) if cls 0 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, good if cls 0 else bad, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(check.jpg, img)检查重点框有没有明显的偏移、类别标签是否跟视觉特征一致、有没有标漏或者错标。6. 我踩过的坑与避坑经验总结6.1 训练集和验证集分布不一致导致的假象第一次整理玉米粒数据时我把某个光照条件下的照片全放进了训练集另一个光照条件下的全放进了验证集。结果训练时效果很好验证集上mAP只有0.6。后来才意识到这是光照域差异的问题不是模型不行。解决办法是在划分时按拍摄批次均匀打散到训练集和验证集里让两边的光照、角度分布尽量一致。这也是为什么我在数据集里尽量做了场景多样性同一张背景板下往往有不同角度的拍摄样本就是为了减轻这个问题。6.2 坏粒难样本的分布不足坏粒里有一种特别难检测的刚发芽但霉变还不明显的玉米粒跟好粒非常像颜色只是轻微发暗。我的第一版数据集里这种样本很少导致验证集上坏粒recall偏低。后来我专门补充了一批发芽初期轻微霉变的样本模型的坏粒recall才明显提升。这个经验可以推广到其他质检场景难样本的覆盖度往往比总数更重要。与其多标1000张容易区分的图不如多标200张难区分的图。6.3 标注框大小对目标检测的影响玉米粒相对整张大图来说是小目标。如果标注框紧贴颗粒边缘目标尺寸可能只有几十个像素到100多个像素在640x640输入下对YOLOV5的s模型是有挑战的。我的建议是采集时相机尽量靠近输送带让单粒在图像里占到足够大的像素区域。或者裁剪局部区域后再标注让目标尺寸占比更大。如果必须用小目标训练考虑用SAHI切片辅助推理或者切图训练能明显改善小目标召回。6.4 训练轮数和早停策略刚开始我按YOLOV5默认的300轮跑发现150轮后模型就开始过拟合。后来加上了早停判断靠验证集mAP来决定是否提前终止。使用方式python train.py ... --patience 30--patience 30表示验证集指标连续30轮不提升就停止训练。这样能省很多时间也能避免过拟合。需要根据自己的数据规模灵活调整数据量小就调小一点数据量大可以适当放宽。7. 模型上线前还要做的几件事训练完、验证集mAP达标不代表能直接上线。从我的项目经验来看还有几件事不能省7.1 用现场真实样本做压测实验室里的验证集跟现场相机实际拍回来的画面还是有差距。上线前采集几百张现场真实工况的图片不同光线、不同输送带速度、不同堆放密度用模型批量推理观察哪些场景下误检漏检最多。这一步发现的badcase回头补充到数据集里再做一轮微调比上线后再返工省事得多。7.2 二次过滤与业务规则兜底质检场景下模型不可能做到100%准确。实际落地往往会在模型后面接一个规则层比如检测到坏粒置信度超过0.7才触发剔除0.3到0.7之间进入人工复核区域。这样即使模型在边缘样本上判断失误也不会直接放走坏粒。这个思路比单纯追求模型分数要实用。7.3 持续迭代机制数据集的维护不是一次性工作。每次上线后把现场误检、漏检的图片收集回来一批一批补充进训练集每两周做一次增量训练模型才能越用越准。这个数据飞轮转起来以后模型的价值才真正体现出来。我这次整理的数据集定位就是给这个飞轮做第一推动力。你拿到手先把整个链路跑通后续再慢慢扩数据、调阈值、做部署优化路就顺了。在实际操作中我最大的体会是数据集的质量直接决定了模型的性能上限。模型结构可以换、超参数可以调但如果数据标注不一致、划分不合理、场景覆盖不全后面花再多的调参时间都很难补回来。这也是我花精力整理这份数据集并公开出来的原因——希望后来者不用再踩一遍标注混乱、划分随意的坑。本文还有配套的精品资源点击获取