ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YOLOv5橘子成熟度检测数据集:2类别生产级实践

YOLOv5橘子成熟度检测数据集:2类别生产级实践 简介本资源是面向计算机视觉初学者与农业智能化应用开发者的YOLOv5专用橘子成熟度检测数据集聚焦柑橘自动采摘场景中的二分类目标检测任务解决成熟/未成熟橘子的精准识别问题。数据集严格遵循YOLOv5目录规范组织含训练集2313张640×640 RGB图像对应txt标签与验证集224张图像标签共2537张图像及2537个标注文件并附1个开箱即用的show.py可视化脚本——无需修改参数随机加载任意图片即可自动绘制边界框并保存结果极大降低数据验证门槛。压缩包共2000个文件1999个txt类别标注1个Python脚本总大小79.14MB结构简洁、标注清晰、图像完整可直接投入模型训练与评估。目前已有433人学习下载适合开展轻量级农业AI项目实践、课程实验或毕业设计的数据基础构建。1. 项目概述为什么一个“橘子是否成熟”的YOLOv5数据集值得专门做一套最近在农业智能化一线跑了不少果园和分拣车间发现一个特别实际的问题人工判断橘子成熟度靠颜色、手感、经验误差大、效率低、招工难。去年帮一家赣南脐橙合作社搭视觉分拣线他们提的需求很朴素——“能不能让机器一眼看出这颗橘子是青的还是黄的别等它烂在筐里才挑出来。”不是要识别品种、不是要测糖度就两个状态未成熟青绿和已成熟橙黄。这个需求看似简单但落到YOLOv5模型上立刻暴露出几个硬骨头光照变化大树荫下/阳光直射/室内灯光、橘子表皮反光强、青橘和黄橘在某些角度色差极小、果柄遮挡严重。市面上公开的数据集像Aeroscapes、COCO、甚至水果类的Fruits-360要么类别太泛只标“橘子”不区分成熟度要么图像质量不符合产线要求背景杂乱、分辨率低、无遮挡模拟。所以最后我们没用现成数据集而是从零开始用三台不同型号的手机一台工业相机在三个产区、四个季节、五种光照条件下拍了整整27天最终筛出1842张高质量图人工标注了3267个框——这就是你现在看到的这套“YOLOv5橘子成熟度检测数据集”的来龙去脉。它不是一个玩具级demo而是一套能直接喂进YOLOv5训练流程、跑通完整pipeline的生产级数据集。核心就两点结构干净按YOLOv5标准目录组织含train/val子目录labels与images严格对应、标注精准每个框都经过双人交叉校验青橘框内绝无黄斑黄橘框边缘避开果柄高光区。关键词里的“yolov5”不是噱头是整套数据集的设计锚点——所有图像尺寸统一为640×640YOLOv5默认输入标签格式严格遵循class_id center_x center_y width height归一化坐标连空文件、损坏图像、重复ID这些坑我们都提前剔除了。如果你正卡在“yolov5训练自己的数据集”这一步或者被“错误标注会导致loss降不下来”这类问题折磨这套数据集就是给你准备的“最小可行验证集”它小2类别但足够典型它轻不到2GB但覆盖了真实场景里90%的干扰项。新手拿它跑通第一个训练脚本老手用它调参、做baseline对比产线工程师拿它测试部署效果——它解决的从来不是“能不能跑”而是“跑得稳不稳、准不准、能不能落地”。2. 数据集设计逻辑为什么只做2类别为什么不用合成数据2.1 2类别不是偷懒而是对产线需求的精准翻译很多人看到标题第一反应是“就两个类别这也太简单了吧”——这恰恰是最大的误解。在农业视觉检测里“简单”不等于“容易”而是“目标明确”。我们反复跟分拣厂确认过他们的产线只需要做一道分选——把未成熟的青橘通常酸涩、皮厚、糖度8°Bx单独分出来送去深加工比如做青橘酱其余黄橘直接进鲜果包装线。这意味着模型不需要知道它是脐橙、砂糖橘还是蜜桔不需要判断大小、瑕疵、虫眼甚至不需要区分“微黄”和“全黄”只要给出一个二元判决青0 or 黄1。这种极简设计带来三个关键优势第一降低标注成本。如果加第三类“半熟橘”标注员要在青黄交界处反复比对色卡单图平均耗时从12秒拉到47秒错误率上升3倍。而2类别下我们用色度阈值HSV空间H通道20°且S30%做了初筛再由农艺师终审标注一致性达99.2%。第二提升模型鲁棒性。YOLOv5的分类头cls loss在2类别时梯度更稳定。我们做过对比实验同样用yolov5s2类别在验证集mAP0.5达到0.892加了“半熟”后虽然理论上更精细但mAP掉到0.763原因是模型在模糊区域过度拟合把青橘误判为“半熟”的比例高达23%。产线可不接受这种“看起来更科学但实际更错”的结果。第三加速推理速度。2类别模型的cls head只有2个输出神经元比3类别少1个单帧推理快1.8ms在Jetson Nano上实测。别小看这不到2毫秒——产线传送带速度2m/s每秒过橘子15颗1.8ms就是多分拣27颗橘子的吞吐量。所以“2类别”不是技术妥协而是把农业场景的决策逻辑精准映射到模型架构上的结果。它省掉的是无效复杂度留下的是可落地的确定性。2.2 为什么坚持实拍死磕光照和遮挡而不是用GAN生成网络上搜“yolov5训练自己的数据集”一堆教程教你用LabelImgGAN合成数据。我们试过——用StyleGAN2生成了5000张橘子图训练后在测试集上mAP只有0.51。问题出在哪合成数据太“完美”果皮纹理均匀、光照方向单一、背景干净如PS、果柄永远垂直向下。而真实果园里你面对的是正午强光下橘子表面出现镜面高光青橘局部反光后接近黄橘色阴天散射光下黄橘暗部发灰与青橘色差缩小到ΔE15CIELAB色差果柄以30°~75°任意角度遮挡有时只露出半个橘子背景是枝叶、网兜、木箱、水泥地纹理复杂且颜色相近深绿/灰褐/土黄。这套数据集的采集策略就是冲着这些“不完美”去的光照控制分三档——自然光上午9-11点/下午3-5点、阴天、室内LED灯5600K色温漫射板遮挡模拟用细铁丝固定果柄手动调整角度用剪刀剪下真实枝叶随机搭在橘子上背景多样性在果园地面、分拣台、纸箱、塑料筐、水泥地五种背景下拍摄设备冗余iPhone 12广角、华为Mate 40超广角、小米12主摄、海康威视MV-CH200工业相机四路并行确保不同传感器特性都被覆盖。最终数据集里有12.7%的图像存在明显果柄遮挡38.4%的图像背景与橘子色差20CIEDE2000这些“麻烦”恰恰是模型泛化的试金石。当你用这套数据训练时模型学到的不是“橘子长什么样”而是“在各种干扰下怎么抓住成熟度的本质特征”——比如青橘的绿色素反射峰在520nm黄橘的类胡萝卜素在450nm这些光谱差异在RGB图像里表现为特定区域的色相偏移模型通过大量样本自己归纳出了这个规律。3. 数据集核心细节目录结构、标注规范、图像质量控制3.1 目录结构为什么必须严格遵循YOLOv5标准YOLOv5官方文档强调“数据集结构决定训练脚本能否一键运行”这不是虚话。我们采用最标准的datasets/orange_maturity/结构具体如下orange_maturity/ ├── images/ │ ├── train/ │ │ ├── img_001.jpg │ │ ├── img_002.jpg │ │ └── ... │ └── val/ │ ├── img_801.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_001.txt │ │ └── ... │ └── val/ │ ├── img_801.txt │ └── ... └── orange_maturity.yaml # 数据集配置文件这个结构的关键在于路径绝对不可变。YOLOv5的train.py会自动拼接路径--data datasets/orange_maturity/orange_maturity.yaml→ 读取yaml里的train: images/train→ 拼成datasets/orange_maturity/images/train。如果你把images放在根目录下或把train/val混在一个文件夹里训练脚本会报错FileNotFoundError: No such file or directory: datasets/orange_maturity/images/train/img_001.jpg而这个错误信息根本不会告诉你“你放错位置了”只会卡在数据加载环节。orange_maturity.yaml内容精简到极致train: ../images/train val: ../images/val nc: 2 names: [unripe, ripe]注意两点一是train和val路径用../相对引用这是YOLOv5 v6.0的强制要求旧版用绝对路径二是names顺序必须和标签文件中的class_id严格一致0unripe, 1ripe。我们曾遇到一个坑某次导出标注时LabelImg把“ripe”排在前面导致所有黄橘被标成0类训练loss狂降但预测全错——因为模型学的是“把黄橘当青橘”。提示检查数据集是否合规只需执行一条命令python detect.py --weights yolov5s.pt --source datasets/orange_maturity/images/val --conf 0.25如果能正常加载图片并显示bbox说明路径和yaml都没问题如果报错90%是路径拼写错误。3.2 标注规范为什么框必须“紧贴果皮”且避开果柄高光区YOLOv5的bbox回归损失giou loss对框的精度极其敏感。我们制定的标注规则全部围绕“减少回归歧义”展开框必须紧贴橘子外缘不允许留白边如框比橘子大5像素也不允许切掉边缘如框比橘子小3像素。实测表明框偏大时模型会学习到“背景纹理也是橘子特征”导致在树叶背景中误检框偏小时模型过度关注中心区域对侧光下的橘子识别率下降17%。果柄处理原则若果柄完全在橘子轮廓内常见于采摘后框需包含果柄若果柄伸出橘子外树上生长态框必须沿橘子边缘截断绝不延伸至果柄高光区。因为果柄高光在RGB图像中常呈现亮白色与黄橘色域重叠模型会把它当成成熟度特征学走。遮挡处理当枝叶遮挡≤30%时框仍画完整橘子轮廓模型需学会补全遮挡30%时该图直接剔除。我们统计过遮挡30%-50%的图像人工标注一致性仅68%机器学习效果更差。多橘子同框同一图中最多标8个橘子避免密集遮挡且每个框的class_id必须准确。曾有一张图里混入1个青橘和7个黄橘标注员漏标了青橘导致该图在训练中成为“噪声样本”拖慢收敛速度。所有标注文件.txt均用UTF-8编码每行格式class_id center_x center_y width height归一化到0~1。例如0 0.423 0.517 0.286 0.312 # 青橘中心在图像42.3%宽、51.7%高处宽占28.6%高占31.2% 1 0.761 0.389 0.245 0.278 # 黄橘注意YOLOv5要求center_x/center_y是框中心坐标不是左上角用LabelImg标注后必须勾选“YOLO format”导出否则会输出左上角坐标训练时bbox全飘移。3.3 图像质量控制为什么分辨率统一640×640为什么拒绝JPEG压缩YOLOv5默认输入尺寸是640×640这不是随意定的。我们做了三组实验输入320×320小目标直径30px的橘子漏检率达41%因为下采样4次后小目标特征图只剩2×2像素输入1280×1280mAP提升0.03但GPU显存占用翻倍RTX 3090从4.2GB→8.7GB推理速度降为原来的62%输入640×640在显存、速度、精度间取得最佳平衡且与主流工业相机输出分辨率匹配如海康MV-CH200默认输出640×480我们裁切为640×640。因此所有原始图像无论手机拍的4000×3000还是工业相机的640×480都经过无损预处理先裁切再缩放对4:3图像优先裁切顶部/底部保留中心橘子区域对16:9图像裁切左右边双三次插值缩放用OpenCV的cv2.resize(img, (640,640), interpolationcv2.INTER_CUBIC)比最近邻插值保留更多纹理拒绝JPEG压缩所有图像保存为PNG格式。实测对比JPEG Q80压缩会使青橘表皮纹理模糊YOLOv5的backboneCSPDarknet在浅层卷积中提取的边缘特征信噪比下降22%最终导致青橘召回率降低9.3%。最终数据集里1842张图全部为PNG平均大小1.2MB总容量2.1GB。你可以用find . -name *.png | xargs -I {} identify -format %wx%h %f\n {} | sort -u快速验证尺寸是否统一。4. 训练实操指南从环境搭建到mAP验证的全流程踩坑记录4.1 环境搭建为什么推荐conda而非pip为什么CUDA版本必须匹配YOLOv5对环境极其挑剔我们踩过的最大坑是CUDA版本冲突。某次在Ubuntu 20.04上用pip install torch1.12.1cu113结果训练时GPU显存只用了10%CPU占用98%——查了一整天发现是PyTorch的cu113包与NVIDIA驱动470.129不兼容必须降级到cu116。后来我们固化了这套方案# 创建独立环境避免污染主环境 conda create -n yolov5-orange python3.8 conda activate yolov5-orange # 安装PyTorch严格按官网CUDA版本选 # 查当前驱动支持的CUDAnvidia-smi → 右上角显示CUDA Version: 11.7 pip3 install torch1.13.1cu117 torchvision0.14.1cu117 --extra-index-url https://download.pytorch.org/whl/cu117 # 安装YOLOv5依赖用requirements.txt更稳 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt # 包含opencv-python, numpy, matplotlib等为什么用conda因为pip安装的numpy可能与PyTorch的BLAS库冲突导致矩阵运算异常conda的环境隔离能彻底避免这个问题。我们还发现YOLOv5 v6.2要求matplotlib3.3.0但旧版Ubuntu自带的matplotlib 3.1.2会报AttributeError: module matplotlib has no attribute use必须升级。实操心得每次换新机器先运行python detect.py --weights yolov5s.pt --source data/images/zidane.jpg如果能弹出检测窗口说明环境OK如果报ImportError: libcudnn.so.8: cannot open shared object file就是CUDA版本错了。4.2 训练命令详解为什么--batch-size不能贪大为什么--epochs要设为300标准训练命令python train.py \ --img 640 \ --batch 16 \ --epochs 300 \ --data ../datasets/orange_maturity/orange_maturity.yaml \ --weights yolov5s.pt \ --name orange_maturity_exp1 \ --cache参数解析--img 640必须与数据集图像尺寸一致否则会触发动态resize增加计算开销--batch 16这是RTX 3090的极限值。如果用GTX 16606GB显存必须降到--batch 8否则OOMOut of Memory实测--batch 32在3090上显存占用11.2GB但loss震荡剧烈收敛变慢--epochs 300不是随便定的。我们监控过loss曲线前100epoch快速下降100-200epoch缓慢收敛200-300epoch进入平台期。设200epoch时val mAP0.5停在0.871设300epoch后稳定在0.892提升0.021——这0.021在产线上意味着每小时多分拣132颗橘子--cache把图像缓存到RAM提速40%。但内存小于32GB的机器慎用否则系统卡死。最关键的隐藏参数是--workers 8数据加载线程数。我们测试过workers0时GPU利用率仅45%workers4时升到78%workers8时达92%再高无提升。这是因为YOLOv5的数据增强Mosaic、HSV调整很吃CPU线程数必须匹配CPU核心数。常见问题训练中途卡住不动大概率是--workers设太高某个线程在读取损坏PNG时阻塞。解决方案加--nosave跳过保存中间权重用--evolve进化超参或直接--workers 4重试。4.3 验证与评估如何解读results.txt为什么mAP0.5比mAP0.5:0.95更重要训练完成后runs/train/orange_maturity_exp1/results.txt里有10列数据我们只关注前三列Epoch GPU_mem box_loss obj_loss cls_loss ... metrics/mAP_0.5 metrics/mAP_0.5:0.95 0 4.2G 0.0721 0.0456 0.0312 ... 0.421 0.287 ... 299 4.2G 0.0183 0.0121 0.0087 ... 0.892 0.634box_loss定位损失越低说明框越准cls_loss分类损失越低说明成熟度判别越准metrics/mAP_0.5IoU阈值为0.5时的平均精度产线最关心这个——只要框和真值重叠一半就算对metrics/mAP_0.5:0.95IoU从0.5到0.95步长0.05的平均学术论文爱用但产线意义不大。因为分拣机只要求“别把青橘当黄橘”不要求框精确到像素级。我们实测发现当mAP_0.5达0.892时mAP_0.5:0.95只有0.634差值0.258。这意味着模型能稳定识别出橘子在哪、是什么状态但框的精度还有提升空间——这完全OK因为分拣机械臂的抓取容差是±15mm而640×640图像中15mm≈32像素IoU0.5时框误差完全在容差内。验证模型效果用这条命令python val.py \ --data ../datasets/orange_maturity/orange_maturity.yaml \ --weights runs/train/orange_maturity_exp1/weights/best.pt \ --task test # 用val集验证不是test集输出confusion_matrix.png比数字更直观理想情况是左上青橘和右下黄橘两个方块颜色深左下青橘误判黄橘和右上黄橘误判青橘颜色浅。我们这套数据集训练出的模型混淆矩阵里误判率仅3.2%青→黄和2.8%黄→青远优于人工分拣的8.7%错误率。5. 常见问题与排查技巧实录那些文档里不会写的实战经验5.1 “训练loss不下降”先查这三件事网上90%的“loss降不下来”问题其实和数据无关而是环境或操作失误yaml路径写错train: ../images/train写成train: images/train少..YOLOv5会静默加载空目录loss恒为0.000但你根本看不到报错标签文件名不匹配img_001.jpg对应img_001.txt但有人导出时生成001.txtYOLOv5找不到标签自动跳过该图loss虚高class_id越界标注时写了2黄橘应为1YOLOv5会报IndexError: index 2 is out of bounds for dimension 0 with size 2但错误堆栈藏在深处新手根本找不到。排查技巧在train.py开头加一行print(Loading dataset from:, opt.data)再加print(Found %d images, %d labels % (len(dataset), len(labels)))运行时看输出数字是否合理1842图对应1842标签。5.2 “验证mAP很低”90%是验证集划分问题很多人把数据集按8:2随机划分结果验证集里全是阴天拍的黄橘训练集全是晴天青橘——模型根本没见过阴天黄橘mAP当然低。我们的划分策略是按采集条件分层抽样先按光照分组自然光1240图、阴天328图、室内274图每组内再按成熟度比例划分自然光组青橘:黄橘1:1.2就按相同比例分train/val最终train集1472图青橘721黄橘751val集370图青橘182黄橘188比例完全一致。验证集划分代码用pandasimport pandas as pd from sklearn.model_selection import train_test_split df pd.read_csv(metadata.csv) # 含filename,light_condition,ripeness train_df, val_df train_test_split( df, test_size0.2, stratifydf[[light_condition, ripeness]], # 分层依据 random_state42 )5.3 “部署后效果差”不是模型问题是预处理不一致在PC上训练好部署到Jetson Nano上效果暴跌原因往往是预处理链不一致。YOLOv5默认用letterbox保持宽高比灰色填充但很多嵌入式部署教程教用resize直接拉伸导致橘子变形模型认不出。正确做法在推理代码里必须复现训练时的预处理# 训练时YOLOv5用的预处理 img cv2.imread(img.jpg) img letterbox(img, 640, stride32)[0] # 关键不是cv2.resize img img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, HWC to CHW img np.ascontiguousarray(img)我们吃过亏第一次部署时用cv2.resize(img, (640,640))黄橘识别率从89%掉到61%。改成letterbox后回升到87.3%略低于PC因算力限制这才是真实差距。5.4 数据集扩展建议如何低成本提升泛化能力这套数据集已够用但想进一步提升我们推荐三个低成本方法添加“伪标签”数据用训练好的best.pt对果园新拍的1000张图做推理筛选置信度0.9的预测框人工校验后加入训练集。我们试过加500张伪标签后mAP提升0.012针对性增强用Albumentations加RandomSunFlare模拟强光高光、RandomShadow模拟枝叶遮挡专攻模型薄弱点跨域微调下载公开的Fruits-360数据集含橘子图冻结backbone只训练head层再用本数据集finetune——相当于给模型“预习课本”实测收敛快2倍。最后分享个小技巧每次训练完用python detect.py --weights best.pt --source datasets/orange_maturity/images/val --save-txt生成所有val图的预测txt然后用脚本统计“青橘被误判为黄橘”的图像重点分析这些图的共性是不是都逆光是不是都有果柄遮挡下次采集就专门补这些场景。这才是数据驱动的迭代闭环。本文还有配套的精品资源点击获取
返回列表