基于YOLOv5/YOLOv8/YOLOv11的香蕉成熟度检测项目实战解析 干了大几年视觉项目我越来越觉得农产品成熟度检测是个特别“讲究手感”的活。人眼判断香蕉熟没熟看着简单真要标准化、规模化落地难处在细节里。这个基于深度学习的香蕉成熟度检测项目本质就是拿YOLOv5、YOLOv8、YOLOv11这些检测模型把老师傅眼睛里的经验“翻译”成网络能学懂的框和类别。整套东西从数据集标注、模型训练、指标评估到部署测试都齐了还带源码、说明文档和讲解很适合正在做毕设、或者想低成本试水农业视觉落地的同学参考。我前前后后调过好几版模型也在产地冷库、分拣线边上蹲过现场踩了不少坑。今天这篇文章不聊虚的把项目从数据到部署完整拆开哪些地方容易翻车、参数怎么设、模型怎么选一次性讲清楚。1. 项目定位与方案选型为什么做香蕉成熟度检测为什么锁死YOLO系1.1 一条香蕉背后的分拣痛点香蕉和苹果、梨这类水果不太一样它是典型的呼吸跃变型水果摘下来之后还会继续后熟。今天看着青绿硬挺放两三天可能就全黄变软再过一两天开始起黑斑、果肉发酵。这个特性决定了它在产地分级、仓储催熟、商超上架这几个环节都卡在同一个问题上怎么快速、稳定地判断眼前这批香蕉“熟到了哪一步”。传统做法是工人目测。听起来不复杂实际干起来问题一堆。首先是标准不统一不同工人对“半熟”和“成熟”的边界理解不一样同一筐蕉能分出好几个等级。其次是疲劳一条分拣线连续跑几个小时眼睛看花了漏检误检率明显上去。还有个容易忽视的点有些饱满的熟蕉表面变化很细微灯光暗一点、摆放角度偏一点人眼判断就开始犹豫。用检测模型做这件事核心价值不是“比人眼准多少”而是“稳定且可复制”。机器只要训练好了同一批次的判断标准是一致的不会上午严下午松。1.2 检测与分类的路线之争很多第一次做水果成熟度项目的朋友会先想到图像分类。把香蕉照片丢进一个分类网络输出“生/半熟/熟/过熟”看起来直接。但真到实际场景你会发现分类模型有个前提假设图像主体要足够居中、占比够大。产线上的香蕉可能是整串的可能是单根果指也可能一根输送带上同时过了好几根、互相有遮挡。这种时候分类模型就有点力不从心了。它只能告诉你“整张图大概是什么状态”没法告诉你“图里这根是不是熟的、那根是不是坏的”。检测模型不一样它输出的是目标框加类别先定位再分类天然能处理多目标、小目标、遮挡这些场景。那为什么锁死YOLO系因为单阶段检测器在速度和精度之间平衡得最好。当年的双阶段模型精度高但慢产线上要算成本、要跑实时视频流没法接受那么大的推理开销。YOLO系列从v5到v8、v11、v12一代代更新部署生态越来越成熟训练工具链也越来越省心。项目源码里全部放了这几个版本的配置目的就是让你能横向对比不同硬件条件下选最优解。2. 数据集构建买香蕉、拍照片、画框子这些环节决定模型的“天花板”2.1 数据采集的场景设计和样本配比这个项目用的是自建数据集我强烈建议你不要一上来就想着爬网上的公开图。网上图确实多但成熟度标注风格不确定很多图还带水印、无关背景、过度后期拿来做训练会学出一堆没用的特征。稳妥的做法是自己拍控制变量。我当时的采集逻辑是三层递进。第一层是纯色背景下的单果照片模拟实验室/质检台场景这层图干净适合模型建立基础特征。第二层是模拟产线场景把香蕉摆在不同颜色的输送带、塑料筐、桌面上拍加一点角度倾斜和互相重叠。第三层是真实环境冷库、催熟房、摆放货架光照杂乱、背景复杂这一层最考验泛化能力。类别建议设四类未熟果皮以绿色为主棱角明显、半熟黄绿相间开始转色、成熟整体金黄棱角变圆润、过熟出现黑斑、果皮变暗甚至裂口。四分类的边界比二分类“熟/不熟”更贴近商用分级的实际需求也不会像细粒度分类那样难标注。样本配比上我会刻意少给过熟类的样本。原因很现实过熟香蕉不容易大量获取而且拍摄、搬运过程中容易碰坏。后面训练时通过增强和采样策略来补这个短板。2.2 标注格式与增强策略标注工具我用的是LabelImg画矩形框导出为VOC格式的XML再转成YOLO训练需要的txt格式也就是每行“class_id x_center y_center width height”坐标全部归一化。这里有个新手高频错误YOLO的框坐标是相对原图尺寸的不是像素值。写转换脚本时如果忘记除以宽高训练会直接起飞。忙活完采集和标注我手里大约攒了一千一百多张图标注框八千出头。这个体量对检测模型来说不算多所以数据增强必须认真做。除了YOLO自带的马赛克增强我额外加了亮度扰动、对比度扰动、轻微旋转和HSV色域扰动。香蕉成熟度本质上依赖颜色特征所以这个增强不能太过分否则绿色被调成黄色模型就学歪了。最后按8:1:1划分训练集、验证集、测试集划分前先做一次shuffle并且保证同一串香蕉的连续照片尽量落在同一个集合里避免“半熟到成熟的连续帧”同时出现在训练和验证里造成指标虚高。3. 模型训练v5、v8、v11、v12同台竞技参数到底怎么调3.1 预训练权重与核心超参数训练前先用COCO预训练权重做迁移学习这一步能省下大量时间。很多人问为什么自己从零训效果差因为目标检测特征提取器的底层结构比如边缘、纹理、颜色块在通用数据集上早就学过了。香蕉检测要学的是“熟没熟”的高层语义没必要从第一层卷积重新爬。数据集配置文件只需要写清楚路径和类别名然后挨个版本跑。核心超参数我建议初始这么设超参数推荐值说明imgsz640x640兼顾小目标和速度显存紧张时用512batch16单卡RTX显卡常规容量根据显存调整epochs100配合早停策略一般50轮后开始收敛优化器AdamW比SGD省心学习率策略选择余弦退火初始学习率0.01SGD/ 0.001AdamW迁移学习不要用太大的初始学习率早停耐心20轮防止过拟合我用训练命令的形式记录一遍不同版本的命令细节有差别但整体套路一致。v5的仓库走的是train.pyv8/v11/v12走的是ultralytics同款CLIv11和v12命令行几乎不用改换模型权重名就行。# YOLOv5 训练 python train.py --data banana.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 # YOLOv8 / v11 / v12 训练以v8为例 yolo detect train databanana.yaml modelyolov8n.pt epochs100 imgsz640 batch16这里有个细节值得专门说训练时项目里搭建的是虚拟环境CUDA版本和PyTorch版本必须匹配。我自己遇到过好几次环境装好后训练报错找不到CUDA其实不是显卡坏了是torch装的CPU版。先跑一句python -c import torch; print(torch.cuda.is_available())输出True再开始训能省很多排查时间。3.2 各版本实际效果与选型建议四个版本我都跑过对比下来各有取舍。YOLOv5s最稳社区资料多报错网上基本都有解适合当基线。YOLOv8n的anchor-free设计让回归头输出更简洁训练收敛速度明显比v5快一点而且ultralytics的API上手很顺。YOLOv11在注意力机制和模块堆叠上做了一些优化同等参数量下面精度有小幅提升。YOLOv12是这里面最新的推理框架和部署链路的坑会相对多一点但它主干网络对特征融合的处理确实有点东西精度上限值得一探。从实际指标来看我的数据集上各版本最终mAP50都能到93%以上mAP50-95的差距会拉开几个点。这里我提醒一句不要过度追高版本号先看你的部署硬件。如果产线上是Jetson这种边缘设备YOLOv8n的性价比最高模型小推理损耗低。如果服务器资源够、对精度要求苛刻再考虑v11或v12。4. 模型评估与可视化分析指标漂亮不代表真的能用4.1 从指标到纠错看懂PR曲线和混淆矩阵训练完之后不要只看一个mAP就跑路。mAP是综合指标它能告诉你“整体不错”但没法告诉你“哪类香蕉正在拖后腿”。我每次训练完固定看三样东西验证集PR曲线、混淆矩阵、还有随机挑一批验证图直接可视化推理结果。PR曲线看的是置信度阈值从高到低变化时precision和recall的拉扯关系。香蕉成熟度检测里过熟类最容易出现recall偏低因为黑斑和阴影在视觉上容易混。如果混淆矩阵里“过熟”有一大块被识别成了“成熟”那就要回头检查过熟样本的标注是否够严格。我后来发现不少工人自己都对“成熟后期”和“过熟早期”的界线含糊我重新拉了几十张图做二次复核标注指标立刻好了不少。可视化推理图则是最直观的。把模型跑出来的框画在图上逐张看你会发现一个典型问题模型偶尔会把背景里的棕色纸箱边缘框成香蕉。这种误检在指标上影响很小因为验证集里纸箱出现频率低但现场一旦出现就会在产线上闹出乌龙。处理办法是增加背景负样本光加香蕉正样本不行得专门拍一些没有香蕉的空场景。4.2 最容易翻车的成熟度边界四分类检测项目真正的难点永远在类别边界上。香蕉刚好黄绿各半的时候让任何一个标注员去定性都会犹豫。我的建议是给标注规范写死三条规则。第一果皮绿色面积明显大于黄色时归“未熟”哪怕带一点淡黄也算未熟黄绿色块基本对半开时归“半熟”。第二“成熟”必须整体黄色且果皮表面无明显黑斑只要出现直径超过几毫米的黑斑就直接归入“过熟”。第三同一串上不同果指成熟度不一致时如果要按串检测那就以整体视觉最成熟的区域为准但这个策略必须和需求方确认否则很容易被吐槽。这些边界规则看着繁琐实际上决定了训练数据的噪声水平。标注噪声是检测项目最大的隐形杀手比模型结构的影响大得多。你宁可多花一周时间做标注规范的校对也不要急着把不干净的标签丢进训练。5. 部署落地从pth权重到产线跑起来中间还有五个坑5.1 模型导出与推理框架选择训练出来的权重是PyTorch格式直接拿去部署不太现实产线机器一般没有深度学习训练环境。常规做法是导出成ONNX再做推理加速。导出这一步有讲究。v5用仓库里的export.pyv8/v11/v12用ultralytics的export接口。导出前要指定imgsz保持和训练尺寸一致。之前遇到过训练用640导出忘记传参默认导出成640但opset版本选低了导致后面用ONNX Runtime推理时某些算子不兼容白白排查了两天。推理框架的选择取决于场景。纯CPU工控机优先考虑OpenVINOIntel平台优化明显。NVIDIA显卡环境走TensorRT半精度FP16推理速度能比ONNX Runtime再快一倍左右。边缘盒子像Jetson就老老实实转TensorRT的engine格式显存占用还能压一压。我用ONNX Runtime写过一个最简推理流程核心代码如下import onnxruntime as ort import cv2 import numpy as np sess ort.InferenceSession(banana_yolov8s.onnx, providers[CPUExecutionProvider]) input_name sess.get_inputs()[0].name image cv2.imread(test.jpg) img_resized cv2.resize(image, (640, 640)) img_input img_resized[:, :, ::-1].transpose(2, 0, 1)[np.newaxis, ...].astype(np.float32) / 255.0 outputs sess.run(None, {input_name: img_input}) # outputs经过解码后画框这段代码只是示意真正的anchor解码和NMS后处理要根据具体模型版本的输出来写v8以后是anchor-free结构解码方式和v5有区别直接套旧代码会画出一堆乱框。5.2 一个低成本的产线检测Demo部署环境我建议先弄一个简化版的测试台不必一上来就接全自动分拣。一颗普通的工控机加USB工业相机就够了相机高度固定光源用白色LED环形灯尽量让光线均匀减少香蕉表面的反光。检测逻辑做成循环取帧、跑推理、结果上屏的模式。为了控制产线节奏我在推理线程里做了一次帧率压制取流和推理分离用队列缓冲防止相机帧率太高导致模型被连续调用、CPU占用满。实测下来单张640分辨率图像在CPU上推理大概150到250毫秒在GPU上能压到20毫秒以内。给分拣机械臂的指令只发类别ID和置信度下游PLC再去触发对应的分拣动作。这里我建议加入一个最低置信度阈值我常用的是0.45到0.5低于这个值就标记为“待人工复核”。有些过熟香蕉长得实在太抽象模型低置信度漏检可以理解直接硬分反而增加客诉风险。6. 常见问题与排查实录那些文档里不会写、但一定会遇到的幺蛾子我整理了一张问题速查表基本都是项目推进过程中真实踩过并且已经验证解法的异常现象常见原因解决思路训练Loss不降学习率过大、标签文件坐标错误先检查标签txt尺寸是否归一化再调低初始学习率mAP很高但现场误检不断背景样本缺失、光照变化大补充负样本图像调整采集光照方案过熟类被大量判成成熟标注规则不严、黑斑样本少重新二审标注增加过熟类增强权重导出ONNX后推理结果全乱了输出解码方式不对、opset版本偏低用官方配套的后处理脚本确认解码结构匹配边缘设备推理帧率上不去模型过大、输入尺寸太高换更小版本模型输入降到480必要时量化INT8GPU训练时显存溢出batch设太大、分辨率太高调小batch开启梯度累积或改完自动混合精度再试摄像头下颜色偏色严重白平衡没固定、光源不稳定手动锁定相机白平衡参数避免自动调节还有个常见到容易被忽略的坑训练时数据增强里的马赛克增强在最后二十轮建议关闭。如果全程开着模型会在增强过度的图像上反复拟合噪声验证集mAP的曲线可能稳中带降。等跑完实验再回头看关掉马赛克之后的权重明显要稳。另外就是样本收集的持续性。第一版模型部署到现场后肯定有漏检案例。我建议在产线旁边放一个“疑问文件夹”定期把模型置信度低但人工认为明显的图像存进去每凑够一批就做一次增量训练。这种闭环打法是常规做法但它真的有用比反复调超参数有效得多。最后再分享一个小技巧。香蕉成熟度检测的部署效果很多时候不取决于模型有多强而是取决于相机摆位和光源。我在产线测试时发现同样是九成熟的香蕉在冷库的白光下和靠近窗边的暖光下拍出来的颜色差异非常大。把光源稳定住模型准确率能凭空涨两个点。这个经验放到其他果蔬检测项目里同样成立谁先把环境光控住谁就先赢了一半。