资讯动态

玉米好坏检测数据集实战:COCO格式标注、切分与训练避坑

发布时间:2026/10/9 22:36:53 来源:尧图企业网站定制
简介面向玉米品质检测与农业视觉识别场景的玉米好坏检测数据集适合目标检测、图像分类等深度学习项目开发者使用。资源对2357张玉米图片进行了COCO格式的人工标注平均标注准确率在89.5%以上可直接用于深度学习模型训练、验证与对比实验标注内容包括类别名称与目标边界框坐标TXT文件进一步给出类别与数据组织说明。压缩包内共有2000个文件以1995张JPG原图为主体配以3个JSON标注文件和2个TXT说明文件压缩包整体约122.84MB目录结构简洁清晰便于快速接入主流目标检测框架。文件名保留了拍摄时间信息便于按批次划分训练集与验证集。目前已有393人学习下载对需要真实农业图像样本的入门及进阶学习者来说都是具有参考价值的数据基础。1. 玉米好坏检测的第一步往往卡在数据集而不是模型做农产品外观质检的第一步往往不是选模型而是先回答一个问题什么样的玉米算坏坏到什么程度要剔除。这个玉米好坏检测数据集把回答装进了一个 zip2357 张真实玉米图片全部经过人工标注输出成 COCO 格式训练出来的检测模型平均准确率在 89.5% 以上。它真正解决的痛点是你不用再带着几十张没标准的手机图去帮模型定义“坏玉米”。我接触农产品质检项目这几年最深的感受是模型选型翻来覆去就那几种真正拉开项目进度的是数据标注的边界和格式。这份数据集的适用场景很明确玉米分级、入库质检、分选线剔除次品。它适合两类人——一类是要快速跑通玉米分选算法的工程师另一类是正准备搭质检数据流程、需要参考标注规范的团队。下面按拿到 zip 之后的实际操作顺序把数据核验、标注复检、训练配置、避坑经验串成一条完整链路。2. 拿到手先看三件事类别边界、COCO 结构、2357 张图到底顶不顶用2.1 好坏玉米的类别标注不能拍脑袋good/bad 的边界得写进标注手册“好坏检测”这四个字落地到标注环节时背后是两种完全不同的数据集设计。第一种设计是只给坏玉米画框类别名叫 bad正常玉米不出现任何标注模型默认“没有被框住的就是好”。这种方案标注工作量小适合在线剔除场景算法一旦检出坏框就把它从分选线上踢出去。第二种设计是 good 和 bad 两类都画框每一根玉米都必须出现在标注里不管是好是坏。这种方案对计数和统计场景更友好但标注量几乎翻倍。这个数据集的名称听起来像是“好坏都标”的二类方向。实际操作里我一般更倾向于把“坏”再细分一层霉变、破损、虫蛀。因为分选线末端需要按不同缺陷做不同处理混在一个大类里会损失信息但如果任务本身只需要一个好坏阈值细分类会导致每个子类样本量不够反而不如二分类稳。真正决定数据集价值的是标注规范里关于“灰色地带”的定义。比如玉米表皮局部变色算不算坏、霉斑面积小于整粒 5% 算不算坏、轻微压伤要不要框。这些边界不写清楚同一个标注项目里两个人画出来的框可能差异非常大。我习惯在标准里加三条硬约定第一霉斑区域必须完整包进框宁可外扩不可切到霉斑中心第二同一张图里有多个玉米每一个都要画框不允许挑着标第三框沿贴着玉米轮廓比玉米实际轮廓多出的背景不超过 3 个像素。这套约定能显著降低后续复检的成本。2.2 COCO 格式的取舍为什么选它、以及最容易错的一个字段COCO 格式本质上是一个 JSON 文件核心由 images、annotations、categories 三块组成。images 数组存每张图的 id、宽高、文件名annotations 数组存每个目标框的类别和坐标categories 数组定义类别列表。这个格式之所以在目标检测里成为主流直接原因是生态开源检测框架大多内置了 CocoDataset 加载器拿到 JSON 后指定路径就能开始训练。第二个好处是扩展性。现在只画了边界框如果后面想把任务升级成玉米实例分割只需要在原有标注基础上补 polygon 字段不需要推翻整个文件结构。第三个好处是合并和拆分的灵活性数据不够时两个 COCO 数据集可以在 JSON 层面直接拼接类别 id 重新映射后合并训练就行。但 COCO 格式有一个字段特别容易翻车bbox。它的定义是[x, y, width, height]指的是框左上角的坐标和框的宽高。很多从分类任务转过来的同事会下意识把 bbox 写成两个对角点[x1, y1, x2, y2]。这个错误在训练时通常不会报错只会导致模型面对完全错误的坐标回归目标最后验证 mAP 低到怀疑人生。所以拿到数据集之后第一件事不是解压看了多少张图而是先把所有 bbox 的合法性跑一遍检查——这部分在下一章会给可直接复制的脚本。2.3 数据规模判断2357 张图在新环境里的有效性与底线要说清楚 2357 张图够不够用先得把“够用”拆成两个维度目标实例总量和场景多样性。玉米检测里单张图平均会有 2 到 4 个目标2357 张图大约对应 5000 到 9000 个标注实例。对一个二分类检测任务来说这个规模足够让 Faster R-CNN 或 YOLO 收敛出一个可用的 baseline前提是类别比例没有严重失衡。真正会让数据集缩水的是“拍摄环境单一”。如果 2357 张图全部来自同一条固定产线、同一个机位、同一批玉米相邻图片的背景几乎一致那么模型学到的可能是光线分布而不是玉米本身的状态。放到真实现场换一个光源或者换一台相机准确率就会掉下去。所以我处理任何检测数据的第一步都是按拍摄批次给图片打上 group 标记然后可视化抽样检查随机抽 100 张如果背景几乎都是同一条传送带就要在后续切分时把批次信息用上。这个细节直接关系到第 4 章的训练集划分方式也直接决定了 89.5% 这个指标能不能在你自己环境里复现。3. 解压 zip 后的三个动作核验标注、检查图片、复检人工质量3.1 用一段检查脚本把“图片-标注”对应关系一次性核完从 zip 解压出来的目录常见结构是 images 文件夹放图片annotations 文件夹放 JSON 标注。第一次处理时不要急着写训练代码先跑一个完整性检查。这段脚本不依赖任何训练框架只要有 Python 和 Pillow 就能跑import json from pathlib import Path from PIL import Image ann_path Path(annotations/instances_train.json) img_dir Path(images) with open(ann_path, r, encodingutf-8) as f: data json.load(f) cat_ids {c[id]: c[name] for c in data[categories]} img_map {im[id]: im for im in data[images]} error_list [] for ann in data[annotations]: img img_map.get(ann[image_id]) if img is None: error_list.append(fannotation {ann[id]} 找不到对应图片) continue x, y, w, h ann[bbox] if w 0 or h 0: error_list.append(fannotation {ann[id]} 的 bbox 宽高必须为正) if x 0 or y 0 or x w img[width] or y h img[height]: error_list.append(fannotation {ann[id]} 的 bbox 超出图像边界) if ann[category_id] not in cat_ids: error_list.append(fannotation {ann[id]} 包含未定义的 category_id) # 检查图片文件是否损坏 for im in data[images]: img_path img_dir / im[file_name] try: with Image.open(img_path) as f: f.verify() except Exception: error_list.append(f图片损坏或无法打开: {im[file_name]}) print(f共检查 {len(data[images])} 张图像、{len(data[annotations])} 个标注) if error_list: for e in error_list[:20]: print(e) else: print(基础结构检查通过)这段脚本做的事有两部分第一把 images 数组建成一个以 id 为键的索引然后逐条检查 annotation 的 image_id、bbox、category_id第二用 Pillow 的 verify 方法逐张确认图片文件没有损坏。三个检查点分别是逻辑对应关系、坐标合法性和类别定义完整性。很多格式错误是静默的——比如 bbox 超出图像边界几像素训练时并不会报错但会让模型在边框附近学出奇怪的特征。所以每接一份新数据我都先跑一遍这几十行代码。损坏图片的检查尤其重要某次项目里训练到一半突然崩溃最后定位到就是两张 JPEG 文件头损坏模型加载图像时直接抛异常。3.2 从零标注到 COCO 的操作流程类别表、边界框规范与工具选型如果你拿到的不只是这份现成数据集而是想复刻一套自己场景的标注管线生产流程大致是收集原始图片准备一张类别表用标注工具画框导出 COCO JSON最后抽检。类别表是第一步也是源头。我一般把类别表做成一个简单的文本文件一行一个类别名顺序固定。常见设定是good和bad两行或者good、mildew、broken、insect四行。类别顺序一旦确定整个标注过程中不要再改动。如果中间删掉一个类别后面所有已标注数据的 category_id 都会错位处理起来非常麻烦。标注工具有两类选择。一类是传统的手动标注工具打开图片后手动拖框保存后自动生成 COCO 或 VOC 格式的标注文件另一类是带预标注功能的工具先用已有的检测模型跑一遍把预测结果加载进标注界面人工只需要修正错误的框和补充漏检的目标。后者能把效率提高一倍但对标注员的审核能力要求更高——预标注如果有系统性偏差人工很容易“顺着错的改对的”把错误的框修得更顺手而不是质疑它本身不合理。画框规范在 2.1 里已经提过这里补充一个执行细节同一张图如果有两棵玉米重叠重叠部分的归属要提前约定。常见做法是两个框都完整画出整个玉米允许框之间产生重叠另一种做法是切掉遮挡部分只圈可见区域。两种方案都能训练出可用的模型但必须统一。混着用会让模型对遮挡目标的学习目标不一致。3.3 人工标注复检抽检 10% 到 20% 的统一对比原则“人工标注”是这份数据集的卖点也是质量风险点。人工标注不是“画过一遍”就结束了没有经过复检的标注边界框的一致性是未知的。所以数据交付前我会强制安排一轮抽检从总数中随机抽 10% 到 20%找另一个人按同一份标注规范重新标一遍然后对比两轮结果。对比指标有两个。第一个是边界框 IoU计算两个框的交并比。如果复检框和原框的 IoU 低于 0.7说明有一个人的画框习惯明显偏离规范第二个是类别一致率两轮标注里类别标签一致的比例低于 95% 就得回去看是不是规范里存在歧义。比如“霉斑面积小于 5% 算不算坏”这种定义很可能在两条标注里得到截然不同的判断。复检的意义不只是找出错框更重要的是定位“歧义区域”。如果发现很多争议框都集中在某一种特定形态的玉米上——比如胚芽部位天然发黑被误判成霉变——那就说明规范描述得不够细。把歧义样本单独挑出来更新标注规范再全量重新检查同类图片。处理完这一轮之后数据集才算真正达到了可训练的状态。4. 训练前的最后两分钟数据切分、模型配置和参数选择4.1 按拍摄批次切分防止同场景图片同时出现在训练集和测试集很多初学者切分数据时直接对图片列表做一次随机划分。这在玉米检测这类场景里有隐患同一批拍摄的玉米图片背景、光线甚至玉米的位置都高度相似随机切分后训练集中某一批照片的“孪生兄弟”可能出现在测试集里。模型相当于提前见过了答案指标虚高真正换到新现场就露馅。正确的做法是以拍摄批次为组整组切分。假设数据集 JSON 里每张图带一个 group 字段对应拍摄批次可以这样操作import json import random from collections import defaultdict random.seed(42) with open(annotations/instances.json, r, encodingutf-8) as f: data json.load(f) # 将图像按拍摄批次分组 groups defaultdict(list) for img in data[images]: group img.get(group, batch_00) groups[group].append(img[id]) train_ids, val_ids, test_ids [], [], [] for group_id, img_ids in groups.items(): random.shuffle(img_ids) n len(img_ids) # 一般按 70/15/15 切分尽量每个批次都保留一份测试样本 train_ids img_ids[: int(n * 0.7)] val_ids img_ids[int(n * 0.7): int(n * 0.85)] test_ids img_ids[int(n * 0.85):] print(ftrain{len(train_ids)}, val{len(val_ids)}, test{len(test_ids)})这里的关键参数是随机种子和切分比例。随机种子固定下来保证每次跑出来的划分结果一致方便对比不同模型配置的差异切分比例上我倾向于 70/15/15而不是常用的 80/10/10因为检测任务里测试集的评估方差本身就大多留 5% 的测试图能让指标更稳定。如果原始数据没有 group 字段也可以退而求其次按文件名前缀聚类或者按拍摄时间戳聚类。前提都是同一个原则——同一场景的图片不能被同时分到训练集和测试集。4.2 一份可直接上手的 Faster R-CNN 配置类别数、数据路径、评估频率数据切好之后用开源检测框架训练是效率最高的方式。以 mmdetection 为例配置文件改动量很小核心是把检测头的类别数改成 2并指定数据集的路径_base_ [ ../_base_/models/faster_rcnn_r50_fpn.py, ../_base_/datasets/coco_detection.py, ../_base_/schedules/schedule_1x.py, ../_base_/default_runtime.py, ] model dict( roi_headdict( bbox_headdict(num_classes2) ) ) dataset_type CocoDataset data_root data/corn/ data dict( traindict( typedataset_type, ann_filedata_root annotations/instances_train.json, img_prefixdata_root images/, ), valdict( typedataset_type, ann_filedata_root annotations/instances_val.json, img_prefixdata_root images/, ), testdict( typedataset_type, ann_filedata_root annotations/instances_test.json, img_prefixdata_root images/, ), )配置里改动最大的就是num_classes2对应 good 和 bad 两个类别。原来是 80 类的 COCO 预训练权重换到 2 类时倒数第二层的全连接结构不同框架会在加载预训练权重时跳过不匹配的层这部分不用手工处理。我一般不会从头训练。加载 COCO 预训练权重再微调比随机初始化收敛快很多通常几十个 epoch 就能达到还不错的精度。数据路径data_root建议改成绝对路径或者统一规范的相对路径否则换一台机器训练光找数据就能浪费不少时间。4.3 决定训练效果的四组参数epoch、batch size、学习率、缩放增强训练参数看着多玉米检测里真正影响结果的只有四组。第一组是 epoch。二类检测任务、几千张图规模我一般先跑 50 个 epoch 看趋势验证集 mAP 如果还在明显上升就继续加 30 到 50 个。盲目跑上百个 epoch 不一定是好事小数据集上后期很容易过拟合。第二组是 batch size。显存够的前提下batch size 8 到 16 是合理区间。如果 batch size 太小BN 层的统计量不稳定训练 loss 会一直抖如果显存不够可以把输入图像的短边缩到 640 左右而不是硬上大图。第三组是学习率要跟着 batch size 走。一个常用的参考基准是batch size 64、学习率 0.02 起步如果 batch size 减半学习率也相应减半。我用 batch size 16 时初始学习率一般设 0.005配合前 500 步的 warmup把学习率从很小的值慢慢升到目标值。学习率设得太大训练初期 loss 会直接爆掉设得太小几十轮 epoch 下来权重几乎没怎么更新。第四组是多尺度训练增强。玉米表面缺陷的尺度变化很大一张图里的霉斑可能只占十几个像素也可能占满半个果穗。开启多尺度训练比如短边在 480 到 960 像素之间随机缩放会让模型对不同尺寸的目标都有学习机会。代价是训练时间增加但对检测指标的提升非常直接。标题里的“平均准确率 89.5% 以上”大概率是在这种常规调参基础上得到的想复现这个数字参数范围不用太激进重点还是数据和标注的质量。5. 避坑记录从标注格式到指标验证四个最常把人绕晕的坑5.1 现象训练集和测试集 mAP 差距巨大换现场数据直接翻车这个坑我踩过一次。当时用一份玉米图片数据集训练验证集 mAP 到了 0.85团队都很兴奋结果拿去新车间实测检测率直接掉了一半。后来复盘发现问题根本不在模型而在数据切分所有图片都是同一条传送带上拍的随机切分时训练集和测试集里混进了大量同一时段的连续帧等于测试集被剧透了。原因按文件列表做纯随机切分没有考虑拍摄批次的边界。解决改成按 group 批次切分测试集只保留“模型没见过的场景”里的图片。如果数据本身只有一个批次最优做法是单独留出一小块完全不同的采样环境比如换一盏灯、换一个背景后重新拍几十张专门做测试。5.2 现象把玉米须或背景中的包装物误检成坏玉米模型训练完推理时最容易看到的错误是把玉米须检成坏玉米。玉米须是细长的丝状物颜色偏褐偏黄和霉变的初期形态在图像上非常相似。如果标注阶段把玉米须包进了框里模型就学会了把这种纹理当成缺陷特征。原因标注规范里没有规定“框内不得包含非玉米组织”或者标注员图省事把玉米须一起框进去了。解决检查训练集里所有 bad 类别的框凡是框内包含明显玉米须的样本重新修框或者直接删除。训练完再对验证集做一次预测可视化专门看 False Positive 的图片确认误检对象集中在哪一类背景。除了玉米须常见的还有包装袋上的文字、人手指和传送带边缘。这些负样本要么通过修标注排除要么额外采集一些空背景图加到训练集里。5.3 现象坏玉米类别反复漏检好玉米几乎满分二分类检测里如果 good 类样本占绝大多数bad 类样本很少模型很容易陷入“全部预测成好玉米”的偷懒解。验证集上整体准确率看着很高但坏玉米的 recall 很低分选线漏过去的次品全在这类场景。原因类别不平衡。先不看图片总数而是按类别统计目标实例数。如果 bad 类实例数量连 good 类的 20% 都不到就需要处理。解决两种常用手段。第一个是在训练时对 bad 类加高 loss 权重让每个坏玉米样本在训练中对梯度的影响更大第二个是数据增强把 bad 类目标通过 copy-paste 方式贴到更多背景图上变相增加坏样本数量。还有一种体感上更直接的方法加大模型对靠近图像边缘目标的敏感度很多漏检的坏玉米其实是贴着边的。5.4 现象模型啥都不检所有目标的置信度都很低另一类常见现象是训练过程 loss 正常下降但推理时所有预测框的置信度都不超过 0.3几乎没有输出。如果数据集标的是 COCO 格式这个坑大概率出现在类别 id 的错位上。原因COCO JSON 里的 categories 数组有可能从 0 开始编号而框架内部的类别 id 约定从 1 开始。category_id 全部错位后模型训练时并没有明显报错但类别对应关系是乱的推理结果自然对不上。解决检查 JSON 里 categories 数组的实际定义。如果一个叫 good 的类别 category_id 是 0需要把它改成 1并同步更新所有 annotation 里的 category_id。改完后重新跑 3.1 的校验脚本确认类别表、标注文件和模型配置三者完全一致再开始训练。6. 进阶操作验证集阈值校准一个把准确率再往上拉一步的步骤很多人把 89.5% 当成一个固定上限其实模型输出的置信度阈值是可调的调整阈值对最终准确率的影响常常比换骨干网络还大。检测模型训练完成后默认阈值通常设在 0.5但这个值不一定适合玉米质检场景。更合理的做法是跑完测试后单独分析验证集上的置信度分布挑一个匹配现场要求的阈值。先明确一个概念目标检测里的“准确率”不是二分分类里那个单点准确率它背后有一条 precision-recall 曲线。阈值高检出来的目标更可信但会漏掉一部分低置信度的坏玉米阈值低召回上去了但误检也多了。玉米分选场景中把坏玉米漏过去造成的损失往往比误杀好玉米更大所以阈值应该往低回调。具体怎么调可以用一段简单的统计脚本对验证集预测结果做扫描import numpy as np # preds 是模型在验证集上的输出每条结构为 # [置信度, 预测类别, 真实类别 0 或 1] preds [] # 需要从模型评估日志中导出 best_threshold 0.5 best_f1 0.0 for threshold in np.arange(0.3, 0.8, 0.05): tp fp fn 0 for score, pred_cls, true_cls in preds: if score threshold and pred_cls 1: if true_cls 1: tp 1 else: fp 1 elif true_cls 1: fn 1 precision tp / (tp fp) recall tp / (tp fn) f1 2 * precision * recall / (precision recall) if f1 best_f1: best_f1 f1 best_threshold threshold print(f最优阈值: {best_threshold:.2f}, F1: {best_f1:.4f})这段代码的思想是对坏玉米这个正类扫描不同置信度阈值下的 precision、recall 和 F1 值选择 F1 最高的阈值作为部署阈值。注意这里只统计了坏玉米类别因为实际业务关心的是“把坏玉米从产线上摘除掉”好玉米的误杀代价可以通过另一组阈值来控制。代码里的 preds 需要从模型评估结果里导出不同框架导出方式有差异但扫描逻辑是通用的。阈值校准之后还有一个小技巧能稳定指标把验证集预测错误的图片全部导出按“漏检的坏玉米”和“误检的好玉米”两类整理再回到第 3 章的复检流程把这些错误样本对应的标注框重新审核一遍。我经常发现模型某几次吃力的样本其实原标注本身就有问题——框歪了几像素或者霉斑边缘被截断。把这些标注修正后重新训一次效果往往比换一个更大的预训练模型来得更实在。这些年做农产品检测项目我已经养成一个习惯任何数据集到手先压缩对模型结构的期待放大对标注质量的诚实检验。一份数据标注不一致再先进的模型也只能在一个虚假的指标上挣扎。搞清楚好坏边界、跑通校验脚本、按批次切分、复检争议样本这套流程做扎实了89.5% 才可能真正复制到你的现场里。希望这段经验能帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