橘子成熟度检测数据集:YOLOv5二分类训练与验证全流程

发布时间:2026/9/27 3:38:17
橘子成熟度检测数据集:YOLOv5二分类训练与验证全流程 简介这份数据集面向从事柑橘采摘自动化、农业视觉检测的开发者与研究者提供橘子成熟度二分类目标检测所需的完整标注数据可直接接入YOLOv5训练流程省去自行采集与标注的成本。包内共约2000个文件以txt标注文件为主另附一个可视化脚本压缩包整体约79MB按YOLOv5标准目录组织训练集含2313张图片及对应标签验证集含224张图片及对应标签图像为640×640分辨率RGB格式边界框标注清晰、图像完整。类别仅成熟与未成熟两类标签文本简洁明确。附带的Python可视化脚本无需修改随机传入一张图片即可绘制边界框并保存到当前目录便于快速核验标注质量。目前已有435人学习下载适合需要快速验证成熟度检测模型或搭建自动采摘原型的读者参考使用。1. 橘子成熟度检测数据集2 类别、训练集与验证集到底怎么用果园里最怕的不是没橘子而是摘早了酸、摘晚了烂。我去年帮一个做分拣设备的朋友看模型他拿网上随便凑的橘子图训了一版 YOLOv5验证集 mAP 看着有 0.8拉到产线上一照青皮橘子全被判成成熟原因很简单——他的数据集里“未成熟”这一类几乎全是远景小目标模型根本没学到青绿果皮在近景下的纹理。这就是标题里“橘子是否成熟检测2 类别包含训练集、验证集”真正要解决的问题它不是让你跑通一个 demo而是让你拿到一份能直接喂给 YOLOv5、类别定义清晰、训练验证划分合理的数据集把“成熟 / 未成熟”这个二分类检测任务做扎实。这份数据集的核心价值在于两点。第一类别只有两个标注边界清楚不像多类别数据集那样容易在相似类别间反复横跳适合刚接触 YOLOv5 训练自己数据集的人快速建立完整链路。第二它自带训练集和验证集意味着你不需要自己从零划分省掉了“按 8:2 随机切分”这种看似简单、实则容易切出分布偏差的步骤。适合谁用做农业视觉分拣的、做采摘机器人感知模块的、以及想拿一个真实二分类检测任务练手 YOLOv5 环境配置和超参数调整的工程师。下面我按“数据怎么读 → 环境怎么搭 → 训练怎么跑 → 坑在哪 → 怎么验证”这条线把能抄作业的部分写清楚。2. 橘子成熟度数据集的目录结构与标注格式先看懂再动手2.1 训练集、验证集、标注文件三者的对应关系拿到一份目标检测数据集第一件事不是急着写训练脚本而是把目录结构摸清楚。常见做法是根目录下分images和labels再各自分train和val。但不同来源的数据集组织方式有差异有的把训练集和验证集直接放在两个大文件夹里有的用train.txt/val.txt列出图片路径。你拿到手之后先跑一条命令把结构打出来# 查看数据集目录树只看两层避免图片太多刷屏 find ./orange_ripeness_dataset -maxdepth 2 -type d | sort这条命令只列目录不列文件目的是确认images/train、images/val、labels/train、labels/val这四个关键路径是否存在。如果发现只有train和val两个文件夹里面混着图片和 txt那说明它用的是“图片与标注同目录”的组织方式YOLOv5 也能读但需要在 data.yaml 里把路径写对。标注格式方面YOLOv5 用的是 YOLO 格式 txt每行一个目标格式为class_id x_center y_center width height后四个值都是相对图片宽高的归一化值范围 0 到 1。二分类任务里class_id只有 0 和 1。我一般会先抽查几个标注文件确认没有越界值# 抽查标注文件检查归一化坐标是否在 0~1 之间 import os label_dir ./orange_ripeness_dataset/labels/train bad_files [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname)) as f: for line_no, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: bad_files.append((fname, line_no, 字段数不对)) continue cls_id int(parts[0]) coords [float(x) for x in parts[1:]] if cls_id not in (0, 1): bad_files.append((fname, line_no, f类别ID异常: {cls_id})) if any(c 0 or c 1 for c in coords): bad_files.append((fname, line_no, f坐标越界: {coords})) print(f异常标注条数: {len(bad_files)}) for item in bad_files[:10]: print(item)这段脚本做三件事检查每行是否恰好 5 个字段、类别 ID 是否只在 0 和 1 之间、归一化坐标是否越界。参数上不需要调直接跑即可。如果异常条数不为零先别急着训练把对应文件挑出来人工看一眼常见的是标注工具导出时把像素坐标直接写进去了这种必须转回归一化坐标否则模型学到的框会全部偏到图片角落。2.2 data.yaml 的写法与两个类别的命名约定YOLOv5 训练时靠一个 yaml 文件告诉它去哪里找数据、有几个类别、类别叫什么。这个文件我一般命名为orange.yaml放在项目根目录或data目录下。写法如下# orange.yaml path: ./orange_ripeness_dataset # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 nc: 2 # 类别数 names: [unripe, ripe] # 类别名顺序必须与标注里的 class_id 对应这里有几个参数值得说清楚。path是根目录train和val是相对于path的路径YOLOv5 会自动把images替换成labels去找标注所以你的目录里必须有同级的labels/train和labels/val。nc是类别数二分类就写 2。names的顺序至关重要如果你的标注里 0 代表未成熟、1 代表成熟那 names 就必须是[unripe, ripe]写反了模型训练不会报错但推理时标签会全部颠倒这种坑我见过不止一次。提示改完 yaml 后用 YOLOv5 自带的检查脚本跑一遍确认图片和标注能一一对应上比训练到一半才发现缺标注要省事得多。2.3 用一条命令确认图片与标注数量是否对齐图片和标注必须一一对应缺一个都会在训练时被跳过或报错。我习惯用下面这条命令快速核对# 分别统计训练集图片数和标注数两者应相等 echo train images: $(ls ./orange_ripeness_dataset/images/train | wc -l) echo train labels: $(ls ./orange_ripeness_dataset/labels/train | wc -l) echo val images: $(ls ./orange_ripeness_dataset/images/val | wc -l) echo val labels: $(ls ./orange_ripeness_dataset/labels/val | wc -l)四个数字里前两个应该相等后两个应该相等。如果标注数少于图片数说明有图片没有对应标注YOLOv5 默认会把这些图片当负样本处理但如果你确定每张图里都有橘子那就是标注漏了。如果标注数多于图片数多出来的标注文件会被忽略。这一步花不了一分钟但能避免训练日志里出现大量“missing labels”警告。3. 用 YOLOv5 跑通橘子成熟度训练环境、命令与参数3.1 环境配置与依赖安装的稳定路径YOLOv5 的环境配置说简单也简单说玄学也玄学主要坑在 PyTorch 版本和 CUDA 的匹配上。我一般用 conda 建一个干净环境避免和系统里的其他包打架# 创建并激活 conda 环境 conda create -n orange_yolo python3.9 -y conda activate orange_yolo # 安装 PyTorch这里以 CUDA 11.8 为例具体按你的显卡驱动选 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 源码并安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt参数说明Python 选 3.9 是因为它在 YOLOv5 各版本上兼容性最稳CUDA 版本要和你nvidia-smi右上角显示的版本匹配不要超过驱动支持的上限。装完之后跑一句python -c import torch; print(torch.cuda.is_available())输出 True 才算环境通了。如果输出 False先别往下走检查驱动和 CUDA 版本这一步翻车后面全白搭。3.2 训练命令与关键超参数怎么设环境通了之后训练命令本身不复杂但参数设不对二分类任务很容易过拟合或欠拟合。我常用的起手命令python train.py \ --data orange.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --workers 4 \ --project runs/train \ --name orange_exp1逐项说--data指向你写好的 yaml--weights用预训练的yolov5s.pt小模型在二分类任务上够用且训练快如果你数据量很大再考虑yolov5m--img 640是输入分辨率橘子检测一般 640 足够如果果实占画面比例很小可以提到 1280但显存要跟上--batch 16是批大小显存不够就降到 8 或 4--epochs 100对二分类通常够收敛但要看验证集 mAP 曲线如果 80 轮还在涨就加到 150--workers是数据加载线程设成 CPU 核心数的一半左右比较稳。训练开始后重点盯三个指标box_loss、obj_loss、mAP0.5。二分类任务里如果obj_loss一直不降多半是标注框有问题如果mAP0.5在训练集上很高但验证集上很低那就是过拟合需要加数据增强或减模型复杂度。3.3 训练过程中该看什么、不该频繁动什么YOLOv5 训练日志会实时打印每轮的损失和 mAP我一般不会频繁中断训练去调参而是等一轮完整跑完再看趋势。真正需要中途干预的情况只有两种一是显存溢出CUDA out of memory这时候停掉把 batch 减半再重启二是损失变成 NaN通常是学习率太大或标注里有非法值先查标注再降学习率。不该做的事不要因为前 10 轮 mAP 低就急着换模型或改数据YOLOv5 在前 20 轮通常还在预热阶段mAP 波动很正常。另外不要一边训练一边改 yaml 或标注文件YOLOv5 会在启动时缓存标签中途改文件不会生效反而让你误以为改动没用。注意如果你用的是自己划分的训练集和验证集而不是数据集自带的务必确认验证集里的橘子成熟度分布和训练集接近否则 mAP 会虚高或虚低参考价值大打折扣。4. 橘子成熟度检测的避坑与排查5 个血泪教训4.1 验证集 mAP 很高但实际推理全错现象训练日志里验证集 mAP0.5 到了 0.9 以上但拿几张新拍的橘子图去推理成熟和未成熟几乎全判反。原因最常见的是names顺序和标注class_id反了模型学到的“0 号类别”其实是成熟但你在 yaml 里写成了未成熟。解决回头核对标注文件里 0 和 1 分别对应什么把 names 改对重新训练。如果 names 没错那就检查验证集图片是否和训练集来自同一批拍摄条件分布差异过大会导致验证集指标失真。4.2 训练到一半报“missing labels”大量警告现象日志里刷屏missing labels训练能继续但 mAP 很低。原因图片路径和标注路径没有对应上YOLOv5 按images替换成labels去找如果你的目录结构是train/images和train/labels但 yaml 里写的是images/train路径就错了。解决用第 2.3 节的命令核对数量再检查 yaml 里的train和val路径是否相对于path正确。路径里不要用绝对路径除非你确定换机器后路径不变。4.3 显存溢出导致训练中断现象跑了几轮之后突然CUDA out of memory。原因YOLOv5 在训练初期显存占用会波动如果 batch 设得刚好卡在显存上限后期数据增强或缓存就可能撑爆。解决把--batch降到 8 或 4同时把--img从 640 降到 512 试试。如果还不行加--nosave减少 checkpoint 占用或者换更小的yolov5n模型。不要盲目加--device 0指定显卡多卡环境下指定错卡反而更糟。4.4 标注框大量重叠或超出边界现象训练损失震荡不收敛推理时框乱飞。原因标注时框画得太大或太小或者多个框严重重叠YOLOv5 的 anchor 匹配会混乱。解决用第 2.1 节的脚本查坐标越界再抽查几个标注文件把明显不合理的框重新标。二分类任务里一个橘子只应该有一个框如果同一颗橘子被标了两次删掉重复的。4.5 验证集指标虚高但实际分拣误判多现象验证集 mAP 好看但产线上青橘子和黄橘子分不清。原因验证集和训练集可能来自同一段视频的相邻帧画面高度相似模型只是记住了背景而不是果皮颜色。解决如果数据集自带的验证集和训练集同源建议自己从不同时间段、不同光照条件下另切一份验证集重新评估。这一步能暴露真实泛化能力比盯着虚高的 mAP 有用得多。5. 验证橘子成熟度模型是否真的可用三个进阶技巧训练跑完、mAP 看着不错不代表模型能上产线。我一般会用下面三个方法做最终验证顺序从简到繁。第一个技巧是混淆矩阵细看。YOLOv5 训练结束后会在runs/train/orange_exp1下生成confusion_matrix.png不要只看 mAP 数字打开这张图看“未成熟”被误判成“成熟”的比例。如果这个比例超过 10%说明模型对青绿果皮的敏感度不够需要补充更多未成熟橘子的近景样本或者把--img提高到 1280 让果皮纹理更清晰。第二个技巧是拿视频流做连续推理。单张图片的指标有偶然性用一段果园实拍视频跑detect.py观察同一颗橘子在连续帧里的类别是否稳定。如果类别频繁跳变说明模型置信度阈值设得太低可以在推理时加--conf 0.5过滤掉低置信度框。下面这条命令把结果保存成带框视频python detect.py \ --weights runs/train/orange_exp1/weights/best.pt \ --source ./test_videos/orchard.mp4 \ --conf 0.5 \ --img 640 \ --project runs/detect \ --name orange_test参数上--conf 0.5是置信度阈值二分类任务里可以设到 0.5 到 0.6太低会引入大量误检--img要和训练时一致否则精度会掉。跑完之后逐帧看重点看遮挡、逆光、果实重叠这三种情况下的表现。第三个技巧是做一个最小分拣逻辑验证。检测框出来之后真正决定“摘不摘”的是业务逻辑。我一般会写一个简单脚本统计画面里成熟橘子的数量和位置模拟分拣信号# 模拟分拣逻辑统计成熟橘子数量并输出信号 import cv2 import torch model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/orange_exp1/weights/best.pt) model.conf 0.5 img cv2.imread(./test_images/sample.jpg) results model(img) df results.pandas().xyxy[0] # 列xmin, ymin, xmax, ymax, confidence, class, name ripe_count len(df[df[name] ripe]) unripe_count len(df[df[name] unripe]) if ripe_count 0 and unripe_count 0: print(信号可采摘) elif unripe_count 0: print(f信号暂缓未成熟 {unripe_count} 个) else: print(信号无目标)这段代码把检测结果转成业务信号model.conf控制置信度阈值df[name]对应 yaml 里的类别名。跑几张不同场景的图看信号是否符合预期。如果“可采摘”信号在青橘子画面上也触发说明模型还没过关回去补数据或调阈值。我自己的习惯是任何检测模型上线前至少用 20 张完全没参与训练的新图跑一遍这个逻辑人工核对每一张的信号。这一步没有捷径但能让你在产线翻车之前先在自己电脑上翻一次。希望帮到你。本文还有配套的精品资源点击获取