橙子成熟度检测数据集:YOLOv5-ready的构建与训练实践
2026/9/1 13:24:47 网站建设 项目流程

简介:面向农业自动化和柑橘智能化检测场景,可直接获得一套YOLOv5兼容的橘子成熟度目标检测数据集,按成熟/未成熟两类标注,图像质量统一、边界框清晰完整,可省去数据整理与格式转换环节。数据集包含2313张训练图与224张验证图,均为640×640 RGB格式,每张图配有对应YOLO格式txt标签,目录按images/与labels/标准结构组织,导入训练环境即可开工。整包共177个文件,以171张JPG图像为主体,另含标签txt、可视化脚本show.py及pt权重文件,压缩包仅13.29MB,轻量易下载。附带的show.py无需修改参数,一键随机加载图片并叠加显示标注框,自动保存结果,方便快速核验标注质量。已有38人浏览学习,对柑橘分级、成熟度识别或采摘机器人开发而言,是一套非常省心的数据基础。

1. 为什么我决定做一个“能直接训练”的橙子成熟度数据集

做目标检测项目的人应该都有这种体会:真正卡住进度的往往不是模型结构、不是显卡算力,而是手里没有一份干净、规范、标注靠谱的数据集。尤其是农业场景,想找一个现成的橙子成熟度检测数据集,搜索结果翻来翻去要么是学术论文里只给了链接的哈佛数据集,要么是几百张图片没做任何划分的随手打包,拿来训练基本属于自找麻烦。

这个YOLOv5-ready的橙子成熟度数据集,核心就做了一件事:把两类标注(ripe成熟、unripe未成熟)的橙子图片整理成开箱即用的格式,附带train/val划分和可视化脚本,喂给YOLOv5直接就能跑训练。这次分享不只是在说“我传了个数据集上去”,而是把整个数据构建过程的思考、踩坑和验证方式完整拆开来讲。

适合谁来参考?两类人:第一类是正在做农业目标检测、水果分拣相关课题的研究者或开发者,这个数据集可以直接作为baseline数据用;第二类是刚开始学YOLOv5、想走一遍“自定义数据集训练”全流程的初学者,建议不要只下载完就跑,跟着后面的可视化脚本和检查清单过一遍,比闷头看文档有效得多。

2. 数据采集与标注:两类标签背后的“成熟度”判断逻辑

2.1 采集场景怎么选直接决定模型的泛化上限

这个数据集里的图片来源基本覆盖了橙子种植和流通环节的真实场景:果园树上的自然光照状态、采摘后的堆叠状态、分拣线上的俯拍角度、不同成熟度混放的情况。这不是随手凑数,而是有意为之。

原因很简单:目标检测模型学的是“外观特征+上下文信息”的组合。如果只在单一背景下采集,模型很容易把背景特征当成橙子特征的一部分,换到真实分拣环境马上掉点。比如树上的橙子有树叶遮挡、有光照不均的问题,这训练出来的模型到田里还能用;但如果训练集全是白色背景下的商品图,部署到果园就完全废掉。

采集时还有一个常被忽略的点:分辨率和拍摄距离。数据集中大部分图片是手机和普通数码相机拍摄的,单张图片里橙子的像素尺寸在几十到几百像素之间浮动。这符合YOLOv5的实际使用场景,毕竟部署端可能是树莓派上的摄像头,也可能是分拣线上的工业相机,目标大小本来就差异很大。

2.2 “成熟”和“未成熟”的边界,其实是标注规范在起作用

两类标注——ripe和unripe——很多人以为看一眼颜色就能标,实际上真的标注起来会碰到不少灰色地带。

我的标注规范参考了果农的实际判断逻辑,而不是单纯依赖RGB值:

  • ripe:果皮呈橙色到深橙色,色泽均匀,有光泽感,果实饱满。即使果蒂附近有一点点青色,只要整体已经转橙,就归为ripe。
  • unripe:果皮以绿色为主,或者大面积青绿色、黄绿色,果实偏硬朗、色泽暗淡。黄中带绿但明显没转橙的,归为unripe。
  • 不标注的情况:被遮挡超过50%的果实不标,严重模糊、对焦失败的图不标,果实只有一小条露在画面边缘的不标。这种“宁可少标不可错标”的原则大幅度减少了训练时的噪声。

这里特别说一下为什么颜色边界不能一刀切。同一个品种的橙子在转色期会出现黄绿混杂的状态,不同光照条件下相机拍出来的色温差异也很大。如果严格规定“绿色像素占比低于某个阈值就算成熟”,反而会因为光照影响误标一堆样本。所以标注规范里加入了果形、光泽、果蒂状态这些辅助判断,实测下来对模型收敛的帮助比像素级颜色判断大得多。

2.3 标注格式统一到YOLO txt格式,少走很多弯路

考虑到数据集的定位是“YOLOv5-ready”,标注文件没有用COCO的JSON格式,而是直接输出成YOLO格式:每张图对应一个同名txt文件,每行是class_id x_center y_center width height,坐标值全部归一化到0-1之间。

