ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

水果新鲜程度检测数据集:从标注到YOLOv8模型落地的工程实践

水果新鲜程度检测数据集:从标注到YOLOv8模型落地的工程实践 简介这份水果新鲜程度检测数据集面向计算机视觉学习者、目标检测练手者及需要构建水果分拣原型的开发者解决新鲜与腐坏水果样本不足、标注格式不统一的问题。数据集覆盖apple、bad banana、banana和bad apple共4个类别兼顾正常与变质状态适合训练YOLO、Faster R-CNN等检测模型也可用于课堂实验与算法对比。压缩包共1192个文件包含397张jpg图像、397个xml标注和398个txt标注两种标签格式分别存放便于直接接入不同检测框架整体约15.19MB体积轻量、下载与解压成本低。目前已有1437人学习下载说明其在入门与进阶检测任务中具备一定参考价值。读者可借此快速搭建四类水果检测流程理解VOC与YOLO标注差异并对照公开检测结果验证模型表现为后续数据增强、类别平衡和部署优化提供可复用的数据基础。1. 水果新鲜程度检测数据集从烂果分拣到模型落地的第一块砖做过水果分拣线改造的工程师都清楚视觉算法能不能跑通八成不取决于网络结构而取决于你手里那批图到底标得对不对、覆盖得全不全。水果新鲜程度检测数据集本质就是一批按新鲜度分级的果蔬图像集合通常划分为新鲜、次鲜、腐烂三档配套边界框或分类标签用来训练分类、检测甚至分割模型。它解决的是“让机器判断这颗果子还能不能卖”的问题适合做农产品质检、冷链仓储、智能零售称重台以及想入门工业视觉的算法同学。我见过太多团队在开源数据上刷到 98% 准确率换到自己产线一跑就崩根因往往不是模型而是数据集里的光照、品种、遮挡分布和现场差太远。这一章先把这件事的边界讲清楚后面再动手。2. 水果新鲜程度检测数据集到底长什么样标签体系与选型逻辑2.1 三档分级还是五档分级先定业务口径再定标签新鲜度分级没有国标统一口径这是新手最容易翻车的地方。常见做法是按可售周期切新鲜刚下树到货架期前段、次鲜外观轻微失水但可食用、腐烂霉变、软腐、明显病斑。有些团队会加“机械损伤”和“过熟”两档凑成五类但类别一多标注一致性断崖式下跌——同一个苹果三个人标可能给出三种结果。我一般建议第一版只做三档原因很实际标注成本低、类间差异大、模型容易收敛。等产线跑顺了再在次鲜里细分“可打折”和“可加工”两个子类。标签体系一旦定下就要写进标注规范文档配典型图例否则外包标出来的东西没法用。从任务形态看分类数据集给整图一个标签检测数据集给每个果子一个框加类别分割数据集给像素级掩码。分拣线上果子会堆叠纯分类不够用检测是主流选择。如果只是做传送带单果检测分类加目标检测级联也能凑合。2.2 数据来源与采集手机拍的和产线拍的差距在哪公开渠道能拿到的水果新鲜度数据多数是实验室环境、单一背景、均匀打光。这类数据训练出的模型换到有反光、有阴影、有传送带纹理的现场mAP 掉 20 个点是常态。所以选型第一原则能用自己场景采的就别偷懒。采集时我一般按下面这个清单走品种覆盖至少涵盖目标产线 Top 5 品种苹果、柑橘、香蕉、番茄、芒果这类常见货光照条件上午侧光、正午顶光、傍晚弱光、冷库荧光灯各采一批姿态与遮挡单果、双果紧贴、三果堆叠、被叶片或包装遮挡背景传送带、塑料筐、纸箱、货架各来一些设备产线相机和手机都拍模拟不同部署端每类至少 500 张起步三档合计 1500 张能跑通 baseline想稳到产线可用3000 到 5000 张更现实。采集时同步记录品种、光照、设备三个元信息后面做分层评估全靠它。2.3 标注规范框怎么画、边界怎么定检测标注的坑集中在边界定义。腐烂区域是只框病斑还是框整个果子我的做法是框整个果子类别标腐烂因为分拣执行机构抓的是整果。如果做病斑分割才需要像素级标注。标注工具用 LabelImg、CVAT、Labelme 都行导出格式统一到 YOLO 的 txt 或 COCO 的 json。关键是一致性同一个标注员连续标 200 张后容易疲劳走样建议每 100 张插入 10 张已标好的复核图抽检一致性低于 90% 就返工。提示标注规范里一定要写“模糊样本处理规则”比如“介于次鲜和腐烂之间、无法判断的一律标次鲜”否则边界样本会成为模型震荡的根源。3. 从零跑通一个新鲜度检测 baseline环境、转换与训练3.1 环境准备与目录结构先假设你拿到的是分类标注的原始图按文件夹分好类要转成检测格式。环境用 Python 3.9 以上PyTorch 加 Ultralytics 的 YOLOv8 是最省事的组合。目录我习惯这样摆fruit_freshness/ ├── raw/ │ ├── fresh/ │ ├── semi_fresh/ │ └── rotten/ ├── datasets/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/ └── data.yamlraw 里是按类别分的原图datasets 是转换后的检测格式。这个结构不强制但保持稳定能省掉后面很多路径调试的时间。3.2 分类标注转检测格式一个脚本搞定如果原图是单果居中拍摄可以用整图框近似即框等于图像边界。下面脚本把分类文件夹转成 YOLO 检测标签类别映射写在字典里。import os import shutil from pathlib import Path from sklearn.model_selection import train_test_split # 类别映射顺序决定 label 里的 class_id CLASS_MAP {fresh: 0, semi_fresh: 1, rotten: 2} RAW_DIR Path(raw) OUT_IMG Path(datasets/images) OUT_LBL Path(datasets/labels) def convert_one(img_path, cls_id): 整图框中心点 0.5,0.5宽高 1.0,1.0 return f{cls_id} 0.5 0.5 1.0 1.0 all_items [] for cls_name, cls_id in CLASS_MAP.items(): for img in (RAW_DIR / cls_name).glob(*.jpg): all_items.append((img, cls_id)) # 8:2 分层切分保证每类都有验证样本 train_items, val_items train_test_split( all_items, test_size0.2, stratify[x[1] for x in all_items], random_state42 ) for split, items in [(train, train_items), (val, val_items)]: (OUT_IMG / split).mkdir(parentsTrue, exist_okTrue) (OUT_LBL / split).mkdir(parentsTrue, exist_okTrue) for img_path, cls_id in items: shutil.copy(img_path, OUT_IMG / split / img_path.name) label_path OUT_LBL / split / (img_path.stem .txt) label_path.write_text(convert_one(img_path, cls_id) \n)逻辑说明CLASS_MAP的顺序就是模型输出的类别索引改顺序必须同步改data.yaml。stratify参数保证训练集和验证集里三档比例一致否则验证集可能全是新鲜果指标虚高。整图框只适合单果居中场景如果原图是多果堆叠必须用真实标注框替换convert_one的返回值。参数说明test_size0.2是验证集比例数据量小于 1000 张时建议调到 0.3让验证更稳。random_state固定后切分可复现团队协作时别乱改。3.3 data.yaml 与训练命令YOLO 训练靠一个 yaml 描述数据位置和类别名path: ./datasets train: images/train val: images/val nc: 3 names: [fresh, semi_fresh, rotten]nc是类别数必须和CLASS_MAP长度一致这是最常见的报错来源。训练命令yolo detect train modelyolov8n.pt datadata.yaml epochs100 imgsz640 batch16model选 nano 版先跑通确认流程没问题再换 s 或 m。imgsz640是输入分辨率产线小目标多可以提到 960但显存和速度要重新权衡。batch16在 8G 显存上比较稳爆显存就降到 8。训练完看runs/detect/train/下的混淆矩阵重点看次鲜和腐烂之间的误判这两类最容易混。3.4 推理验证单图与批量yolo detect predict modelruns/detect/train/weights/best.pt sourcetest_imgs/ saveTruesource可以是单图、文件夹或视频流。产线部署前务必用现场采的、没参与训练的图做一次盲测别只看验证集指标。我一般会额外留 100 张现场图做“黑匣子测试”这批图不参与任何调参只在最后验收时跑一次。4. 新鲜度检测的避坑与排查那些让模型翻车的细节4.1 验证集准确率 99%现场一跑全是误检现象训练日志里 mAP 很高部署到传送带上新鲜果被大量判成腐烂。 原因验证集和训练集同分布都是实验室图现场的光照、背景、品种全变了模型没学过。 解决按 2.2 的采集清单补现场数据至少每类 200 张重新微调。评估时按光照和品种分层看指标别只看总体。4.2 次鲜和腐烂总是分不开现象混淆矩阵里这两类的误判占了大头。 原因标注边界模糊或者次鲜样本里混了实际已经腐烂的图。 解决回到标注规范抽 50 张误判图人工复核统一口径后重标。如果确实类间差异小考虑加一个“过熟”中间类或者引入纹理特征做辅助分支。4.3 小目标漏检严重现象堆叠场景里被压在下层的果子检测不到。 原因输入分辨率不够或者训练集里堆叠样本太少。 解决imgsz提到 960 或 1280补采堆叠场景数据。如果还不行换带 P2 小目标层的模型结构或者用切片推理。4.4 训练 loss 震荡不收敛现象loss 曲线上下跳mAP 不涨。 原因学习率太大、batch 太小、或者标签里有脏数据类别越界、坐标超出 0-1。 解决先跑一遍标签校验脚本检查有没有 class_id 大于 nc-1 或坐标越界。确认干净后学习率降到 0.001batch 调到能承受的最大值。4.5 换品种就崩现象苹果上训的模型换到柑橘直接失效。 原因品种外观差异大模型学到了品种特征而非新鲜度特征。 解决多品种混合训练或者在数据增强里加颜色抖动、灰度化逼模型关注纹理和形状。极端情况下做品种分支每个品种单独一个头。5. 把数据集用出复利分层评估与持续迭代的一个习惯数据集不是训完一次就扔的消耗品。我踩过最大的坑是第一个版本上线后没做数据回流三个月后产线换了新包装模型精度悄悄掉了 15 个点才被发现。后来固定了一个习惯每次现场误判的图按“品种-光照-误判类型”三个维度归档每月做一次分层评估。具体做法是写一个评估脚本把验证集按元信息分组分别算每组的召回和精确率import pandas as pd from sklearn.metrics import classification_report # meta.csv 记录每张图的品种、光照、真实类别、预测类别 df pd.read_csv(meta.csv) for group_name, group_df in df.groupby([variety, lighting]): print(f--- {group_name} ---) print(classification_report(group_df[true], group_df[pred]))这样一眼就能看出模型在“柑橘冷库荧光灯”这组是不是特别差。差的那组下个月优先补数据。补数据也有讲究不是随机补而是按短板补每组至少补到 300 张再重新微调。微调时用低学习率只训 20 到 30 轮避免把之前学好的组带偏。另一个习惯是保留一个“黄金测试集”200 张图覆盖所有品种和光照永远不参与训练只在每次模型更新后跑一次。这个集合的指标波动超过 3 个点就说明这次更新有问题回滚重来。听起来笨但比上线后翻车再救火便宜得多。数据集这件事投入产出比最高的从来不是买更贵的标注服务而是把采集、标注、评估、回流串成一个闭环。第一版粗糙没关系关键是每轮迭代都有据可依。希望帮到你。本文还有配套的精品资源点击获取
返回列表