简介本资源为面向YOLO系列目标检测算法的葡萄数据集适用于从事农业视觉检测、果实分拣与品质分级的研究者及学生可解决葡萄成熟度识别与腐烂斑点检测等任务。包内共496个文件含165张jpg图像、165个txt标签、165个xml标签及1个data.yaml配置文件压缩包约13.85MB已按训练验证需求划分完毕可直接用于yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等模型训练与测试。标签覆盖拣选点、斑点葡萄、腐烂葡萄、成熟葡萄与未成熟葡萄等类别同时提供YOLO格式与VOC格式两套标注YOLO格式采用归一化中心点与宽高比例便于直接读取。目前已有101人学习下载读者可快速获得完整数据配置、双格式标签与划分方案省去采集标注成本用于算法对比、模型微调与农业分拣场景验证。1. 葡萄拣选点检测165 张图像的数据集到底能不能撑起一个 YOLO 模型拿到一个只有 165 张图像、带标签、分了「拣选点 / 斑点葡萄 / 腐烂葡萄 / 成熟葡萄 / 未成熟葡萄」几类的葡萄数据集很多人的第一反应是这点数据也配训 YOLO我一开始也这么想但实际跑过几轮之后发现这类小样本、强场景、类别语义高度重叠的数据集恰恰是检验你对 YOLO 训练流程理解深度的试金石。它解决的不是「通用葡萄检测」这种大而全的问题而是采摘机器人或分拣产线上一个非常具体的诉求在一串葡萄里找到该下剪的拣选点同时把斑点、腐烂、成熟度这些状态区分开。适合谁适合手上有类似小数据集、想跑通 yolov8 训练自己数据集全流程、又不想被「数据量不够」劝退的从业者。165 张不是不能做而是你必须把每一张的标注质量、类别定义、增强策略都抠到极致否则模型学到的全是噪声。下面我按自己踩过的顺序把这个数据集从拆包到出检测结果的路径讲清楚。2. 拆开这个 zip类别定义、标注格式与 165 张的分布陷阱2.1 先搞清楚五个类别到底在标什么这个数据集的类别名给得很直白拣选点、斑点葡萄、腐烂葡萄、成熟葡萄、未成熟葡萄。但直白不等于清晰。我拿到手第一件事不是写训练脚本而是把标注可视化出来逐类看框画在哪。常见的坑是拣选点可能被标成一个极小的点状框而成熟/未成熟葡萄是整颗果粒的框斑点葡萄可能只框了斑点区域而不是整颗葡萄。如果你不先统一「框的语义边界」后面模型会学得精神分裂——同一个位置一会儿预测拣选点一会儿预测成熟葡萄。我的做法是写一个可视化脚本把每张图的标注框和类别画出来人工过一遍。下面这段代码用 OpenCV 把 YOLO 格式的标签还原到图上方便你快速判断标注质量。import cv2 import os import random # 类别名按数据集实际顺序填写顺序错了后面全错 class_names [pick_point, spot_grape, rotten_grape, ripe_grape, unripe_grape] colors [(0,0,255), (0,165,255), (0,255,255), (0,255,0), (255,0,0)] img_dir images/train lbl_dir labels/train # 随机抽 12 张看标注别只看前几张前几张往往标得最认真 samples random.sample(os.listdir(img_dir), 12) for name in samples: img cv2.imread(os.path.join(img_dir, name)) h, w img.shape[:2] lbl_path os.path.join(lbl_dir, name.rsplit(., 1)[0] .txt) if not os.path.exists(lbl_path): print(缺标签:, name) continue with open(lbl_path) as f: for line in f: cid, cx, cy, bw, bh map(float, line.split()) # YOLO 是归一化中心点坐标还原成像素左上右下 x1 int((cx - bw/2) * w) y1 int((cy - bh/2) * h) x2 int((cx bw/2) * w) y2 int((cy bh/2) * h) cv2.rectangle(img, (x1,y1), (x2,y2), colors[int(cid)], 2) cv2.putText(img, class_names[int(cid)], (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[int(cid)], 1) cv2.imwrite(fvis_{name}, img)逻辑说明YOLO 标签每行是类别 id 中心x 中心y 宽 高全部归一化到 0~1。还原时先乘回图像宽高再算左上右下角。参数上唯一要改的是class_names的顺序必须和data.yaml里的names完全一致否则你看到的类别名全是错的。跑完这一步你会对「拣选点」这类小目标占比有个直观感受——如果它只占几个像素后面 anchor 和输入尺寸都得跟着调。2.2 165 张的分布陷阱别让某一类只有个位数165 张图五类平均下来每类 33 个实例但实际分布往往极度倾斜。我见过类似数据集里「腐烂葡萄」只有 8 个框「拣选点」却有 200 多个。这种分布直接训模型会对多数类过拟合少数类几乎不召回。先统计再决定要不要做重采样或针对性增强。# 统计每个类别的实例数快速看分布 for f in labels/train/*.txt; do cat $f; done | awk {print $1} | sort | uniq -c这条命令把 train 下所有标签的类别 id 抽出来计数。输出里如果某个 id 的数量低于 30你就要警惕了。常见做法是对少数类做复制粘贴增强copy-paste或者用 mosaic 时提高含少数类图像的采样权重。我一般会先跑一遍基线看混淆矩阵里哪一类被完全忽略再针对性补而不是一上来就猛增强——增强过头会把小目标糊掉反而更差。提示统计完分布再划分 train/val别先划分再统计。小数据集里如果 val 恰好抽走了少数类的全部实例验证指标会难看得让你怀疑人生。3. 用 yolov8 训练自己的数据集从 data.yaml 到第一次推理3.1 data.yaml 怎么写才不出错yolov8 训练自己的数据集入口就是一份data.yaml。这个文件写错一个路径训练能启动但学的是空标签损失不降你还以为是模型问题。下面是我在这个葡萄数据集上用的配置。# data.yaml path: /home/user/grape_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图目录 val: images/val test: images/test # 没有 test 就删掉这行 nc: 5 # 类别数必须和 names 长度一致 names: 0: pick_point 1: spot_grape 2: rotten_grape 3: ripe_grape 4: unripe_grape参数说明path用绝对路径避免从不同工作目录启动时找不到train/val是相对path的路径指向存放图像的文件夹yolov8 会自动去同级或按约定找labels目录。nc和names的索引必须从 0 连续中间断号会导致类别错位。我踩过的坑是names 里写了中文训练不报错但推理时显示乱码建议先用英文出图后再映射回中文。3.2 第一次训练的命令与关键参数数据配置好之后一条命令就能起训。但小数据集不能照搬大数据的默认参数下面是我在 165 张规模下的起手配置。yolo detect train \ datadata.yaml \ modelyolov8n.pt \ # 小数据集先用 nano别一上来上大模型 epochs300 \ # 小数据收敛慢轮次给足 imgsz640 \ # 输入尺寸小目标多可提到 960 batch8 \ # 显存不够就降到 4 lr00.001 \ # 初始学习率小数据别用默认 0.01 patience50 \ # 50 轮不涨就早停省时间 mosaic1.0 \ # 马赛克增强小数据几乎必开 degrees15.0 \ # 葡萄串有旋转加一点角度增强 fliplr0.5 \ # 左右翻转葡萄左右对称合理 projectruns/grape \ nameexp1逻辑说明yolov8n.pt是预训练权重小数据集靠它迁移学习从零训基本没戏。epochs300配合patience50让它在验证指标停滞时自动停避免过拟合。lr0从默认的 0.01 降到 0.001是因为 165 张图梯度噪声大学习率太高会震荡。mosaic和degrees是针对葡萄串形态的增强但注意degrees别开太大超过 30 度葡萄串的上下文就失真了。3.3 训练过程看什么损失、mAP 与混淆矩阵训练启动后终端会打印每轮的 box_loss、cls_loss 和 mAP50。小数据集上box_loss 下降但 mAP 不涨通常是标注框质量问题cls_loss 居高不下多半是类别语义重叠成熟 vs 未成熟边界模糊。我一般会在训练结束后看混淆矩阵重点看「成熟葡萄」和「未成熟葡萄」有没有互相误判——这两类在颜色过渡期本来就难分如果误判严重说明标注时边界没定清楚得回去重新审标签而不是调模型。# 训练完在验证集上跑一次输出混淆矩阵和 PR 曲线 yolo detect val \ modelruns/grape/exp1/weights/best.pt \ datadata.yaml \ imgsz640 \ plotsTrueplotsTrue会在输出目录生成混淆矩阵、PR 曲线等图。看混淆矩阵时对角线越深越好非对角线上的大块就是你要处理的类别混淆。这一步不是走形式小数据集里它比 mAP 更能告诉你问题出在哪。4. 小样本葡萄检测的避坑清单标注、增强与评估的五个翻车点4.1 拣选点被当成噪声滤掉现象训练后模型对成熟、腐烂葡萄检测正常但拣选点几乎不召回置信度普遍低于 0.1。原因拣选点通常是小目标在 640 输入下经过多次下采样后特征几乎消失加上小数据集里它的样本本就少。解决把imgsz提到 960 或 1280或者在数据里对拣选点区域做局部裁剪放大后作为额外样本加入。我一般先提输入尺寸成本最低效果立竿见影。4.2 增强把腐烂区域糊没了现象开了 mosaic 和 mixup 之后验证集上腐烂葡萄的召回反而下降。原因腐烂区域往往是局部纹理mosaic 拼接和 mixup 混合会破坏这种局部特征模型学到的是拼接边界而不是腐烂本身。解决对腐烂这类依赖局部纹理的类别降低 mosaic 概率或关闭 mixup改用 HSV 色彩抖动来模拟不同光照下的腐烂表现。4.3 验证集指标虚高现象val 的 mAP 到 0.9但拿新图一测惨不忍睹。原因165 张图划分验证集时如果同一串葡萄的不同角度图被分到 train 和 val模型其实见过「同一串」指标虚高。解决按葡萄串或拍摄批次划分而不是随机按图划分。同一串葡萄的图必须整体进 train 或整体进 val这一步不做后面所有指标都不可信。4.4 类别顺序在训练和推理时不一致现象推理结果里「成熟葡萄」的框标成了「未成熟」。原因训练用的data.yaml里 names 顺序和推理时后处理映射的顺序不一致。解决把 names 单独存一份 json训练和推理都从同一份读杜绝手写两遍。这个坑很隐蔽因为模型本身没错错的是你解读输出的方式。4.5 早停太早模型没学完现象训练到 60 轮就停了mAP 还在缓慢上升。原因patience设太小小数据集指标波动大连续几轮不涨不代表到顶了。解决把patience提到 80~100或者干脆关掉早停看完整 300 轮的曲线再决定。我一般会保留每 10 轮的权重训完再挑最好的而不是只信 best.pt。注意这五条里4.3 的划分问题和 4.4 的类别顺序问题最容易被忽略因为它们不报错只是悄悄让你的结果失真。每次开新数据集我都会先把这两条过一遍。5. 把 165 张用到极致小样本下的进阶技巧与验证习惯小数据集的天花板不在模型而在你对数据的挖掘深度。165 张图如果只是原样喂进去能到 0.6 的 mAP 就算不错但如果把增强、迁移、伪标签这几件事做扎实冲到 0.8 以上是有可能的。我自己的习惯是分三步走先用预训练权重跑基线拿到混淆矩阵再针对最弱的类别做定向增强或补标最后用模型对未标注图如果有打伪标签人工修正后加入训练。伪标签这一步在小数据上收益很大但前提是基线模型已经有一定精度否则伪标签全是错的越训越偏。验证习惯上我坚持留一个「从未参与训练和调参」的测试集哪怕只有 20 张。这个测试集只在最后用一次用来判断模型到底能不能上产线。很多人把 val 当测试集反复调参调到最后模型对 val 过拟合真实场景一塌糊涂。另外推理时我会把置信度阈值和 NMS 的 IoU 阈值都做成可调的因为葡萄串里果粒密集NMS 阈值设高了会吞掉相邻果粒的框设低了又会出现重复框。我一般从conf0.25, iou0.45起调根据实际出图微调。from ultralytics import YOLO model YOLO(runs/grape/exp1/weights/best.pt) # 推理时把 conf 和 iou 暴露出来方便按场景调 results model.predict( sourcetest_images/, conf0.25, # 置信度阈值漏检多就降误检多就升 iou0.45, # NMS 的 IoU 阈值果粒密集时适当降低 imgsz960, # 和训练时保持一致或更高 saveTrue, projectruns/grape, nameinfer )这段推理脚本的关键在conf和iou两个参数。conf控制哪些框保留iou控制重叠框怎么合并。葡萄这种密集小目标场景我通常会把iou降到 0.4 左右避免相邻果粒被误合并。imgsz建议不低于训练时的尺寸否则小目标召回会掉。跑完出图后别只看模型画出来的框要拿原图对照看漏了哪些、多了哪些这些才是你下一轮迭代的依据。说到底165 张葡萄图像能不能撑起一个可用的 YOLO 模型答案不在数据量而在你有没有把标注语义、类别分布、增强策略、验证划分这四件事做对。我做过好几个类似规模的小数据集凡是最后能落地的无一例外都是在这四件事上抠得比别人细。希望帮到你。本文还有配套的精品资源点击获取