苹果检测实战:YOLOv5与YOLOv8目标检测全流程解析

发布时间:2026/10/22 21:09:10
苹果检测实战:YOLOv5与YOLOv8目标检测全流程解析 做了几年目标检测相关的项目苹果检测算是农业视觉里很典型的一个需求。采摘机器人要识别果实位置果园巡检无人机要统计挂果量分选线要判断大小品相说到底第一步都是“先用模型把苹果一个个框出来”。这篇就把我在整理苹果数据集、跑通YOLOv5和YOLOv8模型过程中的完整经验写出来从数据准备到训练调参再到部署排查都按实操顺序来适合正在做农业视觉、或者想用目标检测做果实识别但还没形成完整流程的朋友参考。1. 苹果检测任务从需求到技术选型1.1 果园场景下的检测难点苹果检测看着是个单类别检测任务好像比通用目标检测简单但真把相机架到果园里就会发现难点全藏在“场景”二字里。第一个难点是遮挡。苹果长在树上叶子、枝条、相邻果实都会形成遮挡。很多时候一个苹果只露出来半边甚至三分之一模型既要能认出来还不能把被挡住的苹果漏掉。第二个是光照。晴天直射光下果实表面有高光逆光时果子和背景的亮度对比极低早晚低角度阳光还会在地面产生长阴影干扰。第三个是目标尺度差异大。同一张图里近处的大苹果可能占了几百个像素远处枝头的苹果只有二十几个像素多尺度检测能力必须跟得上。第四个是小果与背景的纹理接近尤其是青苹果、黄苹果和树叶的颜色分布有重叠单靠颜色或者简单的边缘特征根本分不开。所以这个任务本质上是“密集小目标 严重遮挡 光照变化 背景干扰”的组合考验。模型不能只做粗定位必须能够在复杂背景下稳定输出每个可见果实的精确边界框。1.2 为什么选择YOLO系列苹果检测对实时性有硬要求。采摘机器人要边移动边识别帧率至少要跑到15FPS以上才跟得上机械臂动作无人机巡检更不用说飞一圈采集几万张图离线都希望处理得快。在这种前提下两阶段检测器虽然精度上限高但速度劣势太明显不太适合现场部署。YOLO系列是当前检测精度和速度平衡得最好的开源方案之一。模型体积小、生态成熟、部署工具链完整从训练到导出ONNX再到TensorRT加速都有现成路径。而且YOLOv5和YOLOv8两个版本覆盖了不同的部署需求v5在低算力设备上更灵活v8在训练稳定性和特征提取能力上明显更好。我这次同时跑通两个版本目的也很简单——对比它们在同一个苹果数据集上的表现搞清楚什么场景该用哪个版本而不是盲目追新或者继续守着旧方案。2. 苹果数据集从采集到组织2.1 数据构成与采集要点模型能学到什么程度数据说了算。我整理苹果数据集时定了一条原则宁可数量少一点也要保证环境多样性。最终的数据集由三部分组成来自公开来源的果园实拍图片、某合作果园提供的不同光照时段拍摄照片、以及我自己用手机和运动相机补拍的部分近景。总量控制在2300张左右类别就一类“apple”。这个数量对单类别检测来说够用如果类别超过三四个单类样本量就要往上走。采集阶段有几个容易被忽略的点。一是分辨率训练图统一缩放到640×640但原图最好不低于720p否则远处的小苹果缩完之后只剩几个像素标注都没法标。二是角度覆盖除了水平视角还要拍仰视和俯视角度因为机械臂的相机视角经常是从下往上看的树冠视角的俯视图也要覆盖。三是天气和时段晴天、阴天、清晨、正午、傍晚的样本都要有不然模型一到阴天就掉点。采集完成后做了一次粗筛把明显模糊的、过度曝光的、完全看不清果实的图片删掉。这一轮能删掉10%到15%别心疼脏数据在训练时带来的负作用远比少几张图严重。2.2 标注规范与格式转换标注环节是纯体力活但边界规范决定了模型上限。我用标注工具逐个框出可见的苹果遵循几条规则被遮挡超过一半的苹果不标勉强标出来只会让模型学混乱。相邻但紧贴的两个苹果边界框必须分开且边界不重叠避免模型把两个框合并。边界框贴紧果实的可见轮廓不要留太大空白也不要切掉果实边缘。同一张图里的所有可见苹果都要标全漏标的负面影响大于标错。这里补充一个实际很常见的坑公开渠道下载的数据集格式经常不统一VOC的XML格式、COCO的JSON格式、YOLO的TXT格式都有。我自己做了个脚本统一转成YOLO格式。YOLO的TXT标注是归一化的中心点加宽高的形式每一行是class_id x_center y_center width height比如一个苹果的边界框在1080×720的图上左上角是(200, 150)右下角是(320, 300)那么归一化计算是x_center (200 320) / 2 / 1080 0.2407 y_center (150 300) / 2 / 720 0.3125 width (320 - 200) / 1080 0.1111 height (300 - 150) / 720 0.2083转换之后那行就是0 0.2407 0.3125 0.1111 0.2083每张图和它的TXT标注文件要保持同名放在images和labels两个对应目录下。目录组织我直接沿用YOLO标准结构datasets/ ├── apple/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/train和val按8:2划分划分的时候要按图片随机分配不能按拍摄批次分否则同一时段光照的图片全部进了验证集指标虚高没有参考意义。2.3 数据增强策略苹果数据集数量有限必须靠增强来扩展分布覆盖。YOLOv5和YOLOv8都内置了Mosaic增强一次把四张图拼成一张训练相当于每步训练能看到四张不同场景的上下文对小目标检测特别有帮助。我实际开启的增强项主要有随机旋转±15度以内超过这个角度苹果的形态就失真了、HSV色域扰动饱和度±20%亮度±30%用来模拟不同光照、随机水平翻转、随机缩放与平移。这几个组合下来相当于把一个300张左右的类别样本扩充出了几倍的有效训练信息量。有一点要特别提醒马赛克增强虽然是训练利器但验证阶段必须关闭。验证集要保证原始分布打开增强会让验证指标失真。所以验证时统一用原始图像尺寸或者缩放到640后再测不做任何增强。3. YOLOv5与YOLOv8两个版本的选型逻辑3.1 网络结构与核心差异只看推理效果的话两个版本差距没想象中大但结构设计思路确实迭代了一代。YOLOv5的核心特征可以总结为三点Focus模块做下采样、CSPDarknet作为骨干网络、Anchor-Based的检测头。它在Neck部分使用了FPN加PAN结构把深层语义特征和浅层纹理特征做了充分融合。值得注意的是YOLOv5的检测头没有完全解耦分类和回归共享了一部分卷积特征这在高密度目标互相遮挡时会增加一些定位误差。YOLOv8在结构上做了几处关键调整。第一是骨干网络里的C3模块换成了C2f模块梯度流更丰富特征复用效率更高。第二是检测头改成解耦头分类分支和回归分支各走各的卷积路径任务冲突被明显缓解。第三是最核心的变化——从Anchor-Based转成Anchor-Free不再依赖预设锚框直接预测目标中心点和宽高。这个设计思路迭代其实有两层意义省去了针对数据集调锚框的步骤训练流程更省心对尺度覆盖也更灵活苹果这种尺度分布很广的目标锚框设计得不好很容易出现小目标召回低的问题Anchor-Free天然不存在这个问题。另外YOLOv8的损失函数里引入了DFL分布损失来优化边界框回归再加上CIoU和分类BCE的配合边界框精度比v5更细。3.2 在苹果数据集上的实测表现同一个数据集、同样的训练配置下我分别用YOLOv5s和YOLOv8s训练了250个epoch输入尺寸640×640batch size 16。两组实验取了效果最好的几个指标模型mAP0.5mAP0.5:0.95模型体积1080Ti上推理帧率YOLOv5s0.9310.724约14MB约95 FPSYOLOv8s0.9480.758约22MB约82 FPSmAP0.5的差距大约是1.7个百分点mAP0.5:0.95的差距大约3.4个百分点。前者代表框得准不准后者代表定位精度和召回的综合能力说明v8在苹果边界框的精细度上确实更有优势。推理速度v5s略快但差距没有质变。在边端设备上这两个模型都还需要做TensorRT加速才能保证实时。3.3 选型建议经过这批数据集的对比实验我的选型判断是这样如果设备算力吃紧比如用树莓派或者老款Jetson系列优先考虑YOLOv5n或YOLOv5s模型小、部署灵活精度损失在可接受范围内。如果目标是做正式项目算力不是卡脖子的瓶颈直接上YOLOv8s甚至YOLOv8m。训练稳定、定位精度好、后处理简单长期维护成本低。如果苹果检测要附带成熟度分类或者坏果检测YOLOv8有现成的分类头支持多任务扩展可以省掉额外训练一个分类模型的成本。如果是个人学习或者竞赛YOLOv8的API更简洁开箱即用程度比v5舒服不少。4. 训练实操全流程4.1 环境准备训练环境我建议直接用Linux加NVIDIA显卡Windows也能跑但坑相对多。我的基准配置是Python 3.9以上PyTorch 1.13或2.x都可以CUDA 11.7以上显卡显存建议8GB以上最低6GB也能跑小模型YOLOv5的仓库环境安装基本是克隆仓库加安装依赖然后根据显卡情况安装对应版本的PyTorch。YOLOv8装起来更省事直接通过pip安装ultralytics包命令行工具和Python API都带上了。核心依赖就是torch、torchvision再加一些图像处理库。安装完第一件事是确认GPU可用python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))输出True才是正常状态。这一步检查很关键很多人装完依赖之后没验证CUDA结果模型一直跑在CPU上一个epoch要跑几个小时还以为是正常的。4.2 数据组织与配置文件数据目录建好后要在项目里写一个YAML配置文件告诉模型去哪里找图和标注。我的apple.yaml长这样path: /home/user/datasets/apple train: images/train val: images/val nc: 1 names: 0: apple注意几个细节path写绝对路径最省心相对路径有时候会因为工作目录不一致报错nc是类别数单类别就是1names里的索引顺序必须和标注文件里的class_id对应。写完之后先做一次完整性校验这一步能省掉训练中途才发现标注文件丢失的痛苦。用脚本统计一下labels/train下有多少个TXTimages/train下有多少张图两个数量要一致。再抽查几个TXT里面的坐标值确保在0到1之间。4.3 关键训练参数解读训练参数的设置直接影响最终效果。我用的训练命令是这样的YOLOv5:python train.py --data apple.yaml --weights yolov5s.pt --batch-size 16 --epochs 250 --img 640 --device 0YOLOv8:yolo train dataapple.yaml modelyolov8s.pt batch16 epochs250 imgsz640 device0几个关键参数逐个说清楚batch size8GB显存建议8到16显存够用就16。batch太大收敛速度并不线性变快反而可能让训练后期震荡。epochs200到300之间比较合适。少于100个epoch模型通常还没收敛充分多于300就边际递减了。我用250是综合考虑了收敛速度和早停机制。imgsz640是性价比最高的输入尺寸。512以下小目标可能掉点768以上对小目标有少量提升但训练和推理时间都明显增加。weights加载预训练权重做迁移学习比从零训练收敛快得多。v5的预训练权重是COCO上训出来的对边缘纹理特征已经有很强的先验。优化器我建议直接用默认值v5默认SGDv8默认AdamW。如果没有充分理由不用刻意改。学习率保持默认的0.01配合前三轮warmup对大部分数据集都适用。v5和v8都内置了早停机制。我一般把patience设置成60到80个epoch如果验证集mAP连续这么多轮没有改善就自动停止能省不少时间。4.4 训练、验证与推理测试训练启动后第一件事是看前几个epoch的loss变化。正常的loss曲线是稳步下降偶有小幅波动。如果第一个epoch的loss就异常高或者前10个epoch完全不降优先检查标注文件有没有错。训练完成后会在runs/train/exp目录下生成权重文件和指标图表。我要重点看的是weights/best.pt和weights/last.pt。best.pt是验证集上mAP最高的权重部署直接用best.pt不要用last.pt。验证用下面的命令# YOLOv5 python val.py --data apple.yaml --weights runs/train/exp/weights/best.pt # YOLOv8 yolo val modelruns/train/exp/weights/best.pt dataapple.yaml验证输出会包含Precision、Recall、mAP0.5、mAP0.5:0.95几个核心指标。苹果这类单类别密集目标我一般要求mAP0.5至少到0.9才算合格低于这个水平说明数据或训练环节有问题。最后一步是拿没进过训练集的果园实拍照片做推理检验。这一步能看出整个验证集指标发现不了的问题。比如模型在密集场景下是不是把两个苹果框成了一个逆光下是不是大量漏检。我碰到的典型情况是验证集mAP有0.94但实地一测发现高处的远距离小苹果基本全漏后来把输入分辨率从640提到768再把训练图里增加高空俯拍角度的样本漏检才明显缓解。# YOLOv8推理 yolo predict modelruns/train/exp/weights/best.pt sourcetest_images/ saveTrue推理输出会直接生成带边界框的图片检查这些图基本就知道模型的真实水平了。5. 常见问题与避坑指南5.1 训练不收敛或loss异常训练不收敛是目标检测最常见的坑但排查路径其实很固定。第一个查标注文件。看一下TXT里坐标有没有超出0到1范围有没有空文件有没有类别索引越界。我用脚本批量扫一遍几秒就能定位问题文件。第二个看图与标注是否对齐。发生过一次因为数据集拷贝时文件名错位导致图像和标注对不上模型训了50个epoch mAP还在0.1以下。第三个查学习率。如果loss一开始下降很快到某个节点后开始大幅震荡多半是学习率偏大。把lr0从0.01降到0.005一般就能缓解。反过来loss下降极为缓慢可以考虑适当增大学习率或者检查是否用错了优化器。还有一个隐蔽问题数据增强过强。有一次我把Mosaic的缩放范围设得很大四张图拼出来之后很多苹果被压成了几个像素的小色块模型直接被带偏。建议新数据集先用默认增强参数跑通流程之后再做微调。5.2 漏检误检怎么排查漏检和误检是两个方向的问题排查思路不同。漏检该框的没框出来优先考虑三件事输入分辨率太低导致小目标丢失训练数据里对应场景样本太少以及NMS阈值设置过严。苹果检测这种密集场景NMS的IoU阈值我一般设在0.5到0.6之间。设太高会导致重叠的框大量保留设太低会把相邻的苹果框一起过滤掉。误检不该框的框出来了大概率是背景干扰没抑制好。我看到过模型把水印上的红色圆形标记当成苹果、把套袋的白色轮廓也框出来。解法是往训练集里补充这些负样本图片让模型看到不同光照、不同背景下的反例。目标检测一定需要负样本这一点很多教程没强调。另一个细节是类别不均衡。如果数据集里不同品种苹果数量差距大模型对样本量小的品种容易漏检。解决办法是给样本量小的类别在损失计算里适当调高权重或者用重采样方式平衡各类别的图片数量。5.3 部署与提速的实用技巧训练跑通只是第一步真正落地到果园设备上是另一回事。我总结几个实用提速手段半精度FP16推理。绝大多数新显卡对FP16有硬件加速精度损失极小速度能提20%到40%。导出ONNX再转TensorRT。同样的YOLOv8s模型TensorRT推理在Jetson上能比原生PyTorch快两到三倍。适当降低输入分辨率。如果检测目标主要是近处大苹果640降到416甚至320帧率可以翻倍代价是远距离小目标基本丧失。调节conf_thres。推理时置信度阈值提高到0.35到0.45能过滤掉大量低置信度误检框视觉上模型“看起来”更干净。部署端还有一个特殊问题果园里通常是边缘设备供电和散热受限模型不能只看精度还要看功耗。实测下来YOLOv8n在低功耗设备上比v8s更有优势如果用Jetson Nano这样的低算力设备老老实实选择n级或者s级强行上m级会导致帧率掉到不可用。写在最后跑完这轮苹果检测项目我个人的体会是目标检测模型的代码门槛并不高真正拉开效果差距的是数据处理和对场景的理解。苹果这种看似简单的目标一旦放进真实果园遮挡、光照、小目标这些问题一个不落全都会找上门来。如果只满足于在公开数据集上刷几个漂亮的指标模型很难在实地场景里真正发挥作用。最后再分享一个小技巧每次实验前把数据集版本、模型版本、关键超参这些信息记录下来。我在调试过程中吃过亏两个实验之间只改了一个参数但忘了记录效果变差之后根本说不清是哪个改动引起的问题。做实验养成记录习惯能少走很多弯路。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询