
简介这份资源是一套基于YOLOv5架构的果蔬图像识别系统完整实现面向计算机科学与技术等相关专业的毕业设计、课程实践与综合作业场景适合具备机器学习基础的学习者参考。包内共717个文件以546张jpg与jpeg图像构成训练与测试数据集辅以15个py源码脚本、4个h5模型权重、4个xml标注文件及txt说明文档压缩包整体约268.88MB目录结构清晰便于按数据、代码、模型分模块检索。系统覆盖数据预处理、模型训练到性能优化的完整流程所有组件均经多轮验证测试运行稳定可靠可作为目标检测算法落地应用的参考范例。目前已有56人学习下载适合需要完整项目方案与排错思路的读者对照研究。1. 果蔬识别系统为什么总在分拣线上翻车从 YOLOv5 与数据集说起做过果蔬分拣产线视觉项目的人大多有过类似经历实验室里 mAP 跑到 0.95一上产线青椒和黄瓜混在一起、苹果被叶子挡掉半边、传送带反光把番茄照成白斑模型立刻开始玄学输出。问题往往不在网络结构而在两件事——你选的检测框架能不能扛住小目标和遮挡以及你的数据集到底有没有覆盖真实工况。基于 YOLOv5 的果蔬识别系统实现与数据集应用讲的就是把这两件事串起来用 YOLOv5 做单阶段检测主干用一套自己标注、自己清洗的果蔬数据集完成训练、验证和部署。它适合想快速搭出可跑通原型的算法工程师、做课程设计或毕设的学生也适合要把识别模型塞进边缘盒子的一线开发者。读完你能拿到一条从环境配置、数据集组织、超参数调整到推理部署的完整路径而不是停在跑通官方 demo这一步。2. YOLOv5 与果蔬数据集选型理由和最小可跑环境2.1 为什么果蔬检测优先选 YOLOv5 而不是两阶段方案果蔬识别本质是密集小目标检测问题。一筐圣女果可能有几十个实例彼此紧贴、颜色相近还经常被枝叶遮挡。两阶段检测器如 Faster R-CNN 系列精度不差但推理链路长在产线这种要求实时出结果、还要部署到算力有限设备上的场景里帧率往往撑不住。YOLOv5 属于单阶段检测一次前向就出框和类别工程成熟度高社区里yolov5训练自己的数据集的踩坑记录也最全遇到问题容易搜到答案。从工程角度看选 YOLOv5 还有几个现实理由。它的模型尺寸分 n/s/m/l/x 五档n 和 s 适合边缘设备m 以上适合服务器端批量处理同一套代码换权重就能切换算力档位。它的数据增强、锚框自适应、混合精度训练都封装好了不需要自己从零写。对果蔬这种类别数不多通常十几到几十类、单类样本量中等的任务YOLOv5s 往往是性价比最高的起点。需要说清楚边界如果你的果蔬类别超过上百种或者需要同时输出成熟度、缺陷等级这类细粒度属性纯检测头会吃力得考虑分类头或多任务结构。YOLOv5 解决的是这是什么、在哪里不解决它有多熟。2.2 果蔬数据集从哪来、怎么组织成 YOLO 格式数据集是这类项目最容易翻车的地方。公开数据集里果蔬相关的有 Fruit-360 这类分类数据集但它只给类别标签没有检测框不能直接喂给 YOLOv5。真正能用的检测数据集要么自己拍自己标要么找带框的公开集再补充。常见做法是先用手机或工业相机在真实光照下拍几百到上千张覆盖不同角度、遮挡、堆叠情况再用 LabelImg 或 CVAT 标注。YOLOv5 要求的数据组织是固定的。目录结构如下dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml每张图对应一个同名.txt标签文件每行格式是class_id x_center y_center width height坐标全部归一化到 0~1。data.yaml描述路径和类别# data.yaml path: ./dataset # 数据集根目录 train: images/train # 训练集相对路径 val: images/val # 验证集相对路径 nc: 12 # 类别数按你的果蔬种类改 names: [apple, banana, orange, tomato, cucumber, pepper, carrot, grape, strawberry, pear, lemon, peach]这里nc和names必须严格对应顺序错了模型会把苹果认成香蕉。归一化坐标如果写成像素值训练时 loss 会直接爆炸这是新手最常见的错误之一。提示标注时同一类果蔬尽量保持命名一致别一会儿写green_pepper一会儿写pepper否则类别会被拆成两个模型学不明白。2.3 conda 环境配置与 YOLOv5 源码拉取的最小命令环境配置是yolov5环境配置搜索量最高的环节。用 conda 隔离环境避免和系统里的其他 torch 版本打架# 创建并激活环境python 版本按 yolov5 要求选 3.8 以上 conda create -n fruit_yolo python3.9 -y conda activate fruit_yolo # 拉取 yolov5 源码用官方仓库别用来路不明的 fork git clone https://github.com/ultralytics/yolov5.git cd yolov5 # 安装依赖requirements 里已锁定兼容版本 pip install -r requirements.txt装完后验证一下 torch 能不能调用 GPUimport torch print(torch.__version__) print(torch.cuda.is_available()) # 有 GPU 应返回 True如果cuda.is_available()返回 False先别急着改代码八成是 CUDA 版本和 torch 不匹配。常见做法是去 PyTorch 官网按你的显卡驱动选对应命令重装而不是硬扛 CPU 训练——果蔬数据集哪怕只有几千张CPU 训练也要跑到天亮。3. 训练自己的果蔬数据集超参数、增强策略与断点续训3.1 从预训练权重出发训练命令与关键参数逐个拆YOLOv5 官方提供了在 COCO 上预训练的权重果蔬检测一定要从预训练权重微调不要从零训。从零训在小数据集上几乎必然过拟合而且收敛慢得让人怀疑人生。# 从 yolov5s 预训练权重开始训练 python train.py \ --img 640 \ # 输入分辨率果蔬小目标可提到 640 或 800 --batch 16 \ # 批大小显存不够就往下调 --epochs 100 \ # 训练轮数小数据集 100~300 足够 --data data.yaml \ # 指向你的数据集配置 --weights yolov5s.pt \ # 预训练权重 --cfg models/yolov5s.yaml \# 网络结构要和权重档位一致 --name fruit_exp1 \ # 实验名结果存 runs/train/fruit_exp1 --cache # 图片缓存到内存加速读取参数里最需要盯的是--img和--batch。果蔬里的小目标比如一颗樱桃在 640 分辨率下可能只剩十几个像素检测头很难抓把--img提到 800 或 1024 通常能涨点代价是显存和训练时间。--batch受显存限制16 是 8G 显存左右的稳妥值显存够可以往上加但批太小会让 BN 层统计不稳。--cache在数据集不大几千张以内时很香直接把图读进内存每个 epoch 省下大量 IO 时间。数据集上万张就别开了内存扛不住。3.2 果蔬场景的数据增强哪些默认策略要关掉YOLOv5 默认开了 mosaic、HSV 抖动、随机翻转、缩放等增强。果蔬检测里mosaic 把四张图拼成一张能显著提升小目标和遮挡场景的鲁棒性建议保留。但有几个默认项要按场景判断HSV 的色调抖动hsv_h默认 0.015对颜色敏感的果蔬要小心。比如青苹果和黄苹果色调一抖可能就跨了类别边界模型学到的颜色特征被搅乱。如果类别之间主要靠颜色区分把hsv_h调小到 0.005 甚至 0。上下翻转flipud默认关闭这是对的。果蔬在传送带上基本不会倒挂开了反而引入不真实样本。左右翻转fliplr默认 0.5一般保留。如果产线光照固定可以适当降低亮度、饱和度抖动幅度让训练分布贴近实际。反过来如果部署现场光照多变就把抖动开大一点逼模型学形状而不是学光照。3.3 训练过程怎么读loss 曲线、mAP 与断点续训训练启动后终端会实时打印每轮的 box_loss、obj_loss、cls_loss 和 mAP0.5。判断训练是否健康看三条线box_loss 和 cls_loss 应该整体下降并逐渐平缓。如果 cls_loss 一直高位震荡多半是类别不平衡或标注有噪声。obj_loss 反映目标置信度如果它不降反升检查标签里有没有空文件或坐标越界。mAP0.5 是主指标果蔬检测里 0.85 以上算可用0.9 以上算不错。但别只盯 mAP还要看每一类的 AP。如果某一类 AP 明显低通常是该类样本太少或标注质量差补样本比调参更有效。训练中断了不用从头来YOLOv5 支持断点续训# 从上次的 last.pt 继续 python train.py \ --resume runs/train/fruit_exp1/weights/last.pt--resume会恢复优化器状态、学习率调度和 epoch 计数比重新加载权重再训要正确得多。血泪经验别用--weights last.pt假装续训那样学习率会重置前期收敛全白费。4. 推理、验证与部署从单张图到树莓派边缘盒子4.1 用 detect.py 验证模型单张、批量与置信度阈值训练完先别急着部署用detect.py在验证集和真实场景图上过一遍# 对单张图或整个目录做推理 python detect.py \ --weights runs/train/fruit_exp1/weights/best.pt \ --source ./test_images \ # 可以是单张图、目录或视频 --img 640 \ --conf-thres 0.4 \ # 置信度阈值 --iou-thres 0.45 \ # NMS 的 IoU 阈值 --save-txt # 同时保存检测框坐标--conf-thres是最需要调的参数。调高0.5~0.6漏检变多但误检少适合对误报敏感的分拣调低0.25~0.35召回高但可能把背景认成目标。果蔬堆叠场景里我一般先设 0.4 看效果再按漏检和误检的实际情况微调。--iou-thres控制 NMS 合并重叠框的力度。果蔬紧挨着时这个值设太高会把相邻的两个果子合并成一个框设太低又会对同一个果子出多个框。0.45 是通用起点密集场景可以试 0.5~0.6。4.2 树莓派 5 上部署自己训练的 YOLOv5 模型树莓派5上部署自己训练的yolov5模型是很多人的落地目标。树莓派 5 算力比前代强不少但直接跑 PyTorch 原版仍然吃力常见做法是导出 ONNX 或 NCNN 再推理。先导出 ONNX# 导出为 ONNXopset 按部署框架要求选 python export.py \ --weights runs/train/fruit_exp1/weights/best.pt \ --include onnx \ --img 640 \ --opset 12导出后在树莓派上用 onnxruntime 推理import onnxruntime as ort import numpy as np import cv2 # 加载 ONNX 模型CPU 推理 session ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) # 预处理resize 到 640、归一化、转 NCHW img cv2.imread(test.jpg) img cv2.resize(img, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 img np.expand_dims(img, 0) # 推理并取输出 outputs session.run(None, {session.get_inputs()[0].name: img}) print(outputs[0].shape) # 后续做 NMS 和坐标还原树莓派上要盯的是帧率和温度。640 输入下YOLOv5s 的 ONNX 在树莓派 5 上大概能跑到个位数到十几 FPS具体取决于散热和是否开了多线程。如果帧率不够把输入降到 416 或换 YOLOv5n精度会掉一点但能跑起来。别忘了加散热片或风扇长时间推理降频是常事。注意ONNX 导出时的--img要和推理时的输入尺寸一致否则坐标还原会错位框会整体偏移。4.3 用验证集量化评估mAP、混淆矩阵和每类 AP部署前必须用验证集做一次量化评估别靠肉眼看几张图就下结论# 在验证集上评估输出 mAP、precision、recall python val.py \ --weights runs/train/fruit_exp1/weights/best.pt \ --data data.yaml \ --img 640 \ --task val跑完会在runs/val/下生成混淆矩阵和 PR 曲线。混淆矩阵能直接看出哪两类容易混——比如青椒和黄瓜、柠檬和梨如果它们互相误判严重说明特征区分度不够要么补样本要么在类别定义上重新划分。每类 AP 低于 0.7 的类别优先补该类的多样本而不是全局调参。5. 果蔬识别落地避坑五条踩出来的经验5.1 现象训练 mAP 很高上线就崩原因训练集和真实场景分布不一致。实验室拍的是干净背景、均匀光照产线上有反光、阴影、遮挡和传送带纹理。模型学到的是实验室特征不是果蔬本身。解决训练集里必须混入真实工况图哪怕只有一两百张。标注时把反光、遮挡的样本也标进去让模型见过脏数据。上线前用现场图做一次验证别用实验室图自欺欺人。5.2 现象某一类果蔬 AP 始终上不去原因该类样本量太少或者标注框松紧不一致。比如草莓只标了 50 张而苹果标了 500 张模型自然偏向多数类。解决先看该类样本数少于 200 就补拍补标。再看标注质量同一类果子的框要松紧一致别有的贴边有的留一大圈背景。类别极度不平衡时可以在data.yaml里用hyp配置调类别权重但补样本永远比调权重有效。5.3 现象推理时同一个果子出好几个框原因NMS 的--iou-thres设太高重叠框没被合并掉。果蔬密集堆叠时尤其明显。解决把--iou-thres从 0.45 降到 0.3~0.4 试。如果降了还是多框检查是不是模型对同一目标输出了不同类别的高置信框那说明类别特征没学好得回到训练数据上找问题。5.4 现象树莓派上推理帧率只有个位数原因输入分辨率太高、模型档位太大或者没开多线程、没做量化。解决先把--img从 640 降到 416再考虑换 YOLOv5n。ONNX 可以进一步做 INT8 量化帧率能翻倍但精度会掉量化后必须重新用验证集评估。散热也要跟上降频会让帧率断崖式下跌。5.5 现象换一批新果蔬就要重训成本高原因模型是闭集分类只认训练时见过的类别。新增类别必须重新标注并重训。解决如果类别会持续增加考虑把检测和分类拆开——检测只负责找到果蔬分类头单独训练新增类别只重训分类头。或者用开放词汇检测思路但那是另一套方案了。对固定品类产线闭集模型够用对品类频繁变化的场景架构上要提前留口子。6. 把果蔬识别做扎实的一个技巧用困难样本回灌闭环模型上线不是终点。真正让果蔬识别系统越用越准的是一个困难样本回灌的闭环把线上推理置信度处于中间区间比如 0.3~0.6的图自动存下来人工复核后补进训练集定期重训。这个区间是模型最犹豫的地方往往藏着它没学好的场景——遮挡、反光、罕见角度。具体做法是在推理脚本里加一段筛选逻辑# 推理后筛选困难样本置信度在 0.3~0.6 之间的存下来 import os os.makedirs(hard_samples, exist_okTrue) for det in results.xyxy[0]: # 每张图的检测结果 conf float(det[4]) if 0.3 conf 0.6: # 中间置信度区间 cv2.imwrite(fhard_samples/{img_name}, img) break # 一张图存一次即可这段逻辑不复杂但坚持跑几周你会攒下一批极有价值的样本。我自己的习惯是每两周把hard_samples过一遍人工确认标签后并入训练集重训一轮。通常两三轮之后那些原本在 0.4 附近晃的检测会稳定到 0.8 以上产线上的漏检和误检明显下降。参数上中间区间的上下界要按你的场景调。误检多就把下界提到 0.4漏检多就把上界降到 0.5。别把区间设太宽否则存下来的图太多人工复核成本会压垮你。还有一点重训时别把旧数据全丢掉新老数据按比例混合避免模型只适应新场景而遗忘旧场景。我一般保持新样本占三成左右剩下的用历史数据。这个比例不是铁律按你新增场景和原有场景的差异程度调。做果蔬识别这几年最大的教训是别迷信一次训练出来的模型。产线上的光照、果蔬品种、摆放方式都在变模型必须跟着迭代。把回灌闭环搭起来比任何一次调参都值钱。希望帮到你。本文还有配套的精品资源点击获取