当时这样选的原因很直接:YOLOv5的dataset配置文件直接支持这种格式,Labelimg或AnyLabeling标注完导出YOLO格式就能直接进训练流程,不需要写额外的转换脚本。而且后续如果想转成COCO格式喂给其他模型,用ultralytics仓库里的转换工具也花不了几分钟。

有个细节容易被新人忽略:YOLO格式里的框坐标是归一化值,但标注工具里显示的是像素值。如果你用的是Labelimg,导出时务必确认导出设置里选的是YOLO格式,而不是PascalVOC。之前见过有人用VOC的XML喂给YOLOv5,结果在数据加载阶段报了一堆错,排查半天才发现是格式不匹配。

3. train/val划分:不是随机抽样那么简单

3.1 划分层的逻辑:按图像来源分组,而不是按文件随机分

从数据集里随机抽20%当验证集,这个做法在学术demo里没问题,但在实际项目中会让验证集的评估结果虚高。原因在于同一时间、同一场景拍摄的连续帧之间高度相似,随机划分容易把同一场景的图像分别塞进训练集和验证集,模型等于“开卷考试”。

这个数据集的划分方式是按图像来源的场景分组后,再整体分配。具体做法是:先从采集记录里把图片按拍摄批次(果园点位、时间段、光照条件)归档,每个批次作为一个unit整体分配到train或者val,保证同一个场景的照片不会同时出现在两个集合中。最终比例大约在train 80%、val 20%,图片总量上百张的量级,虽然不算海量,但类别均衡性和场景覆盖度才是这个数据集的重点。

这样做的代价是验证集和训练集之间的分布差异会明显一些,模型在val上的mAP会比随机划分低几个百分点。但这才是真实水平——部署到新果园、新光照环境时,模型的表现就应该以这种“严格模式”评估为准。

3.2 配置文件与目录结构,直接clone下来就能用

YOLOv5的目录结构要求比较明确,数据集根目录下需要images/trainimages/vallabels/trainlabels/val四个标准子目录。这个数据集也按同样的约定组织:

orange_maturity_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ ├── README.md └── visualize_dataset.py

配套的orange.yaml内容如下:

train: /path/to/orange_maturity_dataset/images/train val: /path/to/orange_maturity_dataset/images/val nc: 2 names: ['unripe', 'ripe']

注意类别顺序,names列表里unripe在前、ripe在后,class_id从0开始。如果你后续用其他模型做迁移学习,Class 0对应的是unripe,这个顺序在数据处理阶段就要想清楚,别等训练完看混淆矩阵才反应过来标签反了。

3.3 每类样本数量差异带来的正负样本平衡问题

两类标注的数量并没有完全做到1:1。橙子的成熟期是一个持续推进的过程,采集到的unripe样本量会略少一些,这是客观现实。处理方式没有选择简单的过采样复制,而是靠调整采集策略来补:去果园时刻意多拍了一些果皮偏绿、转色早期的果实,让unripe的数量尽量贴近ripe。

如果后续你自己扩展采集数据,建议保持这个原则:靠增加真实样本的多样性来平衡类别,而不是靠复制图片或加噪声生成合成样本。目标检测模型对重复样本的记忆非常敏感,用复制样本强行平衡,轻则过拟合,重则让模型对某些特定角度过度敏感。

4. 可视化脚本:验证标注质量的最后一道防线

4.1 写这个脚本的动机:光看txt文件根本发现不了问题

标注质量出问题,最坑的地方在于YOLOv5不会直接报错——框坐标超出图像边界、类别串号、标注框和实际目标严重错位,这些都不会阻止训练启动,只会让模型默默学到错误内容,最后体现在mAP和PR曲线上,排查时已经浪费了大量训练时间。

可视化脚本就是干这个的:把标注框直接画回到原图上,生成一张带框的图片,让人眼快速判断标注是否正确。

核心代码逻辑不复杂:

import cv2 import glob def draw_yolo_boxes(image_path, label_path, class_names): img = cv2.imread(image_path) h, w = img.shape[:2] with open(label_path, 'r') as f: for line in f.readlines(): parts = line.strip().split() cls_id = int(parts[0]) x_center, y_center, box_w, box_h = map(float, parts[1:]) x1 = int((x_center - box_w / 2) * w) y1 = int((y_center - box_h / 2) * h) x2 = int((x_center + box_w / 2) * w) y2 = int((y_center + box_h / 2) * h) color = (0, 255, 0) if cls_id == 1 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls_id], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) return img class_names = ['unripe', 'ripe'] output_dir = 'visualized/'

脚本本身是拿来就能用的,但重点在于用它执行一套检查流程,而不是走马观花看图。

4.2 抽检策略:每一批数据都按比例可视化,而不是随机抽几张

随机抽几张图看一眼,效果约等于没检查。这个数据集在交付前跑了一轮全量可视化,生成的方式是把所有标注框的数量、尺寸分布、中心点分布统计出来,先看数据层面是否有异常,再逐张看可视化图。

