ARTICLE DETAIL

资讯详情

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

草莓成熟度检测实战:YOLOv8训练自定义数据集全流程

草莓成熟度检测实战:YOLOv8训练自定义数据集全流程 简介这份YOLO格式的草莓成熟度检测数据集面向目标检测学习者、农业AI开发者与智慧农业项目实践者主要用于解决草莓成熟与未成熟状态的自动识别与计数问题。数据已按YOLOv5标准目录整理包含训练集400张、验证集100张、测试集50张左右图片每张图片均附带对应的txt标签文件标注采用yolo相对坐标类别、中心点x、中心点y、宽、高共有成熟、未成熟等2个类别另附class类别文本与Python数据处理脚本可直接接入常见YOLO训练流程。资源包共1063个文件以jpg图片和txt标签为主体附带少量脚本与说明图压缩包大小约22.96MB下载后解压即可使用。目前已有259人学习下载适合想要快速获取规范数据集、开展草莓成熟度检测模型训练或进行农业目标检测入门实践的读者。1. 草莓成熟度检测数据集一张图里同时出现红果、青果和花做农业视觉检测的人最头疼的往往不是模型而是数据。草莓成熟度检测就是一个典型场景一棵植株上同时挂着成熟的红果、未熟的青果、白花和绿叶类间差异小、类内差异大背景还特别杂。这份 YOLO 数据集把问题简化到了能直接开训的程度——训练集 400 张左右、验证集 100 张左右、测试集 50 张左右标签是 YOLO 格式的相对坐标 txt类别按成熟、未成熟划分目录结构按 YOLOv5 约定排好解压就能喂给训练脚本。适合三类人想跑通 YOLO 全流程但没数据的学生、给农业巡检项目做初步验证的工程师、以及需要一份干净数据测试自己数据增强 pipeline 的算法岗。这份资源的价值不在于图片数量而在于省掉了人工标注和格式转换这两段最耗时的脏活。2. 数据集结构先行train/valid/test 划分与 YOLO 相对坐标标签2.1 目录结构YOLOv5 风格文件夹约定拿到压缩包后第一件事不是急着写训练代码而是先看清楚目录长什么样。这份数据集的叶子目录是按照 YOLOv5 的工程习惯组织的图片和标签分属 images 和 labels 两个根目录下面各自再挂 train、valid、test 三个子集。用 tree 命令看一眼就能确认dataset/ ├── images/ │ ├── train/ # 约 400 张 jpg │ ├── valid/ # 约 100 张 jpg │ └── test/ # 约 50 张 jpg ├── labels/ │ ├── train/ # 与 images/train 一一对应的 txt │ ├── valid/ │ └── test/ ├── class.txt # 类别文本文件 └── data.yaml # 部分版本会附带没有就自己写这里有个容易忽略的细节labels 目录下每个 txt 的文件名必须和 images 目录下对应 jpg 的文件名完全一致包括中间那串哈希值一样的编号不能有扩展名差异。数据集里文件名带有.rf.标记这是从 Roboflow 导出时留下的命名特征不影响使用但要留意如果自己追加图片命名规则得延续同一种风格否则 YOLO 在训练时会出现图片找不到标签的警告。这个结构本身没什么高深的东西但它决定了你后续所有操作的路径假设。我习惯先把整棵目录树列出来确认 train 和 valid 的图片数量级跟描述一致再进下一步。任何「训练时突然报错找不到文件」的问题九成出在这个环节。2.2 标签格式拆解中心点坐标和归一化宽高打开任意一个 txt 标签文件里面每一行对应一个目标框格式是五个数字0 0.4825 0.7133 0.1248 0.0862 1 0.3152 0.4297 0.1013 0.0795从左到右依次是类别编号、框中心点的 x 坐标、框中心点的 y 坐标、框宽度、框高度。注意这里全部是相对坐标也就是已经除以了图片的宽和高取值范围在 0 到 1 之间。这样做的好处是图片分辨率怎么变标签都不用跟着改YOLO 在训练时会把输入统一缩放到你设定的 imgsz标签依然有效。如果要把相对坐标换算回像素坐标公式很简单# 假设图片宽 w640, 高 h640 # 标签行为: cls, cx, cy, bw, bh cx_pixel 0.4825 * 640 # 308.8 cy_pixel 0.7133 * 640 # 456.5 box_w_pixel 0.1248 * 640 # 79.9 box_h_pixel 0.0862 * 640 # 55.2 # 左上角坐标 (cx_pixel - box_w_pixel/2, cy_pixel - box_h_pixel/2)做这个换算不是为了写代码而是为了核对标签是否可靠。数据集的标注质量是黑匣子你不可能逐张检查几百个框但可以抽样几十个框画在原图上看看。最常见的标注事故是类别编号串位和框整体偏移抽样检查能提前发现这些问题省得训练完才翻车。2.3 class.txt 和类别编号顺序就是一切class.txt 文件里一般就是两行文本比如ripe unripe在这里行号决定了类别编号第一行是 0第二行是 1。也就是说训练脚本里 data.yaml 的 names 列表顺序必须和这个文件保持一致。如果你写 names 时把 unripe 放在前面训练也能正常跑指标也好看但推理出来的结果成熟和未成熟会整个颠倒这才是最阴间的错误——模型没坏是标签语义反了。判断类别名到底怎么写以压缩包里的 class.txt 为准不要猜。因为不同导出者对命名可能有细微差别比如ripe、unripe或者strawberry_ripe、strawberry_unripe这都不影响训练影响的是你后续做结果可视化时的可读性。2.4 样本形态小目标多、背景杂、类间差距不大这份数据集的图片大多是从草莓种植场景里拍摄的包含中叶、花、成熟果和未熟果同时出现的画面。成熟果是红色未熟果偏绿但背景里的叶子也是绿色所以对检测器来说未熟果和叶子的边缘区分并不轻松。再加上有的草莓在画面里占比小、离镜头远小目标漏检的概率不低。从训练角度看400 张训练图不算多但对二分类检测来说足够启动训练流程。我的建议是把测试集看熟它在训练时不会参与是用来做最终评估的别为了多喂几张图而把它并到训练集里。数据量少的项目测试集是唯一诚实的裁判。如果追求更好的泛化后续可以自己补拍一些不同光照条件下的图片按同样的 YOLO 格式打好标签再放进 train 目录这个数据集作为底子是完全够用的。3. 训练前准备写 data.yaml 并跑通 YOLOv8 训练命令3.1 框架选型为什么推荐 YOLOv8 而不是 YOLOv5数据集目录是按 YOLOv5 的约定组织的但这不等于你必须用 YOLOv5 训练。YOLOv8 的 input-output 完全兼容这种目录结构而且训练命令更简洁、默认 aug 策略更省心。现在「yolov8 训练自己的数据集」已经是很成熟的流程网上的报错案例也齐遇到问题容易搜到答案。Ultralytics 框架把数据加载、增强、训练循环都封装成了现成接口你只需要提供一个 data.yaml 路径。先安装依赖pip install ultralytics装完后确认版本用yolo命令直接验证yolo predict modelyolov8n.pt sourceimages/train/0a.jpg能正常推理就说明环境没问题。选 yolov8n 而不是 s/m/l我的习惯是400 张这个量级的数据集n 模型的参数容量已经足够拟合而且训练速度快、显存占用小先跑通全流程再考虑换大模型。等训练完如果 mAP 确实不达预期再升级到 s 也不迟。3.2 编写 data.yaml路径和 names 顺序是命门在数据集根目录下新建一个strawberry.yaml内容如下# 草莓成熟度检测数据集配置 path: /absolute/path/to/dataset # 改成你的实际路径 train: images/train val: images/valid test: images/test # 类别顺序必须与 class.txt 保持一致 names: 0: ripe 1: unripe这里最关键的是path字段使用绝对路径。很多人喜欢写相对路径然后切换工作目录结果训练器在内部拼接路径时找不到目录。相对路径在某些版本下表现不稳定我吃过亏后统一改用绝对路径省掉一堆排查时间。names的写法和 class.txt 的语义一一对应。一个保守做法是训练前写一小段脚本读 class.txt 并打印出来with open(class.txt, r) as f: lines [line.strip() for line in f.readlines()] print(lines) # 期望输出 [ripe, unripe]跑完这段再对照着填 yaml 里的 names。不要凭记忆不要猜。3.3 训练命令与参数折解写好后执行训练基础命令如下yolo train modelyolov8n.pt datastrawberry.yaml \ epochs100 imgsz640 batch16 \ patience20 optimizerauto \ projectstrawberry_run nameexp1逐参数说明modelyolov8n.pt加载预训练权重。对小型数据集来说用 COCO 预训练权重做迁移学习能显著加快收敛因为模型已经具备了通用的边缘、纹理、形状特征只需要适应到底层特征上做成熟/未成熟的语义区分。imgsz640输入分辨率。草莓在画面里偏小如果显存允许可以试 960能提升小目标召回率但训练时间也会相应变长。batch16批大小。16 在 8GB 显存级别的卡上通常没问题如果报 OOM降到 8不要为了面子硬撑。patience20早停轮数。如果 20 个 epoch 内指标没有提升训练自动终止防止过拟合并节省时间。optimizerauto让框架自动选择优化器YOLOv8 默认会权衡 AdamW 和 SGD对二分类数据集来说 auto 足够稳。训练启动后终端会实时打印 epoch、box_loss、cls_loss、dfl_loss、precision、recall、mAP50、mAP50-95 这些指标。loss 曲线里 box_loss 持续下降但 cls_loss 震荡不收敛通常意味着类别间特征区分不够回到数据层面看样本而不是调参。训练结束时runs/detect/exp1/weights/下会生成best.pt和last.pt。best.pt是验证集上 mAP 最高的权重推理时优先用它last.pt是最后一个 epoch 的权重一般只用于断点续训。3.4 训练过程的可视化与结果检查Ultralytics 在训练目录下会输出results.csv里面记录了每个 epoch 的完整指标。不想用 wandb 或 tensorboard 的话直接读这个 CSV 就够了import pandas as pd df pd.read_csv(strawberry_run/exp1/results.csv) # 查看最后 5 个 epoch 的 mAP 和 loss cols [epoch, metrics/precision(B), metrics/recall(B), metrics/mAP50(B), train/box_loss] print(df[cols].tail())看这个表格时要注意两个边界一是 mAP50 和 mAP50-95 之间的距离二分类小目标数据集上 mAP50-95 偏低是正常现象不要被吓到二是 precision 和 recall 的此消彼长成熟果容易漏检的时候 recall 低叶子被误判成熟果的时候 precision 低。后面第 5 章会讲怎么用混淆矩阵把这些指标落到具体的错误类型上。4. 避坑排查标注顺序、小目标漏检与显存告警4.1 类别编号串位模型没坏标签语义反了现象训练完 mAP 很高画出来的预测框位置也准但成熟果被标成未成熟果未成熟果被标成成熟果整个语义颠倒。原因data.yaml 中 names 的顺序与 class.txt 不一致。训练过程只看编号不看文本含义。编号 0 是成熟、编号 1 是未成熟但 yaml 里写反了模型学到的语义自然就反了。解决训练前先用open(class.txt).readlines()打印原始类别列表再一个字一个字地对照填写 data.yaml。推理阶段如果发现类别标签反了不需要重新训练直接交换 names 列表中的两个名称即可。4.2 数据增强导致的标签翻转问题现象训练 loss 稳定下降但验证集 mAP 出现周期性波动有时某几个 epoch 掉得厉害之后又涨回来。原因YOLOv8 默认开启了随机翻转、HSV 扰动等增强。对目标检测来说水平和垂直翻转会同步翻转边界框坐标这本身没问题但如果你在训练配置里加了额外的旋转增强如degrees90而标签没做好相应几何变换框和内容就错位了。解决在这个数据集上保持默认增强不额外加旋转角度或者显式关闭翻转类增强再对比一次。我的习惯做法是先用默认配置跑一轮作为基准再调整增强参数两次对比 mAP 再判断要不要开加强。不用迷信增强越多越好小数据集上过度增强反而容易让模型学到错误的框形分布。4.3 显存不足导致训练中断现象训练刚启动不到一分钟终端直接报CUDA out of memory进程被杀。原因batch16加imgsz640在某些 4GB~6GB 显存的卡上确实会溢出尤其是同时开着 tensorboard 或者别的占用显存的服务时。解决两个方向。一是缩小资源需求把 batch 降到 8或把 imgsz 降到 480二是开启混合精度训练YOLOv8 默认ampTrue如果之前手动关掉了请打开yolo train modelyolov8n.pt datastrawberry.yaml \ epochs100 imgsz640 batch8 ampTrueamp 是半精度浮点训练显存占用能砍掉近一半loss 精度损失在一个可接受的范围。如果 4GB 显存仍然撑不住就调整到imgsz480跑通流程再说模型结构不用改。4.4 验证集路径不可用导致评估失败现象训练完成执行yolo val时直接报错FileNotFoundError说找到不图片。原因data.yaml 里的 path 字段是相对路径训练和验证时的工作目录不一致导致图片路径拼接错误。或是 Windows 编辑器自动填入了反斜杠路径Linux 环境解析出错。解决统一改成绝对路径并且路径里不要带中文字符和空格。手动校验一下路径是否真实存在ls -ld /your/dataset/images/valid这是血泪经验。路径问题是最不具技术含量但最常见的问题每次换机器都要重新确认一遍。我现在的习惯是先把 yaml 里的三个子目录挨个ls一遍确认存在再启动训练。4.5 成熟度边界模糊带来的误检现象验证集上 mAP 不错但实际跑照片时距离稍远的草莓检测不到或者把暗红色的叶子边缘检测成未成熟果。原因草莓成熟度本身是一个连续过程青果转红中间有过渡色标注人员对「成熟」和「未成熟」的判定边界必然存在主观差异。数据集中处于中间状态的样本可能被不同标注者分成不同类别这会让模型在决策边界附近混乱。解决当模型在边界的表现不稳时可以在推理阶段提高置信度阈值默认 0.25 改成 0.4让模型只输出高置信度的框宁可漏检不要误检。如果项目要求高召回率则反过来把阈值调低到 0.1保证成熟果不落到地里。阈值具体取多少要看业务是更怕漏采还是更怕误采这个玄学参数每换一个场景都得重新试。5. 验证与进阶混淆矩阵读法与置信度阈值调优5.1 val 模式评估正式核对测试集保留测试集就是为了这一刻。训练完的模型先在 valid 上快速评估确认没有明显问题后再用 test 做最终检验yolo val modelstrawberry_run/exp1/weights/best.pt \ datastrawberry.yaml splittest输出会包含每类别的 precision、recall、mAP50、mAP50-95。二分类成熟度检测任务上mAP50 在 0.7 以上就算流程通顺mAP50-95 如果在 0.4 以下不必灰心小目标占多数时这个指标天然吃亏。val 模式会顺便生成混淆矩阵图存在runs/detect/val/目录下那是接下来分析的主材料。5.2 混淆矩阵总和为什么不是 1很多人第一次看混淆矩阵会犯懵行和列加起来不是 1对角线也不是每行唯一的峰值。这背后有个常见误解——YOLO 的混淆矩阵包含 background 这一类未标注的目标框在计算时会把错误命中的目标算入背景类导致计数偏移。所以出现过你搜到「yolo 混淆矩阵总合不唯一」这种疑问本质是背景类的存在让矩阵看起来「缺数字」。正确读法是看相对比值而不是绝对数量成熟果有多少被误判成未熟果未熟果有多少落回背景如果成熟→未成熟的误判偏高大概率是标注边界不一致如果未熟→背景的误判偏高多半是绿色果实与叶片特征太接近这时候要么补数据要么调低 conf 阈值。矩阵本身不是给人背下来的是用来定位错误集中在哪条边上的。5.3 置信度阈值与 NMS 的配合调优推理阶段最常调的参数是两个conf和iou。conf控制一个框要被输出时须达到的最低类别概率iou控制非极大值抑制时两个框重叠到什么程度算一个框。对这个草莓数据集我一般这样起调yolo predict modelstrawberry_run/exp1/weights/best.pt \ source/path/to/new/images \ conf0.3 iou0.5如果场景是收果机器人要求尽可能把每个成熟果都框出来conf 降到 0.15同时 iou 保持 0.5 或降到 0.4避免紧密相邻的多个草莓被合并成一个框。如果场景是质量抽检宁缺毋滥conf 上调到 0.5误报会明显减少。没有一组参数是银弹换一个光照环境就得重新扫几组值对比。从那以后我每拿到一个检测类数据集都会强制自己先走一遍完整流程——先看 class.txt 确认类别顺序再抽查标签换算坐标然后跑默认参数训练一轮最后用混淆矩阵和 conf 扫描收尾。这套流程看起来耗时却能把「标注错位」「类别语义反了」「小目标漏检」这类问题在两天内全部暴露出来而不是在交付给现场后才发现。这份草莓数据集值得你花一个下午把它完整跑一遍把每一步的产物都留下希望帮到你。本文还有配套的精品资源点击获取
返回列表