简介:这份资源面向计算机科学与技术等相关专业的毕业设计学生与课程实践者,提供一套基于YOLOv5架构的果蔬图像识别系统完整实现方案,可解决目标检测算法从数据预处理、模型训练到性能优化的全流程落地问题,适合具备机器学习基础的学习者参考开发。压缩包共717个文件,约268.88MB,以546张jpg与jpeg图像构成训练与测试数据集,辅以15个py脚本承载模型训练与推理逻辑,另有h5权重文件、zbak备份、png示意图、txt说明及xml标注等,目录结构清晰便于按模块检索。目前已有56人学习下载。读者可从中获得可直接运行的源码工程、配套数据集与实现指南,理解果蔬类别自动化检测的完整链路,并借鉴经导师审核获优秀评价的项目组织方式,用于毕业设计、综合作业或算法研究复现。
1. 果蔬识别系统为什么总在产线翻车:从 YOLOv5 到自建数据集的落地路径
做过分拣线的人都知道,果蔬识别这件事在 demo 里几乎不会失败,一上产线就原形毕露。原因不复杂:公开数据集里的苹果是影棚光下的苹果,而你产线上的苹果带着泥、带着水珠、被前一颗果子挡住三分之一,还可能在传送带上滚成任意角度。基于 YOLOv5 的果蔬识别系统实现与数据集应用,讲的正是怎么把「能识别」变成「稳定识别」——用 YOLOv5 做检测主干,把数据集从采集、标注、增强到训练、部署整条链路打通。这套方案适合两类人:一类是要交课程设计或毕设、需要完整代码加界面加数据集的学生;另一类是工厂里真要上分拣设备、被误检率折磨过的工程师。下面按「先立住原理、再动手复现、最后讲坑」的顺序拆开讲,参数和命令都能直接抄。
2. 果蔬识别系统的技术选型:为什么是 YOLOv5 而不是别的
2.1 单阶段检测在果蔬场景的取舍逻辑
果蔬分拣的核心诉求是实时。一条传送带每秒过 3 到 5 个果子,检测模型必须在几十毫秒内出结果,否则机械臂来不及动作。目标检测大致分两派:两阶段(以 Faster R-CNN 为代表)先出候选框再分类,精度高但慢;单阶段(YOLO、SSD 系列)一步回归出框和类别,快。果蔬识别里类别通常不多——苹果、橘子、香蕉、番茄、黄瓜,撑死二三十类——两阶段那点精度优势换不回速度损失,所以单阶段是默认选择。
YOLOv5 在单阶段里又占一个特殊位置。它不是论文里精度最高的,但工程化程度高:仓库结构清晰,训练脚本、推理脚本、导出脚本齐全,配置文件用 yaml 写,改网络结构不用动 Python。对果蔬这种「类别少、目标大、背景相对固定」的场景,YOLOv5s 或 YOLOv5m 就够,参数量小,树莓派 5 这类边缘设备也能跑。相比之下 YOLOv8 精度略高、API 更现代,但如果你手上是旧教程、旧代码、旧部署脚本,YOLOv5 的生态兼容性反而更省心。选型不是选最强,是选最不容易在部署环节卡住的。
2.2 环境配置:conda 建环境到跑通 detect.py
环境这一步翻车的人最多,血泪经验是先锁 Python 版本再装依赖。YOLOv5 对 Python 3.8 到 3.10 兼容最好,3.11 以上偶尔会在某些 torch 版本上出问题。
# 创建独立环境,避免污染系统 Python conda create -n fruit_yolo python=3.9 -y conda activate fruit_yolo # 克隆 YOLOv5 源码(用官方仓库,别用来路不明的压缩包) git clone https://github.com/ultralytics/yolov5 cd yolov5 # 安装依赖,torch 单独指定 CUDA 版本更稳 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt逻辑说明:conda 建独立环境是为了让后面装 torch、opencv 时不和系统里其他项目打架。torch 单独装是因为 requirements.txt 里的 torch 版本可能和你显卡驱动不匹配,先按 CUDA 版本装好 torch,再装其余依赖,能避开大半「torch.cuda.is_available() 返回 False」的问题。参数上,cu118对应 CUDA 11.8,你要先nvidia-smi看驱动支持的 CUDA 上限,再选对应 wheel。
装完验证:
python -c "import torch; print(torch.cuda.is_available(), torch.__version__)" python detect.py --weights yolov5s.pt --source data/images --device 0第一条打印True和版本号才算环境通了。第二条用预训练权重跑官方示例图,能出结果说明推理链路没问题。如果detect.py报缺yaml或cv2,回pip install -r requirements.txt补,别一个个手装。
2.3 数据集从哪来:公开集与自采集的配比
果蔬识别的数据集有两条路。一条是找公开集,比如一些农业图像数据集、超市货架数据集,优点是省事,缺点是类别和你的实际场景对不上,光照、角度、品种都有偏差。另一条是自采集,拿手机或工业相机在真实产线上拍,优点是分布一致,缺点是要标。
我的做法是混合:公开集打底,自采集补场景。公开集用来让模型先学到「苹果长什么样」这种通用特征,自采集用来教它「你这条线上的苹果带泥、侧放、被遮挡时是什么样」。比例上,自采集至少占三成,否则模型在你自己场景里的表现会明显掉。类别命名要统一,别公开集叫apple、自采集叫Apple,训练时会被当成两类。
采集时注意几点:每个类别至少 300 到 500 张,光照要覆盖早中晚或开灯关灯两种状态,遮挡和堆叠要专门拍一批。这些是后面模型泛化的底子,采集偷懒,训练再调参也补不回来。
3. 数据集制作:从原始图片到 YOLOv5 能吃的格式
3.1 标注规范与 labelImg 实操
YOLOv5 要的标注是每张图一个同名 txt,每行一个目标,格式是类别索引 中心x 中心y 宽 高,后四个都是相对整图宽高的归一化值,范围 0 到 1。这个格式和 VOC 的 xml、COCO 的 json 都不一样,转换是必经步骤。
标注工具用 labelImg 最省事:
pip install labelImg labelImg打开后选YOLO格式(不是 PascalVOC),设置好图片目录和标注保存目录,快捷键 W 画框、D 下一张。画框时贴紧目标边缘,别留太多背景,也别切掉果子。同一张图里被遮挡的果子,只要肉眼能辨认出超过一半,就标;完全看不见的不标,标了反而教坏模型。
标注完检查一遍:有没有漏标、有没有把背景当目标、类别有没有选错。漏标是果蔬数据集里最隐蔽的坑,一张图漏一个果子,模型就学成「这种果子可以不存在」。
3.2 目录结构与 data.yaml 配置
YOLOv5 认的目录结构是固定的,摆错位置训练脚本直接找不到图。
fruit_dataset/ ├── images/ │ ├── train/ # 训练图 │ └── val/ # 验证图 ├── labels/ │ ├── train/ # 训练标注 txt │ └── val/ # 验证标注 txt └── data.yamldata.yaml是数据集的总入口:
# 类别数,必须和 names 长度一致 nc: 5 # 类别名,顺序就是标注时用的索引顺序 names: ['apple', 'orange', 'banana', 'tomato', 'cucumber'] # 训练和验证图片目录,用绝对路径或相对 yolov5 根目录的路径 train: ../fruit_dataset/images/train val: ../fruit_dataset/images/val参数说明:nc写错是最常见的报错来源,多一类少一类都会在训练启动时崩。names的顺序必须和标注时 labelImg 里类别列表的顺序完全一致,否则模型会把苹果学成橘子。train和val路径建议写绝对路径,相对路径容易因为工作目录不同而找不到。
划分训练验证集时,按 8:2 或 9:1 分。注意别让同一颗果子在不同角度拍的多张图同时进训练和验证,否则验证精度虚高,实际部署打脸。按「拍摄批次」划分比按「单张图」随机划分更靠谱。
3.3 数据增强:什么时候该开,什么时候该关
YOLOv5 训练时自带增强,在hyp.scratch-low.yaml这类超参文件里控制。果蔬场景常用的几个:
| 参数 | 作用 | 果蔬场景建议 |
|---|---|---|
| hsv_h | 色调抖动 | 0.015 左右,模拟不同成熟度 |
| hsv_s | 饱和度抖动 | 0.7 左右,模拟光照变化 |
| hsv_v | 明度抖动 | 0.4 左右,模拟明暗 |
| fliplr | 水平翻转 | 0.5,果蔬左右对称可开 |
| flipud | 垂直翻转 | 0,果子一般不会倒挂 |
| mosaic | 四图拼接 | 1.0,小目标多时有用 |
| mixup | 图像混合 | 0.1 到 0.2,别太高 |
逻辑是:颜色抖动对应果蔬成熟度和光照差异,翻转对应摆放角度,mosaic 让模型见到更多组合场景。但垂直翻转要关,因为现实里果子不会头朝下挂在传送带上,开了反而引入不存在的分布。mixup 开太高会让果子边界糊掉,检测框回归变差,果蔬这种需要精确框的场景控制在 0.2 以内。
增强不是越多越好。如果你自采集数据本来就少,增强能救一救;如果数据已经几千张且分布真实,增强开太猛反而让模型学不到真实纹理。先按默认跑一版,看验证集表现再调。
4. 训练与调参:让果蔬识别模型真正收敛
4.1 从预训练权重开始训练自己的数据集
果蔬识别千万别从零训。YOLOv5 官方在 COCO 上训过的权重已经学到了边缘、纹理、形状这些通用特征,拿来微调收敛快得多。
# 用 yolov5s 预训练权重,在自建果蔬数据集上训练 python train.py \ --weights yolov5s.pt \ --data ../fruit_dataset/data.yaml \ --epochs 100 \ --batch-size 16 \ --img 640 \ --device 0 \ --workers 4 \ --name fruit_exp1逻辑说明:--weights yolov5s.pt加载预训练权重,脚本会自动把最后一层换成你的类别数。--data指向刚才的 data.yaml。--epochs 100对果蔬这种小数据集通常够,看损失曲线决定要不要加。--batch-size 16要按显存调,8G 显存跑 640 尺寸大概能到 16,爆显存就降到 8。--img 640是输入尺寸,果蔬目标大,640 够用,小目标多可以上 1280 但显存翻倍。--device 0指定第一块 GPU,CPU 训练把这里去掉但会很慢。--workers是数据加载线程,Windows 上设 0 或 2 避免多进程报错。
训练开始后看几个信号:box_loss、obj_loss、cls_loss三条损失应该整体下降,如果某条一直不降或震荡,多半是学习率或数据有问题。mAP@0.5是主指标,果蔬场景一般能到 0.9 以上,到不了就回去查标注质量。
4.2 超参数怎么调:学习率、batch 与图像尺寸
YOLOv5 的超参在data/hyps/下的 yaml 里,训练时用--hyp指定。果蔬场景最该动的是这三个:
学习率lr0默认 0.01。数据集小(几千张以内)时,0.01 偏大,容易震荡,降到 0.001 到 0.005 更稳。判断方法看损失曲线,前期剧烈上下跳就是大了。
lrf是最终学习率系数,默认 0.01,配合余弦退火。一般不用动,除非你发现训练后期损失还在降但 mAP 不涨,可以适当调大让后期学得更细。
图像尺寸--img前面提过。果蔬目标在画面里占比大,640 通常够;如果传送带上果子小、相机又远,目标只有几十像素,那要上 960 或 1280,同时 batch 相应减小。
调参顺序建议:先固定默认超参跑一版拿到基线,再单独调学习率,再调尺寸,一次只动一个变量。同时改三个参数,出了问题你根本不知道是哪个引起的,这是玄学调参的根源。
4.3 训练过程监控与早停判断
训练时终端会打印每轮的指标,同时runs/train/fruit_exp1/下会存results.csv和曲线图。重点看results.png里的 mAP 曲线。
早停的判断:如果连续 20 到 30 轮 mAP 不再上升,且验证损失开始抬头,就是过拟合了,可以停。YOLOv5 有--patience参数控制早停轮数,默认 50,果蔬数据集可以设 30 省时间。
另一个信号是训练集和验证集指标差距。训练 mAP 0.99、验证 mAP 0.7,说明过拟合严重,要么加数据,要么加增强,要么减模型复杂度(换 yolov5n)。两者都低,说明欠拟合,加轮数或加模型容量。
训练完在runs/train/fruit_exp1/weights/下会有best.pt和last.pt。best.pt是验证集表现最好的那轮,部署用它;last.pt是最后一轮,一般不用。
5. 避坑与排查:果蔬识别落地时最常踩的五个坑
5.1 验证集精度很高,一上产线就崩
现象:训练完 mAP@0.5 到 0.95,拿产线视频一测,误检漏检一堆。
原因:验证集和训练集来自同一批拍摄,分布太像,模型只是记住了这批图,没学到泛化特征。或者验证集划分时把同一颗果子的多角度图分到了两边,造成数据泄漏。
解决:按拍摄批次划分数据集,验证集用完全没参与训练的批次。再单独留一批「测试集」,训练全程不碰,最后只用它评估。测试集精度才是真实水平。
5.2 类别不平衡导致小类识别不出来
现象:苹果识别很准,黄瓜几乎检不到。
原因:苹果图片占了七成,黄瓜只有几十张,模型倾向于把不确定的目标都判成多数类。
解决:补采小类数据到和其他类接近;或者在 data.yaml 里没法直接设权重,改用重采样,训练时让小类图片被抽到的概率更高;也可以先合并相似类别,比如把不同品种番茄合成一类,减少类别数。
5.3 显存爆了但不知道爆在哪
现象:训练跑几轮后报 CUDA out of memory。
原因:batch 太大、图像尺寸太大、workers 太多导致数据加载占用显存,或者验证阶段 batch 没单独设。
解决:先降--batch-size到 8 或 4;再降--img;--workers设小一点。YOLOv5 验证时的 batch 默认是训练 batch 的两倍,可以用--noval先跳过验证确认是不是验证阶段爆的。
5.4 标注格式转换后训练报标签越界
现象:训练启动时报Label class x is invalid或坐标超出 0 到 1。
原因:从 VOC 或 COCO 转 YOLO 格式时,归一化算错,或者类别索引从 1 开始(VOC 习惯)而 YOLO 要求从 0 开始。
解决:转换脚本里确认除以的是图片真实宽高,类别索引减 1。转完写个校验脚本,遍历所有 txt,检查每行五个值,后四个在 0 到 1 之间,第一个是 0 到 nc-1 的整数。
5.5 部署到树莓派 5 后帧率低到没法用
现象:PC 上跑得好好的模型,树莓派上推理一张要几百毫秒。
原因:树莓派没有 CUDA,只能 CPU 推理,yolov5s 在 CPU 上本来就慢;再加上没做模型导出优化。
解决:先把模型导出成 ONNX 或 NCNN 格式,NCNN 在 ARM 上优化好,帧率能翻几倍。导出命令python export.py --weights best.pt --include onnx,再用 NCNN 工具转。输入尺寸也可以从 640 降到 416,精度掉一点换速度。如果还不行,换 yolov5n,参数量最小。
6. 从训练完到能用:导出、量化与一个验证技巧
模型训完只是半成品,真正落地还要过导出和验证两关。导出这一步,PC 上用 PyTorch 权重没问题,但部署到边缘设备或想提速,就得转格式。ONNX 是通用中间格式,NCNN 在 ARM 上快,TensorRT 在 NVIDIA 边缘设备上最快。果蔬识别如果上的是 Jetson 系列,直接走 TensorRT:
# 导出 ONNX python export.py --weights runs/train/fruit_exp1/weights/best.pt --include onnx --img 640 # 导出 TensorRT(需要装 tensorrt 和 pycuda) python export.py --weights runs/train/fruit_exp1/weights/best.pt --include engine --img 640 --device 0逻辑说明:--include指定导出格式,可以一次写多个用逗号隔开。--img要和训练时一致,否则精度会掉。TensorRT 导出会做层融合和 FP16 量化,速度提升明显,但精度可能掉零点几个点,导出后必须重新验证。
量化是另一个提速手段。FP16 量化几乎不掉精度,INT8 量化提速更多但需要校准集,果蔬场景如果颜色差异大,INT8 容易把相近颜色判错,谨慎用。我一般先用 FP16,不够快再考虑 INT8。
验证导出模型有没有掉精度,别只看 mAP 数字,要拿真实产线视频跑一遍,人眼比对。有个技巧:把导出前后的模型对同一批图推理,把两次的检测框画在同一张图上,颜色区分,肉眼能直接看出哪里框偏了、哪里漏了。这比看指标直观得多,很多量化引入的细微偏移,指标上看不出来,画出来一眼就发现。
我自己踩过最深的坑是导出时改了输入尺寸却没重训,模型在 640 上训的,导出成 416,框全偏了,查了一下午才反应过来。所以导出参数和训练参数必须对齐,这是后悔药都来不及吃的错误。部署前把「训练配置、导出配置、推理配置」三份参数列个表对一遍,能省掉大量返工。
希望帮到你。
本文还有配套的精品资源,点击获取