常用的快速筛查指标有三个:标注框宽度和高度的比值(橙子接近圆形,宽高比应该在0.7到1.3之间,如果出现大量细长框说明标注出错)、标注框中心点的热区分布(如果所有框都在画面中心区域,说明边缘目标没被标到)、单张图上的目标数量(橙子堆叠场景目标数会明显偏高,但正常单果场景不会出现十几个框)。

可视化脚本跑完一遍后我通常还会做一次人工抽帧——按train/val目录每20张挑一张,把带框图认真看一遍,重点检查三类问题:误标(把树叶、阴影当成了橙子)、漏标(图片里的橙子没有框)、错标(ripe和unripe标签贴反了)。慢是慢一点,但这一步省掉,后面训练出问题再排查,花的时间是十倍还不止。

5. 数据集配合YOLOv5训练时的几个实测要点

5.1 环境搭建和超参数选择不用盲目照搬

围绕这个数据集训练YOLOv5,环境方面常见的坑集中在显卡驱动和依赖版本上。PyTorch版本跟CUDA不匹配、cuDNN版本不对,都会在训练启动阶段报一些让人摸不着头脑的错误,比如CUDA error: no kernel image is available。这类问题通常不是代码的错误,而是环境问题,建议先查驱动和PyTorch版本的匹配关系,再回头看代码。

超参数方面,数据集规模不算大的前提下,不建议去动hyp.scratch.yaml里的学习率、动量这些全局参数,直接把默认配置跑起来,效果通常已经不错。值得关注的几个参数是--batch-size--img-size--epochs。图片尺寸用YOLOv5默认的640即可,batch size根据显存调整——6G显存用8,12G显存用16,这个数据集的图片分辨率不会把显存压力推得太高。epochs在100到200之间就能看到明显的收敛趋势,不要一上来就300 epochs起步,先跑100个epoch看val曲线,再决定是继续训练还是加数据。

5.2 训练过程中看哪几条曲线,别只盯mAP

训练启动后,很多人习惯只盯着mAP看,但mAP是最终指标,训练过程中更重要的是loss曲线的形态。

  • train/box_loss下降平稳、没有剧烈震荡,说明标注框质量没问题;
  • val/box_lossval/cls_loss在训练后期不再下降甚至回升,说明过拟合苗头出现,这时应该考虑早停或者数据增强;
  • val/cls_loss如果一直下不去,优先怀疑类别标注的噪声,回去用可视化脚本重新检查标签。

初始跑出来的mAP@0.5不应该低于0.85,如果明显低于这个水平,先不要急着调模型,回到数据层面找问题:图片是否模糊、标注是否错位、类别是否不均衡,这些比换backbone的影响大多了。

5.3 对这个数据集来说,哪些数据增强值得开、哪些建议关

YOLOv5默认开启的增强包括随机平移、随机缩放、HSV色域变换、Mosaic等。对橙子检测场景,hsv_hhsv_s这些颜色相关增强是友好的,因为橙子的颜色和背景差异明显,微小的色域扰动相当于做了一次光照校正,泛化能力会变好。

需要谨慎的是degrees旋转增强。橙子是近似圆形的,旋转增强的影响虽然不会致命,但训练集里如果存在大量旋转样本,模型学到的是“看圆形”,对其他形状的水果参考意义不大。建议把degrees设置为0或者一个很小的值,比如5度以内,用来抵消拍摄角度的轻微偏差就够了。

另外fliplr水平翻转建议开启,这个增强对任何目标检测任务都是安全的,能有效提升样本多样性。mosaic增强在这个数据集上也有正向收益,因为它模拟了果实堆叠场景,和真实分拣环境一致。

6. 从数据集到落地部署,这条路还能往下走很远

这个橙子成熟度数据集目前定位是基础版:两类分类、标准YOLO格式、中小规模、单场景覆盖。它可以直接用于目标检测模型的训练入门、迁移学习的baseline、以及农业视觉算法的快速验证,但真正用到工业分拣场景,还有几个明确的方向可以扩展。

第一个方向是增加类别粒度。现在只有ripe和unripe,实际分拣需求往往要区分“成熟”、“接近成熟”、“未成熟”多个等级,这直接在现有标注体系上细粒度化即可,数据集的目录结构和脚本不需要改动。第二个方向是增加品种维度,不同品种的橙子在颜色、纹理、光泽上的差异会直接影响模型的迁移效果,目前标注的是单一品种,跨品种泛化属于后续验证的重点。第三个方向是模型部署,结合树莓派5或NXPi.MX8MP这类边缘设备,把训练好的模型导出为TensorRT或NCNN格式做端侧推理,这又是另一个值得展开的话题。

从我实际使用的角度说一句:数据集的构建难度从来不在采集本身,而在于如何让数据在“采集—标注—清洗—训练—验证—反馈”这条链路中流动起来。这款数据集能直接把前面几环打通,剩下的反馈环节,就得靠在使用过程中自行积累了。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询