YOLOv5果蔬识别系统实战:从数据集标注到模型训练与部署
发布时间:2026/9/15 2:05:24来源:尧图网络
简介YOLOv5果蔬识别系统是一套面向计算机专业毕业设计、期末大作业与深度学习实战的完整项目资料包含可供模型训练与评估的果蔬数据集、可本地编译运行的源代码以及配套教程适合需要快速落地目标检测实践的高校学生和开发者。压缩包共56个文件大小94.07MB以Python脚本14个py为主涵盖数据划分、预处理、模型训练与推理等环节同时包含展示用的PNG/JPG/JPEG图片、格式转换与标注相关的TXT/XML文件以及训练好的H5权重模型和Readme说明文档目录结构清晰便于按流程学习与二次开发。项目经导师指导并认可评审分为98分源码经过严格调试运行有保障。已有123人学习下载尤其适合正在做课程设计、毕业设计的学生直接借鉴思路或作为PyTorch/YOLOv5实战练手的参考项目。1. 果蔬识别系统为什么可以成为高分项目YOLOv5 果蔬识别系统的完整交付不等于“能框出水果”。从数据集标注、模型训练到部署演示每一步都可能成为答辩或验收时的加分点。我见过不少项目源码下载后能直接跑通检测但一旦换成本地照片mAP 立刻掉到 0.3 以下原因几乎都出在数据集和超参数上。所以这里按“先造数据、再跑训练、后调参排错、最后推理验证”的顺序把 YOLOv5 训练自己数据集时需要避开的坑和可以直接复用的命令梳理出来。适合毕业设计、课设或竞赛作品也适合想借果蔬场景掌握 YOLOv5 模型训练教程的工程师。2. 果蔬识别数据集构建从公开源到 YOLO 标签格式2.1 果蔬数据集来源怎么选公开集、自采照片和标注取舍常见的公开果蔬数据集中Fruits 360 以单果分类图为主虽然图像干净但它的标注是中心点和半径转成 YOLOv5 检测框需要额外计算而且场景单一训练出来的模型很难处理重叠摆放的果实。AI Challenger 2017 的果蔬数据更贴近自然场景提供 JSON 标注转成 YOLO 格式更实用。Roboflow 上也有不少“fruit detection”项目导出时可以直接选择 YOLOv5 格式省去自己标注的时间。如果打算自己采集照片要注意类别均衡和姿态多样性。只拍红苹果模型会把“苹果”学成“红苹果”只拍超市保鲜膜包装里的水果换到农贸市场就会漏检。常见做法是每个类别至少收集 300 到 500 张照片并覆盖不同光线、遮挡和角度。接下来的标注格式才是决定训练能否顺利的关键。2.2 YOLO 标签格式和 LabelImg 标注txt 文件里的 5 列数字YOLOv5 的标签是每张图片一个同名 txt 文件内容每行表示一个目标格式为class cx cy w h其中坐标都归一化到 0~1。比如一张 1024x768 的图片苹果框的左上角是 (200, 180)右下角是 (520, 560)可以用下面的代码转成 YOLO 格式。# 把绝对坐标转成YOLO格式 x1, y1, x2, y2 200, 180, 520, 560 img_w, img_h 1024, 768 cx ((x1 x2) / 2) / img_w cy ((y1 y2) / 2) / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h print(0, round(cx, 6), round(cy, 6), round(w, 6), round(h, 6))这段代码里cx和cy是目标中心点归一化坐标w和h是框宽高的归一化尺寸类别编号0要与后面的数据集配置保持一致。手动标注时我一般用 LabelImg保存前在右边选择 PascalVOC 或 YOLO 格式YOLO 格式会直接生成同名 txt。需要注意的是 LabelImg 的类别列表从 0 开始顺序必须和你后续在 yaml 里写的names完全一致否则训练出的模型类别会错位。下面表格说明 txt 中每一列的含义方便核对标注文件列位字段说明示例值第1列class类别编号从0开始0 表示苹果第2列cx目标中心点 x 坐标除以图片宽度0.351562第3列cy目标中心点 y 坐标除以图片高度0.482292第4列w目标框宽度除以图片宽度0.312500第5列h目标框高度除以图片高度0.4947922.3 目录结构和数据划分train/val 的路径规范YOLOv5 训练时并不会自动在项目根目录下寻找图片而是通过 yaml 文件指定训练集和验证集的图片目录。目录结构的常见做法是images/train放训练图片labels/train放对应的 txt 标签验证集同理。下面的命令可以创建基础目录mkdir -p dataset/images/train dataset/images/val mkdir -p dataset/labels/train dataset/labels/val然后把标注软件输出的图片和 txt 按 8:2 的比例分到 train 和 val。注意图片与标签必须同名且放在不同的子目录下YOLOv5 训练时自动将图片路径中的images替换为labels来匹配标签。用 Python 做随机划分时要先把图片和 txt 成对 shuffle避免出现训练集有图没有标签、验证集有标签没有图的情况。import os import random from pathlib import Path img_files [p for p in Path(all_images).glob(*.jpg)] random.shuffle(img_files) split int(len(img_files) * 0.8) for i, img in enumerate(img_files): label Path(all_labels) / (img.stem .txt) if i split: img.rename(Path(dataset/images/train) / img.name) label.rename(Path(dataset/labels/train) / label.name) else: img.rename(Path(dataset/images/val) / img.name) label.rename(Path(dataset/labels/val) / label.name)这个脚本里random.shuffle决定划分随机性img.stem是去掉扩展名后的文件名保证 txt 和图片同步移动。移动前建议先打印目标路径确认没有覆盖同名文件。2.4 数据集校验训练前必须跑一次的检查脚本最影响训练稳定性的是标签错误尤其是坐标越界、宽高为负值和空的 txt 文件。YOLOv5 会在训练时报错但报错位置不清晰逐个文件排查很浪费时间。我一般会先跑下面的检查脚本扫描整个 labels 目录。import os from pathlib import Path label_dir Path(dataset/labels/train) for p in sorted(label_dir.glob(*.txt)): lines p.read_text().strip().splitlines() for line in lines: v line.split() cls int(v[0]) cx, cy, w, h map(float, v[1:]) # 归一化坐标必须都在0~1之间宽高不能为0或负数 if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): print(f坐标异常: {p}: {line})脚本检查四类问题类别编号不是整数、中心点超出 0~1、宽或高超过 1、存在空 label 文件。如果输出为空说明标签数据基本可以进入训练阶段。空 txt 文件也值得注意YOLOv5 会忽略它但会减少该图的监督信号影响模型训练稳定性。3. YOLOv5 源代码环境配置从克隆到跑通最小训练3.1 环境配置conda 创建 YOLOv5 运行环境YOLOv5 的依赖集中在requirements.txt中常见做法是用 conda 创建干净的 Python 环境避免和系统 Python 包冲突。Python 3.8 或 3.9 对 YOLOv5 各小版本兼容性最好不必一味追求最新版本。conda create -n yolov5 python3.8 -y conda activate yolov5 pip install -r requirements.txt安装完成后再根据本机 CUDA 版本安装对应 PyTorch。如果忽略这一步训练时可能会遇到“torch not compiled with CUDA enabled”的提示。验证环境是否正确的命令是python -c import torch; print(torch.__version__, torch.cuda.is_available())这里torch.cuda.is_available()返回True才说明 PyTorch 能正常使用 GPU。如果只有 CPU可以继续跑小模型但训练时间会明显变长。3.2 项目源代码目录训练时只需要关注几个文件YOLOv5 项目源码的核心文件不多训练流程也相对固定。熟悉这几个文件就足以完成果蔬识别系统的开发和二次调整文件或目录作用train.py训练入口接收数据集配置、模型结构、超参数等参数detect.py推理入口加载权重对图片、视频或摄像头做检测val.py在验证集上计算 mAP 和 PR 曲线data/custom.yaml数据集配置文件写明图片路径、类别数和类别名data/hyps/hyp.scratch-low.yaml默认超参数文件包含学习率、数据增强等开关models/yolov5s.yaml模型结构定义一般不需要修改不需要改动模型结构文件直接使用 yolov5s 作为基线就够了。果蔬识别场景下yolov5s 在精度和推理速度之间最均衡yolov5m 可以留到后面作为对比。3.3 配置果蔬数据集 yaml训练前最重要的一步在data目录下新建custom.yaml把数据集路径和类别信息写进去。下面是一个可直接复用的配置# 数据集根目录建议写成绝对路径 path: /home/user/dataset train: images/train val: images/val nc: 5 names: 0: apple 1: banana 2: orange 3: tomato 4: potato这里的path是数据集根目录train和val是相对根目录的图片路径nc是类别总数names的索引顺序必须和标注时一致。如果使用相对路径YOLOv5 会相对于当前工作目录寻找在服务器上跑任务时我一般会写绝对路径避免因启动目录不同导致Dataset not found。3.4 最小训练命令解析每个参数都能解释清楚完成数据集配置后用下面的命令启动训练python train.py \ --data data/custom.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --imgsz 640 \ --device 0--weights指定预训练权重yolov5s.pt 会在首次运行时自动下载--epochs是训练轮数小数据集 100 轮足够收敛--batch-size根据显存调整16 以下几乎不会爆显存--imgsz是训练分辨率640 是速度和精度平衡点--device 0表示第一张 GPUCPU 则填cpu。训练过程中会生成runs/train/exp目录保存每个 epoch 的权重、loss 曲线和验证结果。4. 训练果蔬识别模型超参数调整与常见报错4.1 超参数在哪里改hyp yaml 和 train.py 参数的分工在 YOLOv5 中--batch-size、--imgsz、--epochs是命令行参数而学习率、动量和数据增强强度则集中在data/hyps/hyp.scratch-low.yaml里。不要直接修改原始 hyp 文件否则以后升级代码会覆盖。常见做法是复制一份改成hyp.fruit.yaml再传参cp data/hyps/hyp.scratch-low.yaml data/hyps/hyp.fruit.yaml常用参数含义如下表参数默认值作用lr00.01初始学习率果蔬数据集较小时可以降到 0.005lrf0.01最终学习率系数实际最终学习率是 lr0*lrfmomentum0.937SGD 动量提高收敛稳定性weight_decay0.0005权重衰减防止过拟合warmup_epochs3.0初始热身轮数避免开头 loss 爆炸mosaic1.0是否启用 mosaic 数据增强mixup0.0图像混合增强小类别容易过拟合时开启调参时一次只改一个因子不要同时调整学习率和增强概率。果蔬检测场景中最常见的陷阱是数据集类别不平衡。比如苹果多、柠檬少模型会偏向苹果可以降低lr0并延长训练轮数让模型记住少类别特征。4.2 从“能训”到“训好”imgsz、mosaic 和 anchors 的调整顺序如果果实占整张图片的比例很小比如远处果树上的橘子imgsz从 640 调到 960 通常比改任何数据增强都有效。对应命令如下python train.py \ --data data/custom.yaml \ --weights yolov5s.pt \ --hyp data/hyps/hyp.fruit.yaml \ --epochs 120 \ --batch-size 8 \ --imgsz 960 \ --device 0这里把batch-size降到 8是因为 960 分辨率下显存占用约为 640 的 2.25 倍。第二个调整点是在训练后段关闭 mosaic。mosaic 拼接 4 张图可能把不相关的果蔬拼到一起在最后的 10 个 epoch 出现 loss 震荡。可以在 hyp 文件中将mosaic设为 0.5或者用余弦退火调度器的后段自然平稳下来。锚框方面YOLOv5 会在训练开始时自动基于你的标签重新计算 anchors不需要手动指定但要确保标签坐标正确否则 anchor 自适应也会出错。4.3 训练时的常见报错与对策报错现象原因与对策CUDA out of memory降低 batch-size 或 imgsz也可以换 yolov5s 为更小的模型assert label file is missing图片没有对应 txt检查 labels 目录是否与 images 目录一一对应Dataset not foundyaml 中 path 路径写错建议写绝对路径No labels in train set标签全为空或 yaml 的 names 顺序与标注不一致AttributeError: NoneType object预训练权重下载失败手动下载后放到项目根目录遇到 assert 或缺失标签时用前面 2.4 的检查脚本扫描一遍就能定位。训练流程跑通后真正的质量体现在验证集指标上下一章看验证方法和推理部署。5. 模型推理与验证把检测结果变成可交付的演示5.1 用 detect.py 对图片、视频和摄像头实测训练完成后用runs/train/exp/weights/best.pt做推理python detect.py \ --weights runs/train/exp/weights/best.pt \ --source 0 \ --conf-thres 0.45 \ --line-thickness 2--source 0表示第一个 USB 摄像头也可以填图片目录或视频文件路径。--conf-thres是置信度阈值果蔬重叠较多时调到 0.5 可以降低误报但也会减少召回0.3 则相反。先以 0.4 为基准看一轮输出再根据漏检和误检的分布调整。5.2 用验证命令查看 mAP 和 PR 曲线推理看着不错还不够要量化模型精度python val.py \ --data data/custom.yaml \ --weights runs/train/exp/weights/best.pt \ --conf-thres 0.25 \ --iou-thres 0.45val.py 输出每个类别的 AP、整体 mAP0.5 和 mAP0.5:0.95。果蔬识别项目中mAP0.5 更贴近实际演示效果重点看每个类目的 AP 是否均衡如果某个类别明显偏低说明它的训练样本量或光照多样性不足。5.3 导出 ONNX 做轻量化部署如果需要在网页或桌面端演示导出 ONNX 是好选择python export.py \ --weights runs/train/exp/weights/best.pt \ --include onnx \ --opset 12导出后可用 onnxruntime 加载推理速度在 CPU 上通常比 PyTorch 更快。这个过程还会顺带做模型结构简化和常量折叠是答辩演示时比较稳的一条路径。如果后续集成到 Android 或 Jetson可以继续导出 TensorRT 或 TorchScript。5.4 一个大图切块的实测技巧果蔬识别经常面对团队合照或高分辨率货架图直接把大图缩放到 640 会让小果实的像素被压缩。我的做法是像下面这样把大图切成多个 640 的 patch分别检测后再合并重叠框。# 伪代码示意切块推理后合并结果 def crop_infer(model, img, crop_size640, stride320, conf0.4): boxes [] for x in range(0, img.shape[1] - crop_size 1, stride): for y in range(0, img.shape[0] - crop_size 1, stride): crop img[y:ycrop_size, x:xcrop_size] pred model(crop, confconf) for det in pred.xyxy[0]: boxes.append((det[0]x, det[1]y, det[2]x, det[3]y, det[4].item(), det[5].item())) return boxesstride 小于 crop_size保证相邻切块之间有重叠区域避免果实正好被切分。合并后对所有框做一次非极大值抑制就能消除重叠 patch 产生的重复框。最终效果可以根据自己的果蔬图片对比整体缩放到 640 的漏检率再决定是否在正式演示中启用切块推理。如果手头数据里果实都很集中这个技巧可以不启用若货架图密集排列则通常能让 mAP 提升 3 到 5 个百分点。本文还有配套的精品资源点击获取
网站建设高端定制企业官网