基于YOLOv8的损坏苹果检测:数据集标注与训练部署全流程
简介这是一份面向农业质检、食品质量控制与计算机视觉方向的YOLO目标检测数据集聚焦于识别并定位图像中受损的苹果适合希望快速上手目标检测任务的研究者与开发者。资源包共724个文件以361张jpg图像、362个txt标注文件和1个yaml配置文件为主图像用于模型训练与验证txt提供对应边界框与类别信息yaml则定义数据集路径与类别结构压缩包整体约3.56MB体量轻便便于快速加载。数据集划分为253张训练样本、103张验证样本和5张测试样本标注精确可直接用于YOLOv8迁移学习或从头训练帮助读者实践小目标检测、超参数调优与mAP、召回率等指标评估。目前已有609人学习下载适合作为农产品质量检测场景下的入门与实验素材。1. 损坏的苹果检测数据集从标注到 YOLOv8 训练的一条龙落地苹果分选线上最头疼的不是好果坏果混在一起而是碰伤、腐烂、虫蛀这类隐性损伤——表面看着还行装箱后几天就烂一片。人工挑拣速度慢、标准还不统一所以很多做果蔬分选的团队会直接上目标检测模型。这份YOLO损坏的苹果检测数据集就是冲着这个场景来的它把损坏苹果按类别框好直接能喂给 YOLOv8 这类检测器训练。适合谁做农产品质检、分选设备、视觉分拣的工程师以及想拿一个真实缺陷检测任务练手 YOLO 训练全流程的人。它解决的核心问题就一个——省掉你自己拍图、标注、划分数据集的那几天苦力活让你把精力放在模型和部署上。2. 数据集结构与 YOLO 标注格式先看懂再动手拿到一个目标检测数据集第一件事不是急着训练而是搞清楚它的目录长什么样、标注是什么格式。格式不对后面训练报的错能让你怀疑人生。这一章把数据集的典型结构和 YOLO 标注规范拆开讲让你在动手前心里有底。2.1 目录结构与文件组织目标检测数据集常见的组织方式有两种一种是 COCO 风格的单个 JSON 标注文件一种是 YOLO 风格的每张图配一个 txt。这份数据集走的是 YOLO 路线典型结构如下apple_defect_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ │ ├── 0001.jpg │ │ └── ... │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片可选 ├── labels/ │ ├── train/ # 训练集标注与图片同名 │ │ ├── 0001.txt │ │ └── ... │ ├── val/ │ └── test/ └── data.yaml # 数据集配置文件关键点在于images和labels是镜像对应的images/train/0001.jpg对应的标注必须是labels/train/0001.txt文件名不含扩展名必须完全一致。这是 YOLO 训练时找标注的硬规则差一个字符就找不到训练时那张图会被当成无标注背景图处理白白浪费。常见做法是训练前先跑一遍校验脚本确认每张图都有对应标注、没有空文件、没有越界坐标。我一般会写个小脚本扫一遍比训练到一半才发现问题强得多。2.2 YOLO 标注格式详解YOLO 的标注是归一化坐标每行一个目标格式是class_id x_center y_center width height五个值用空格分隔后四个都是相对图片宽高的归一化值范围 0~1。举个例子一张 640×480 的图里有个框左上角 (100, 80)右下角 (300, 260)0 0.3125 0.3542 0.3125 0.3750算一下中心 x (100300)/2/640 0.3125中心 y (80260)/2/480 0.3542宽 (300-100)/640 0.3125高 (260-80)/480 0.3750。这就是归一化的意义——不管图片原始分辨率多少标注都能通用。损坏苹果这类数据集类别通常按损伤类型分比如碰伤、腐烂、虫蛀、完好果。具体类别数以data.yaml里的names为准训练前务必打开看一眼别想当然。2.3 data.yaml 配置怎么写data.yaml是 YOLOv8 训练的入口配置结构固定path: ./apple_defect_dataset # 数据集根目录 train: images/train # 训练集路径相对 path val: images/val # 验证集路径 test: images/test # 测试集路径可选 nc: 4 # 类别数量 names: # 类别名称顺序即 class_id 0: bruise 1: rot 2: wormhole 3: intactnc必须和names的条目数一致names的顺序就是标注里class_id的含义。这里最容易翻车的是路径path是根train/val是相对根的路径。如果你把 yaml 放在别处路径写错训练直接报Dataset not found。我一般用绝对路径省心或者确认相对路径是相对 yaml 文件所在目录还是当前工作目录——YOLOv8 里是相对 yaml 所在目录这点要记牢。3. 用 YOLOv8 训练损坏苹果检测模型环境、命令与参数看懂数据之后就进入真正的训练环节。这一章从环境配置讲到训练命令再到参数怎么调尽量让你照着敲就能跑起来。YOLOv8 是目前工程落地最顺手的一代API 干净、文档全拿它做缺陷检测是稳妥选择。3.1 环境配置与依赖安装先建个干净的虚拟环境别在系统 Python 里乱装。常见做法是用 conda 或 venvconda create -n apple_yolo python3.10 -y conda activate apple_yolo # 安装 PyTorch按你的 CUDA 版本选这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics pip install ultralytics装完验证一下yolo checks这条命令会打印环境信息包括 PyTorch 版本、CUDA 是否可用、ultralytics 版本。如果 CUDA 显示不可用训练会退回 CPU速度慢到你想砸键盘。显卡驱动和 CUDA 版本对不上是新手最常见的坑装之前先nvidia-smi看一眼驱动支持的 CUDA 上限。3.2 训练命令与关键参数YOLOv8 训练有两种方式命令行和 Python 脚本。命令行适合快速试脚本适合固化流程。yolo detect train \ data./apple_defect_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/apple \ nameexp1逐项说下参数含义data指向 data.yaml路径别写错。model预训练权重。yolov8n.pt是最小的 nano 版速度快、精度低数据量小或要精度就换yolov8s.pt或yolov8m.pt。用预训练权重比从零训练收敛快得多这是常识。epochs训练轮数。100 是常见起点小数据集容易过拟合可以配合早停。imgsz输入尺寸。640 是默认值损坏区域小的话可以提到 960 或 1280但显存占用和耗时都会涨。batch批大小。显存不够就往下调8、4 都行别硬撑导致 OOM。device0表示第一块 GPUcpu表示用 CPU。project/name输出目录权重、日志、曲线都存这里。Python 脚本方式等价from ultralytics import YOLO model YOLO(yolov8n.pt) results model.train( data./apple_defect_dataset/data.yaml, epochs100, imgsz640, batch16, device0, projectruns/apple, nameexp1, )脚本方式的好处是能加回调、能接自己的日志系统工程化时更灵活。3.3 训练过程监控与指标解读训练启动后控制台会实时打印每个 epoch 的损失和指标。重点看几个指标含义关注点box_loss边界框回归损失持续下降说明框在收敛cls_loss分类损失不降反升可能过拟合mAP50IoU0.5 时的平均精度主指标越高越好mAP50-95多 IoU 阈值平均更严格反映定位质量训练完在runs/apple/exp1/下会有results.png把损失和 mAP 曲线画在一起。我一般先看 mAP50 有没有到平台期再看 train 和 val 的损失是否背离——背离就是过拟合信号该加数据增强或减模型规模了。提示损坏苹果的损伤区域往往偏小如果 mAP 一直上不去先别急着换模型把imgsz提上去往往比换大模型更有效。4. 推理、验证与部署模型训完怎么用训练只是中间步骤模型最终要能对着一张新图或一路视频流给出框。这一章讲推理、验证和轻量部署把数据集的价值真正落到产线上。4.1 单图与批量推理训练完的权重在runs/apple/exp1/weights/best.pt用它推理from ultralytics import YOLO model YOLO(runs/apple/exp1/weights/best.pt) # 单图推理 results model(test_apple.jpg, conf0.25, iou0.45) results[0].save(output.jpg) # 保存带框结果 # 批量推理整个目录 results model.predict( source./test_images, conf0.25, saveTrue, projectruns/predict, namebatch1, )conf是置信度阈值低于它的框直接丢掉iou是 NMS 的 IoU 阈值控制重叠框合并。这两个参数对结果影响很大conf调高漏检增多调低误检增多iou调低会压掉密集目标。损坏苹果如果多个损伤挨得近iou别设太低否则相邻框会被误合并。4.2 验证集评估与混淆矩阵想量化模型好坏跑验证yolo detect val \ modelruns/apple/exp1/weights/best.pt \ data./apple_defect_dataset/data.yaml \ imgsz640输出里除了 mAP还会生成混淆矩阵confusion_matrix.png。这个图特别有用能看出哪类容易被误判成哪类。比如腐烂果经常被认成碰伤说明这两类视觉特征接近要么补数据要么在标注阶段把边界定清楚。热词里提到的yolo混淆矩阵总合不唯一其实就是归一化方式不同导致的看的时候注意是计数还是归一化版本别被数字绕进去。4.3 导出与轻量部署产线上往往要更快可以把模型导出成 ONNX 或 TensorRT# 导出 ONNX yolo export modelruns/apple/exp1/weights/best.pt formatonnx imgsz640 # 导出 TensorRT需要 GPU 环境 yolo export modelruns/apple/exp1/weights/best.pt formatengine imgsz640 halfTruehalfTrue表示 FP16 半精度速度更快、显存更省精度损失通常可接受。导出后可以用 ONNXRuntime 或 TensorRT 在 C 侧加载接上相机和分选机构就成了。注意导出时的imgsz要和训练一致否则精度会掉。5. 避坑与排查损坏苹果检测训练里最容易翻车的几件事数据集和代码都摆在那但真跑起来还是各种报错。这一章把我在缺陷检测任务里踩过的坑列出来每条按现象 → 原因 → 解决写能帮你省下不少调试时间。5.1 训练报 Dataset not found 或标注全为空现象训练能启动但 loss 一直是 0 或者 mAP 恒为 0日志里提示找不到标注。原因data.yaml里的路径写错或者images和labels文件名对不上。YOLO 找不到标注时会把图当纯背景模型学不到任何东西。解决先确认path是绝对路径或相对 yaml 的正确路径再写脚本核对每张图是否有同名 txt。下面这段能快速扫一遍import os from pathlib import Path img_dir Path(apple_defect_dataset/images/train) lbl_dir Path(apple_defect_dataset/labels/train) missing [] for img in img_dir.glob(*.jpg): lbl lbl_dir / (img.stem .txt) if not lbl.exists() or lbl.stat().st_size 0: missing.append(img.name) print(f缺失或空标注: {len(missing)}) print(missing[:10])5.2 显存不足 OOM现象训练刚开始就报CUDA out of memory。原因batch或imgsz太大超出显卡显存。解决先把batch减半还不行就降imgsz640→512→416。也可以用梯度累积模拟大 batch但 YOLOv8 里要手动配。别一上来就 batch64先小后大试。5.3 小目标漏检严重现象大块腐烂能检出小虫蛀、小碰伤基本漏掉。原因损伤区域在原图里占比太小下采样后特征几乎消失。解决提高imgsz是最直接的办法其次检查标注框有没有画得太松把背景也框进去会稀释特征数据增强里可以开mosaic和scale增加小目标出现频率。5.4 过拟合训练集 mAP 高验证集拉胯现象训练损失一路降验证 mAP 早早到顶然后回落。原因数据量小、模型相对太大或者增强太弱。解决换更小的模型n 或 s开强增强hsv_h、hsv_s、flipud、mosaic加dropout或者干脆补数据。损坏苹果数据集如果每类样本不均衡还要考虑过采样少数类。5.5 类别不均衡导致少数类几乎检不出现象完好果检出率很高虫蛀果几乎检不到。原因训练集里完好果远多于缺陷果模型偏向多数类。解决统计各类别框数量对少数类做复制增强或在 loss 里加权。YOLOv8 默认不带类别权重需要自己改或用fraction控制采样。先统计再动手from collections import Counter from pathlib import Path counter Counter() for txt in Path(apple_defect_dataset/labels/train).glob(*.txt): for line in txt.read_text().splitlines(): if line.strip(): counter[int(line.split()[0])] 1 print(counter)6. 进阶技巧把损坏苹果检测做到产线可用模型能跑通只是及格线要真上分选线还得在几个细节上抠。这一章讲我实际落地时最看重的几招都是能直接抄的。第一招是用切片推理救小目标。如果损伤区域实在太小与其把整图分辨率拉到 1280 吃显存不如用 SAHI 这类切片推理框架把大图切成带重叠的小块分别推理再合并结果。代价是推理变慢但小目标召回能明显提升。常见做法是切 640 的块、重叠 20%对虫蛀这类小缺陷效果立竿见影。第二招是按业务定阈值而不是看 mAP。产线上漏检一个腐烂果的代价远大于误报一个。所以conf要往低调宁可多框几个让后处理去筛。我一般会画一条 precision-recall 曲线按业务能接受的误报率反推conf而不是直接用默认 0.25。第三招是定期回流难例。上线后把模型判错、判漏的图存下来人工复核后加进训练集重训。缺陷检测的场景会随季节、品种、光照变化一次训练管不了一年。这个回流机制比任何调参都管用。验证模型是否真的可用我习惯做两件事一是拿一批完全没参与训练的现场图跑一遍看漏检集中在哪类二是把同一批图用不同imgsz和conf组合跑画个表格对比选综合最优的那组。配置imgszconf漏检率误报率A6400.2512%8%B9600.206%11%C9600.309%6%这种表比单看 mAP 有用得多因为它直接对应产线指标。选哪组取决于你的分选机构能容忍多少误报。最后说个血泪经验别在标注质量上省钱。我见过太多团队模型怎么调都上不去最后发现是标注框画得随意、类别边界模糊。损坏苹果的碰伤和腐烂在早期本来就难分标注规范必须先定死最好两个人交叉复核。从那以后我每次接缺陷检测项目都强制先抽 50 张图做标注一致性检查再谈训练。希望这份数据集和这套流程能帮你少走点弯路。本文还有配套的精品资源点击获取