简介一套面向目标检测学习者的水果识别数据集涵盖菠萝、李子、红番茄、西瓜等类别图片来自真实场景已按 YOLO 标准划分好 train、val、test 目录并附带 data.yaml 配置文件可直接用于 YOLOv5、YOLOv7、YOLOv8 等模型训练省去自行采集、标注和格式转换的环节。压缩包内共 1107 个文件包括 553 张 JPG 图片、553 个对应 txt 标注文件以及 1 个 YAML 配置整体大小约 31.72MB目录结构清晰方便按需调用同时同名 txt 与 JPG 一一对应便于快速检查标注质量。目前已有 840 人学习下载。对刚入门目标检测的开发者来说这是现成的实验数据对有经验的工程师也能用于迁移学习、数据增强或模型对比测试。1. 水果检测数据集能直接开训几百张图目录和 yaml 都已备好做目标检测最怕的不是训练慢而是数据没备好。很多从网上下载的水果图片集图片是一堆标注却没有统一的格式还得自己写脚本转成 YOLO 的 txt更别说划分 train、val、test。这份 yolov5 水果检测数据集压缩包解压后就是可以直接丢进 YOLO 系算法的状态图片已经统一缩放标注是 YOLO 格式的 txt训练集、验证集、测试集按目录分好data.yaml 也写好了类别和路径。对想快速验证 YOLOv5 流程、或者做水果检测 demo 的人来说省掉了最枯燥的数据整理环节。适合三种人刚接触目标检测、想跑通训练流程的新手需要一份干净数据做算法对比的从业者以及临时要做水果识别演示的开发者。接下来我从目录结构讲起带你把这套数据集从头到尾用起来。2. 解压后先看目录结构train/valid/test 划分与 data.yaml 的映射关系2.1 目录结构与 label 文件细节拿到压缩包第一步不是急着训练而是把目录树打出来看清楚。常见结构是这样的fruit-detect-yolov5-5/ ├── train/ │ ├── images/ │ │ ├── plums-190832_640_jpg.rf.0576a85afbd1d7d9f69d798bbaa46833.jpg │ │ └── ... │ └── labels/ │ ├── plums-190832_640_jpg.rf.0576a85afbd1d7d9f69d798bbaa46833.txt │ └── ... ├── valid/ │ ├── images/ │ └── labels/ ├── test/ │ ├── images/ │ └── labels/ └── data.yaml图片文件名里有.rf.这个标记说明这批图经过 Roboflow 平台处理过原始图片被统一缩放到了 640 边长这个尺寸正好是 YOLOv5 默认输入尺寸训练时不用额外改 imgsz。每个 jpg 对应一个同名 txttxt 里每一行是一个目标框格式是class_id x_center y_center width height前四个值是归一化到 0~1 的浮点数。这种格式是 YOLO 系列通用的所以 YOLOv5、YOLOv7、YOLOv8 都能直接吃。2.2 data.yaml 的类别配置与路径写法data.yaml 是训练时的数据入口里面写明了类别清单和路径。这份数据集的 yaml 内容如下names: [ pineapple, plum, redtomato, semangka] train: ./train/images val: ./valid/images test: ./test/images注意类别列表里有四个类pineapple 是菠萝plum 是李子redtomato 是红番茄semangka 是印尼语里的西瓜。如果你训练时看到类别名跟你预期不一样先对照这里。train、val、test写的是相对路径这意味着运行时你的当前工作目录必须是数据集根目录或者你要把 yaml 里的路径改成绝对路径。很多人在这一步翻车——在项目目录下执行训练命令data.yaml 还写着./train/images结果系统去项目目录下找 train 文件夹找不到就报错。2.3 图片和标注如何一一对应命名规则与检查方法YOLO 格式依赖“同名同目录”的对应关系图片在 train/images 下标注在 train/labels 下只是顶层目录不同。检查对应关系最快的方法是写一行 bashfor f in train/images/*.jpg; do name$(basename $f .jpg) if [ ! -f train/labels/$name.txt ]; then echo missing label for $name fi done这段逻辑很简单遍历每张图片取出不带后缀的文件名再检查 labels 目录是否存在同名 txt。如果有输出缺失列表说明标注文件不完整。我一般还会顺手统计一下 txt 的行数如果某张图的 txt 是空文件意味着图中没有目标这种样本多了会干扰训练最好提前剔除。做这一步不是强迫症而是 YOLO 训练时如果标签文件损坏或缺失常会报奇怪的索引错误提前排查能省很多时间。3. 用自己的数据训练前先做这几项数据体检3.1 图片尺寸与 EXIF 方向检查虽然这份数据集声称已经统一到 640但下载解压的环节里可能出现文件损坏或者有人二次压缩。训练前我习惯用 Python 统一检查一遍图片尺寸from PIL import Image import os img_dir train/images for f in os.listdir(img_dir): p os.path.join(img_dir, f) with Image.open(p) as im: w, h im.size if (w, h) ! (640, 640): print(f{f}: {w}x{h})这段代码用 Pillow 读取每张图片的宽高只要不是 640 就打印出来。YOLOv5 训练时会自动做 letterbox 缩放理论上不强制 640但如果你发现一批图是 640、另一批是 480混合训练会让模型对尺寸的适应性变差尤其是小目标。另外要注意 EXIF 方向手机拍的图经常带旋转信息Pillow 读出来的宽高可能和实际显示相反。可用im.getexif()查看 Orientation 字段若有值最好用ImageOps.exif_transpose重转一遍再存。常见做法是在数据准备阶段统一处理而不是让训练脚本去猜。3.2 标注框的有效性检查越界、空标注、类别错误YOLO 格式的框坐标是归一化的理论上都在 0~1 之间但手工标注或转换脚本可能产生越界框。比如标注时手抖把 width 写成了 1.2或者 x_center 是负数。训练时这些框会被裁剪但会导致 loss 异常波动。检查脚本如下import os label_dir train/labels cls_id 0 for f in os.listdir(label_dir): p os.path.join(label_dir, f) for line in open(p): parts line.strip().split() if len(parts) ! 5: print(f{f}: bad format - {line}) continue cid int(parts[0]) x, y, w, h map(float, parts[1:]) if cid 0 or cid 4: print(f{f}: class id out of range - {cid}) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): print(f{f}: box out of range - {line})这里三个检查点每行必须 5 个值class_id 必须在 0~3 之间四个坐标值必须在 0~1 之间。如果出现越界简单暴力的做法是直接把该样本删掉或者用np.clip把坐标裁剪到 0~1。但裁剪要谨慎如果框的中心点本身在图片外裁剪后这个框可能变成一条线等于噪声不如删掉。3.3 用脚本可视化标注确认框与目标匹配标签数值检查只能保证格式合法不能保证框的位置准。最直观的方式是把标注画到图片上肉眼扫一遍。我一般用 OpenCV 画import cv2 import os img_dir train/images label_dir train/labels out_dir check_vis os.makedirs(out_dir, exist_okTrue) colors [(0, 255, 0), (0, 0, 255), (255, 0, 0), (0, 255, 255)] names [pineapple, plum, redtomato, semangka] for f in os.listdir(img_dir): img_path os.path.join(img_dir, f) label_path os.path.join(label_dir, os.path.splitext(f)[0] .txt) if not os.path.exists(label_path): continue img cv2.imread(img_path) h, w img.shape[:2] for line in open(label_path): cid, x, y, bw, bh map(float, line.strip().split()) cid int(cid) x1 int((x - bw / 2) * w) y1 int((y - bh / 2) * h) x2 int((x bw / 2) * w) y2 int((y bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[cid % 4], 2) cv2.putText(img, names[cid], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[cid % 4], 2) cv2.imwrite(os.path.join(out_dir, f), img)这段脚本把每个框按类别颜色画出来并写上名称。跑完后去 check_vis 目录里翻一遍重点看李子的框有没有把旁边的叶子包进去红番茄的框是不是只框住了番茄没框住茎西瓜这种大目标有没有只框一半。可视化这一步没什么玄学但它能暴露标注错误里最坑的一类——标签和图像内容对不上。比如一张青番茄的图标注可能是 redtomato模型训练完了遇到青番茄就检测不出来这种坑在纯数值检查里根本发现不了。3.4 类别分布统计与不均衡处理最后统计一下每个类别的目标数量看是否有严重不均衡。执行下面这段import os from collections import Counter cnt Counter() for split in [train, valid, test]: label_dir f{split}/labels for f in os.listdir(label_dir): for line in open(os.path.join(label_dir, f)): cid int(line.strip().split()[0]) cnt[cid] 1 print(split, cnt)输出结果可以对比每个类别在 train 里的数量。如果 pineapple 只有几十个框而 plum 有几百个模型会偏向 plum。处理办法有两个一是对过少的类别做过采样也就是在训练时多重复几次该类的图片YOLOv5 里可以用--image-weights参数让采样权重按类别分布调整二是对过多的类别做欠采样删掉一部分冗余样本。对于这份几百张的数据集我建议先不管均衡性直接跑一轮看各类 AP 的差距如果某个类 AP 明显低再回来采样。新手最容易犯的错是一上来就追求数据完美结果把时间都花在造数据上反而没空跑训练。4. 在 YOLOv5 和 YOLOv8 上跑通训练关键参数与命令4.1 环境准备与数据集路径放置这份数据集可以同时用于 YOLOv5、YOLOv7、YOLOv8因为它们读取数据集的逻辑是相通的都认 YOLO 格式的 txt 和 yaml 文件。第一步把数据集放到项目能访问的路径。我习惯放在与yolov5目录平级的datasets/下YOUR_PROJECT/ ├── yolov5/ ├── datasets/ │ └── fruit-detect/ # 把解压出来的 train/ valid/ test/ data.yaml 放这里放入后要把data.yaml里的路径改成相对数据集根目录的写法并在 yaml 中加上path字段。我常用的一种写法是path: ../datasets/fruit-detect # 相对 yolov5 项目根目录 train: train/images val: valid/images test: test/images names: [ pineapple, plum, redtomato, semangka]注意path是 YOLOv5 和 YOLOv8 都支持的顶层字段写相对路径时以你执行训练命令的目录为准。如果你把数据集放在datasets/fruit-detect而训练命令在yolov5/下执行上面的../datasets/fruit-detect就能正确解析。如果怕路径出错直接用绝对路径最省事path: /home/user/YOUR_PROJECT/datasets/fruit-detect绝对路径的问题是不方便换机器但训练自己电脑上跑的 demo绝对路径反而更稳。4.2 YOLOv5 训练命令与超参数说明进入yolov5目录确认已经按官方文档装好依赖然后执行python train.py \ --data ../datasets/fruit-detect/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project fruits \ --name exp1各参数含义--data指向 yaml 文件--weights用预训练权重 yolov5s.pt它会在首次运行时自动下载--img输入图片尺寸这里用 640 与数据集保持一致--batch批大小8G 显存建议 16显存不够就降到 8--epochs训练轮数几百张的数据集 100 轮基本收敛--project和--name决定输出目录训练结果会写到fruits/exp1/下包括权重best.pt和last.pt以及训练曲线results.png。训练完成后验证集上的指标会打印在终端重点关注mAP0.5和mAP0.5:0.95。水果目标比较大mAP0.5一般能到 0.9 以上如果只有 0.7 左右要么数据标注有问题要么训练轮数太少。用--resume可以从断点继续训练比如python train.py --resume fruits/exp1/weights/last.pt这个命令会加载 last.pt 并继续原来的训练计划。我用这个功能时吃过亏——它必须配合原来的 data 参数才能正确恢复如果你换了一个 data.yaml它也会接着跑但结果会乱。所以恢复训练前先确认opt.yaml里的配置是不是你要的。4.3 YOLOv8 训练命令与模型选择如果你更习惯 ultralytics 的接口YOLOv8 的写法更简洁用 Python 或命令行都行。命令行如下yolo train \ data../datasets/fruit-detect/data.yaml \ modelyolov8s.pt \ imgsz640 \ batch16 \ epochs100 \ projectfruits \ nameexp8YOLOv8 使用modelyolov8s.pt指定预训练权重同样会自动下载。它的输出目录默认是fruits/exp8/weights/best.pt训练日志里会有更多的指标曲线包括每个类别的PR_curve.png、confusion_matrix.png。在这份小数据集上YOLOv8s 的速度比 YOLOv5s 略慢一点点但精度差距不大选择哪个主要看你后续要部署在哪里。如果要在树莓派 5 上部署我建议用 YOLOv5s因为它的 ONNX 导出和量化生态更成熟如果只是做个实验对比YOLOv8 的 API 更顺。4.4 训练中断恢复与结果输出训练过程可能因为断电、显存溢出等原因中断。YOLOv5 的中断恢复上面提到了--resume。YOLOv8 则是重新执行同样的命令并加resumeTrueyolo train resumeTrue projectfruits nameexp8它会自动寻找fruits/exp8/weights/last.pt继续训练。使用前提是之前至少保存过 last.pt所以训练前不要删任何中间产物。训练结束后fruits/exp1/目录下会生成best.pt验证集上最优权重、last.pt最后一轮权重、results.pngloss 和 mAP 曲线、confusion_matrix.png混淆矩阵。如果你的任务是快速得到一个能用的模型直接拿best.pt做推理如果你打算继续训练更多轮次可以拿last.pt作为初始权重继续跑它比从 COCO 预训练权重起步更贴近这个数据分布。5. 训练中的避坑与常见问题排查5.1 训练 loss 一直是 nan现象训练开始后终端打印的box_loss或cls_loss出现nan并且一直不恢复。原因最常见的是学习率过大或者是标注文件里出现了非法值比如坐标是空行、标签文本用了中文或逗号分隔。YOLOv5 的 dataloader 会读取 txt但它对非法格式的容错并不高一个解析错误可能导致整个 batch 的 loss 计算失败。解决先用第 3.2 节的脚本检查所有 txt 文件确认没有空行、没有奇数个字段。如果数据没问题把学习率调低在train.py里加--lr0 0.001默认是 0.01。小数据集上学习率太高权重很容易发散。5.2 验证集 mAP 一直为 0现象训练损失正常下降但验证集上mAP0.5始终是 0precision和recall也都是 0。原因类别标签错位。比如 data.yaml 里的类别顺序是[pineapple, plum, redtomato, semangka]但标注 txt 里的 class_id 是按[plum, pineapple, ...]顺序生成的。模型在训练时把 class_id0 当成 pineapple而验证时也按 data.yaml 解析但预测结果却对应错了真实类别导致匹配不上。解决随机挑几个 txt 文件对照原图看 class_id 对应的目标确认类别顺序完全一致。这类问题在从 Roboflow 等平台导出的数据集中很少见但如果你手动改过 yaml 里的 names就很容易出这种错。排查时用第 3.3 节的可视化脚本把类别名称画在框上一眼就能看出标签是否错位。5.3 训练时报错找不到图片或 paths 不存在现象运行训练命令后报AssertionError: train: No labels in ...或FileNotFoundError。原因data.yaml 中的路径相对于当前执行命令的目录解析不了。我遇到过最典型的情况是在yolov5/下执行python train.py --data ./datasets/fruit-detect/data.yaml但 data.yaml 里写的是train: ./train/images这时系统会去找yolov5/train/images显然不存在。解决统一在 data.yaml 里加上path字段写成绝对路径或者../datasets/...这样的相对路径。注意path和train、val是拼接关系如果写了pathtrain最好写成train/images而不是./train/images后者虽然能解析但容易混淆。5.4 显存不足 OOM现象训练刚开始就报CUDA out of memory或者跑几轮后中断。原因batch size 或模型规模超过显存容量。默认的yolov5s在 640 精度下batch 16 大约需要 8G 显存如果你用yolov5l且 batch 3216G 也不够用。解决先缩小 batch比如--batch 8再不行就换更小的模型yolov5n。还有一个技巧是开启梯度累积YOLOv5 没有直接的梯度累积参数但你可以用--batch 8 --accumulate 4达到等效 batch 32 的效果。YOLOv8 也有类似的策略减少 batch 即可。不建议为了跑大批次而把图片 resize 到 320因为小尺寸会明显降低小目标检测能力尤其是李子这种小圆果。5.5 训练结束后 results.png 里 mAP 曲线剧烈震荡现象mAP 曲线上下跳动幅度超过 10 个点无法判断最终收敛值。原因验证集样本太少或者 batch 内随机抽样的波动。这份数据集就几百张valid 集可能只有几十张指标受单张图片影响很大。解决一是把 train.py 里的--val间隔调大一点比如每 5 轮验证一次减少波动感二是不必纠结中间曲线直接看best.pt对应的最终指标。如果验证集实在太小可以沿用训练集的分布用测试集做 final validation但前提是 test 集没有参与训练。6. 验证训练效果用训练好的模型做推理并看懂指标6.1 用 detect.py 做批量推理训练结束后不要只看终端指标拿几张没见过的图跑一遍推理感受模型的实际表现。YOLOv5 的推理命令python detect.py \ --weights fruits/exp1/weights/best.pt \ --source ../datasets/fruit-detect/test/images \ --conf-thres 0.3 \ --project inference_results \ --name test_run--conf-thres控制置信度阈值0.3 比较宽松能看到更多漏检和误检如果只想看高置信度的框调到 0.5。推理结果会保存为标注了类别和置信度的图片逐个翻看重点观察红番茄会不会被漏掉西瓜和菠萝这种大目标的框是否贴合边缘。6.2 看懂 results.png 与 confusion_matrix.confusion_matrix.pngresults.png里包含train/box_loss、val/box_loss、val/mAP0.5等子图。判断收敛的标准是训练 loss 和验证 loss 都趋于平稳验证 mAP 不再明显上升。如果训练 loss 持续下降但验证 loss 回升说明过拟合可以提前停止或加数据增强。confusion_matrix.png的横轴是真实类别纵轴是预测类别对角线上的值越高越好。如果某一行除了对角线外还有不少响应说明两个类别容易被混淆——比如 redtomato 和 plum 都是圆形红色物体容易互相误判。可以在训练时给这两个类专门做色彩增强或者检查是不是标注时框选得太紧导致特征缺失。6.3 从验证指标反推数据扩充策略当你确认模型能稳定跑通再回到数据本身。这份数据集只有几百张对四个类别来说上限不高。一个有效技巧是通过 YOLOv5 自带的增强参数在训练时扩大数据多样性比如--hsv-h 0.015色相增强、--fliplr 0.5水平翻转、--mosaic 1.0马赛克增强。如果靠这些还不够再考虑采集更多数据尤其是光照变化和遮挡场景。从那以后我每个新数据集完整跑下来都会做一轮“指标→误检图→数据修正”的循环先看 mAP再找误检图最后回过去修标注或补数据而不是一味加训练轮数。这一轮下来模型提升往往比调三个月参更明显。希望这份数据集的梳理能帮你少踩点坑把时间花在真正重要的地方。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
云原生数据仓库选型避坑指南:从底层引擎到真实压测 1. 为什么“云原生数据仓库选型”正在变成一场系统性误判?我去年帮一家做跨境SaaS的客户做数仓重构,他们原本用的是自建ClickHouse集群,跑着20多个核心BI看板和实时风控模型。老板拍板要“上云原生”,CTO直接拉出四份PPTÿ… · 2026/9/24 18:51:39
WPF布局控件全解析:从Grid到Canvas的实战指南 1. 为什么WPF布局控件值得单独写一篇做WPF开发的人,不管你是刚入门还是写了几年,一定绕不开一个最基础也是最核心的话题——布局控件。我见过太多新手上来就拖一个Canvas,把所有控件用绝对坐标钉死在界面上,结果窗口一拉伸&#x… · 2026/9/24 18:51:33
学生编程助手实战指南:免费工具与高效上手路径 1. 先搞清楚学生的真实需求:编程助手到底帮你省什么时间先说个我观察到的现象。这几年带过不少实习生和刚入门的朋友,发现大家拿到编程助手后的第一反应高度一致——装好插件,打开编辑器,然后开始疯狂地敲Tab键。代码是出来得很快… · 2026/9/24 18:51:33
面向对象编程进阶:多态、抽象类与接口的实战选择 “面向对象编程(05)”这个标题看着简单,但放在整个系列里,它就是一座分水岭。前几讲把类与对象、属性方法、封装继承都过了一遍,到了这一讲,主题开始从“怎么写一个类”转向“怎么组织一堆类”。很多人在这… · 2026/9/24 19:35:30
性价比高的桌面小五轴系统生产厂家 近年随着职校数控实训普及、精密五金小批量打样需求攀升,桌面级小五轴系统成为工业自动化领域的细分热点。数据表明,2023年国内桌面小五轴市场规模同比增长47%,其中82%的采购方为中小加工厂、职业院校、创客团队,这类用户的核心诉… · 2026/9/24 19:35:30
PS去AI水印实战指南:内容识别与仿制图章的核心技巧 做设计这行的人,几乎每天都要跟"水印"打交道。最近这一年,AI出图工具越来越普及,我身边不少朋友的工作流都变成了"先生成、再精修"。可AI工具出图时,常常会在角落压一个小logo,在画面中间铺一层版… · 2026/9/24 19:35:30
Flet DragTargetLeaveEvent 详解:拖放目标离开事件的载荷结构与实战用法 前端跨平台桌面应用移动开发 【免费下载链接】flet Build realtime web, mobile and desktop apps in Python only. No frontend experience required. 项目地址: https://gitcode.com/gh_mirrors/fl/flet 点击查看 免费下载 flet.DragTargetLeaveEvent 是 Flet 拖… · 2026/9/24 19:35:30
模式与模式匹配:现代语言如何用数据形状替代if-else 教材里那一章往往被放在书的后半部分,甚至有人直接跳过——“模式与模式匹配”,听起来像是给编译器作者准备的内容。但这两年你会发现,C# 9 的 switch 表达式、Java 21 的 switch 模式匹配、Python 3.10 的 match-case,全都在往这… · 2026/9/24 19:35:24
模式匹配详解:Rust match语法、解构与多语言对比 “模式匹配”这四个字,我第一次看到的时候,以为是某种高大上的设计模式或者架构方案。后来在写 Rust 和 Kotlin 的过程中,才意识到这是一套完全不同的思维工具。它不只是语法糖,更是一种对数据结构的“拆解能力”——让你能用一种… · 2026/9/24 19:35:24
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44