简介:本资源面向深度学习目标检测初学者与进阶开发者,提供一套基于YOLOv8的瓶子识别检测系统完整源码,涵盖训练好的模型、部署教程与各项评估指标曲线,平均准确率达0.95,类别为bottle。压缩包共488个文件,约89.27MB,以115个Python脚本、173个Markdown说明文档、41个YAML配置、91个编译文件及5个pt权重文件为主,另含少量图片、Shell脚本与Dockerfile,覆盖训练、推理、部署全流程。资源基于ultralytics-main官方代码,包含分类、检测、姿态估计与分割四部分,重点使用detect模块,并附带数据集配置、训练脚本与预测脚本,方便读者快速复现瓶子检测实验。目前已有2653人学习下载,适合希望掌握YOLOv8目标检测实战、理解模型评估与调参思路的读者参考。
1. 拿到一个瓶子识别检测系统源码包,先别急着解压
工厂质检线上,一瓶饮料要过的关卡比想象中多:瓶身有没有裂纹、瓶盖有没有歪、液位够不够、标签贴没贴正。过去这些靠人眼盯,一条线三班倒至少六个人,漏检率还压不下去。现在用 YOLOv8 做瓶子识别检测,单张图推理能压到十几毫秒,mAP 稳定在 0.95 以上,这是很多中小产线愿意投入的原因。
你手上这个「基于 YOLOv8 的各种瓶子识别检测系统源码」压缩包,本质上是一套已经跑通的完整工程:训练好的权重、训练曲线、评估指标、推理脚本、部署说明都在里面。它解决的不是「YOLOv8 是什么」的问题,而是「我不想从零标注三千张图、不想调两周超参,能不能直接拿来用或者微调」的问题。适合两类人:一是产线视觉工程师要快速验证方案可行性,二是学生或转行者想拿一个完整项目吃透检测流程。但源码包不是黑匣子,你得知道每一块在干什么,否则换个瓶子品类就翻车。
2. 拆开压缩包:目录结构决定你能不能改得动
2.1 一个标准 YOLOv8 检测工程应该有什么
拿到源码包先别运行,花五分钟看目录。一个能落地、能二次开发的 YOLOv8 瓶子检测工程,目录结构通常长这样:
bottle_detection/ ├── datasets/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── bottle.yaml ├── weights/ │ ├── best.pt │ └── last.pt ├── runs/ │ └── detect/ │ └── train/ │ ├── results.csv │ ├── results.png │ ├── confusion_matrix.png │ ├── PR_curve.png │ └── weights/ ├── train.py ├── predict.py ├── val.py ├── export.py └── requirements.txtdatasets放数据和类别配置,weights放训练好的权重,runs放训练过程产出的所有曲线和日志,根目录三个脚本分别对应训练、推理、验证。如果压缩包里缺了runs目录或者里面只有一张results.png没有results.csv,说明作者可能只留了图没留原始日志,你想复现训练过程就得自己重跑。
bottle.yaml是数据集描述文件,内容一般是这样:
path: ./datasets train: images/train val: images/val test: images/test nc: 4 names: 0: bottle_ok 1: bottle_crack 2: cap_missing 3: label_offsetnc是类别数,names是类别名和索引的映射。这里有个血泪经验:很多人改数据集时只改了names忘了改nc,训练直接报维度不匹配,排查半天以为是环境问题。nc必须等于names的条目数,一个都不能多。
2.2 权重文件和评估曲线怎么读
best.pt是验证集上表现最好的权重,last.pt是最后一个 epoch 的权重。优先用best.pt做推理,除非你发现训练后期还在下降、last.pt反而更好,那说明验证集划分可能有问题。
runs/detect/train目录下的文件是判断这个模型能不能用的关键:
| 文件 | 看什么 | 判断标准 |
|---|---|---|
| results.csv | 每个 epoch 的 loss 和 mAP | mAP50 是否收敛且无剧烈震荡 |
| results.png | 损失和指标曲线 | 训练 loss 和验证 loss 是否同步下降 |
| confusion_matrix.png | 各类别混淆情况 | 对角线是否够深,有无系统性误判 |
| PR_curve.png | 精确率-召回率曲线 | 曲线是否靠近右上角 |
| F1_curve.png | F1 随置信度变化 | 峰值对应的置信度就是推理阈值参考 |
打开results.csv,重点看三列:train/box_loss、val/box_loss、metrics/mAP50(B)。如果train/box_loss一直降但val/box_loss从某个 epoch 开始往上走,这是典型过拟合,说明数据量不够或者增强太弱。如果mAP50在 0.9 以上且最后十个 epoch 波动不超过 0.01,这个权重可以直接用。
提示:有些源码包会把
results.csv删掉只留图,这时候你没法精确判断收敛情况,只能从results.png目测。如果连图都没有,建议直接用自己的数据重训,别赌。
3. 从零跑通推理:环境配置和最小命令
3.1 环境配置的版本坑
YOLOv8 依赖 ultralytics 包,而 ultralytics 对 torch 版本有要求。截至我最近一次部署,稳定组合是 Python 3.9 或 3.10、torch 2.0.x、ultralytics 8.0.x。Python 3.11 在部分 CUDA 版本下会有兼容问题,Python 3.12 更不建议,很多轮子还没跟上。
conda create -n bottle_yolo python=3.10 -y conda activate bottle_yolo pip install torch==2.0.1 torchvision==0.15.2 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics==8.0.200 opencv-python==4.8.1.78第一行建虚拟环境,第二行激活,第三行装 GPU 版 torch,cu118对应 CUDA 11.8,如果你机器是 CUDA 12.x 就换成cu121。第四行装 ultralytics 和 opencv。注意 ultralytics 不要装最新版,新版本有时会改 API,源码包里的脚本可能跑不通。
验证环境是否正常:
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"输出True和你的显卡型号就对了。如果输出False,检查驱动和 CUDA 版本,别急着往下走,CPU 推理一张图要几百毫秒,产线根本没法用。
3.2 用训练好的权重跑单张图和批量图
源码包里一般有predict.py,但你可能想先手动跑一遍确认权重没问题:
from ultralytics import YOLO # 加载训练好的权重 model = YOLO("weights/best.pt") # 单张图推理,conf 是置信度阈值,iou 是 NMS 的 IoU 阈值 results = model.predict( source="test_images/bottle_001.jpg", conf=0.25, iou=0.45, imgsz=640, save=True, project="output", name="single_test" ) # 打印检测到的类别和置信度 for r in results: for box in r.boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) xyxy = box.xyxy[0].tolist() print(f"类别: {model.names[cls_id]}, 置信度: {conf:.3f}, 坐标: {xyxy}")conf=0.25是置信度阈值,低于这个值的检测框会被丢弃。iou=0.45是 NMS 的 IoU 阈值,控制重叠框的合并程度。imgsz=640是推理输入尺寸,必须和训练时一致,否则精度会掉。save=True会把画了框的图存到output/single_test目录。
批量推理把source改成文件夹路径:
results = model.predict( source="test_images/", conf=0.25, iou=0.45, imgsz=640, save=True, save_txt=True, project="output", name="batch_test" )save_txt=True会额外输出 YOLO 格式的标注文件,每行是类别 中心x 中心y 宽 高,方便你后续做统计或者导入其他系统。
3.3 参数怎么调:置信度和 IoU 的取舍
conf和iou这两个参数直接决定漏检和误检的平衡。瓶子检测场景下,我的经验值是这样的:
| 场景 | conf | iou | 理由 |
|---|---|---|---|
| 缺陷检测(裂纹、缺盖) | 0.15~0.20 | 0.45 | 宁可误检不可漏检,后续人工复核 |
| 计数统计 | 0.35~0.45 | 0.50 | 要求准确,误检会污染计数 |
| 实时分拣 | 0.25~0.30 | 0.45 | 平衡速度和精度 |
| 标注辅助 | 0.10~0.15 | 0.40 | 尽量多出框,人工删比人工画快 |
调参方法:拿一批有标注的测试图,用val.py跑不同conf值下的 mAP 和 F1,选 F1 峰值对应的conf。不要凭感觉设 0.5,很多缺陷类目标的置信度天然偏低,0.5 会漏掉一大半。
4. 用自己的瓶子数据微调:标注、训练、看曲线
4.1 数据标注和格式转换
源码包自带的权重只认它训练时的类别。你要检测新品类瓶子,必须自己标注数据微调。标注工具用 labelImg 或 Roboflow 都行,导出 YOLO 格式。
标注时注意三条:框要贴紧目标边缘,不要留太多背景;同类目标框的大小要一致,不要有的框到瓶盖有的框到瓶底;遮挡超过 50% 的目标要么不标要么标可见部分,别硬猜。
标注完的目录结构按 2.1 节那样组织,然后改bottle.yaml的nc和names。如果只检测一种瓶子且不分缺陷类型,nc: 1,names: {0: bottle}。
4.2 训练命令和关键参数
yolo detect train \ data=datasets/bottle.yaml \ model=weights/best.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.001 \ lrf=0.01 \ patience=20 \ device=0 \ project=runs/detect \ name=finetune逐行解释:data指向数据集配置;model用预训练权重初始化,比从yolov8n.pt从头训收敛快得多;epochs=100是最大轮数;imgsz=640输入尺寸;batch=16批大小,显存不够就降到 8 或 4;lr0=0.001初始学习率,微调时比从头训小一个数量级;lrf=0.01最终学习率是初始的 1%;patience=20连续 20 轮 mAP 不升就早停;device=0用第一块 GPU。
如果你用 GTX 1660 Ti 这种 6GB 显存的卡,batch设 8,imgsz可以降到 512,但精度会损失两三个点。显存不够时的优先级:先降 batch,再降 imgsz,最后才考虑换小模型。
4.3 训练过程中看什么、怎么判断要不要停
训练启动后,终端会实时打印每个 epoch 的 loss 和 mAP。同时runs/detect/finetune目录下会生成results.csv,你可以用 pandas 画图:
import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("runs/detect/finetune/results.csv") df.columns = df.columns.str.strip() fig, axes = plt.subplots(1, 2, figsize=(12, 4)) axes[0].plot(df["epoch"], df["train/box_loss"], label="train_box_loss") axes[0].plot(df["epoch"], df["val/box_loss"], label="val_box_loss") axes[0].set_xlabel("epoch") axes[0].set_ylabel("box_loss") axes[0].legend() axes[1].plot(df["epoch"], df["metrics/mAP50(B)"], label="mAP50") axes[1].plot(df["epoch"], df["metrics/mAP50-95(B)"], label="mAP50-95") axes[1].set_xlabel("epoch") axes[1].set_ylabel("mAP") axes[1].legend() plt.tight_layout() plt.savefig("training_curves.png", dpi=150)这段代码读results.csv,左图画训练和验证的 box loss,右图画 mAP50 和 mAP50-95。判断标准:两条 loss 曲线同步下降且趋于平缓,mAP 曲线上升后走平,说明训练正常。如果验证 loss 抬头而训练 loss 还在降,过拟合了,要么加数据要么加增强(degrees、translate、scale参数调大)。如果 mAP 从第一轮就平着不动,检查标注格式是不是错了,YOLO 格式的坐标必须归一化到 0~1。
注意:
results.csv的列名在不同 ultralytics 版本里可能有细微差异,比如metrics/mAP50(B)在某些版本里写成metrics/mAP_0.5。用df.columns先看一眼实际列名再改代码。
5. 部署到产线边缘设备:从 PyTorch 到 RK3588
5.1 为什么要导出 ONNX 和 RKNN
PyTorch 权重在服务器上跑没问题,但产线边缘盒子通常是瑞芯微 RK3588 这类 ARM 芯片,没有 CUDA,直接跑.pt推理慢到没法用。标准路径是:PyTorch → ONNX → RKNN。ONNX 是中间格式,RKNN 是瑞芯微 NPU 能加速的格式。
导出 ONNX:
yolo export model=weights/best.pt format=onnx imgsz=640 opset=12 simplify=Trueopset=12是 ONNX 算子集版本,RKNN 工具链对 12 支持最好。simplify=True会做图优化,去掉冗余算子。导出后在同目录得到best.onnx。
5.2 RK3588 部署的关键步骤
RK3588 上跑 YOLOv8 需要用到 rknn-toolkit2 做模型转换,rknn-toolkit-lite2 做板端推理。转换脚本核心逻辑:
from rknn.api import RKNN rknn = RKNN(verbose=True) rknn.config( mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform="rk3588" ) rknn.load_onnx(model="best.onnx") rknn.build(do_quantization=True, dataset="quant_dataset.txt") rknn.export_rknn("best.rknn") rknn.release()mean_values和std_values是归一化参数,YOLOv8 训练时输入是 0~1,所以这里除以 255。do_quantization=True开启量化,把 FP32 转成 INT8,速度能提两三倍,但精度会掉一两个点。quant_dataset.txt是量化校准集,里面每行是一张校准图片的路径,一般准备 100~200 张覆盖各种场景的图。
板端推理用 rknn-toolkit-lite2,加载best.rknn后调用inference接口,输出需要自己做后处理(解码边界框和 NMS)。这部分代码比较长,源码包里如果有deploy/rk3588/目录就直接用,没有的话参考 rknn_model_zoo 里的 YOLOv8 示例改。
5.3 部署后精度掉了怎么办
量化后 mAP 掉超过 3 个点,按这个顺序排查:校准集是不是太少或太单一,补到 200 张以上且覆盖不同光照和角度;do_quantization改成False先跑 FP16 看精度,确认是量化问题还是转换问题;检查预处理是否一致,训练时的 letterbox 填充在板端有没有做对,很多精度问题出在预处理不对齐。
6. 避坑与排查:瓶子检测落地时最容易翻车的五件事
6.1 现象:训练 mAP 很高但实际推理全是误检
原因:验证集和训练集来自同一批图片,分布太像,模型过拟合了。或者验证集里没有负样本(没有瓶子的图),模型没学会「什么不是瓶子」。
解决:重新划分数据集,确保训练集和验证集来自不同时间段或不同批次的图片。往验证集里加 10%~20% 的纯背景图,让模型学会抑制误检。
6.2 现象:小目标瓶子(如瓶盖)检测不到
原因:YOLOv8 默认下采样到 640 后,小目标在特征图上只剩几个像素,特征太弱。或者标注时瓶盖框太小,训练时被过滤了。
解决:推理时把imgsz提到 1280,小目标召回能明显提升,代价是速度减半。训练时开mosaic增强(默认开),让模型多见小目标拼接场景。如果还不行,换 YOLOv8m 或 YOLOv8l,大模型对小目标更友好。
6.3 现象:换了批次瓶子后精度骤降
原因:训练数据的光照、背景、瓶子颜色和实际产线不一致。模型学到了「背景特征」而不是「瓶子特征」。
解决:在产线上采集新批次的图,哪怕只标 50 张,混进训练集微调 20 个 epoch,精度能拉回来大半。长期方案是建立数据回流机制,每周把产线误检图捞出来标注后加入训练集。
6.4 现象:RK3588 上推理速度只有 5 FPS
原因:模型没量化,或者输入尺寸太大,或者 NPU 没被调用(跑在 CPU 上了)。
解决:确认do_quantization=True且校准集有效。imgsz从 640 降到 416 试试,速度能翻倍。用rknn.query确认模型跑在 NPU 上。如果还慢,检查是不是每个推理周期都在做内存拷贝,把输入输出 buffer 复用起来。
6.5 现象:results.csv 里 mAP 是 0 或者 NaN
原因:标注文件格式错误,最常见的是坐标没归一化(写成了像素值),或者类别索引从 1 开始(YOLO 要求从 0 开始)。
解决:打开一个 label 文件检查,每行应该是类别 中心x 中心y 宽 高,后四个值都在 0~1 之间。如果坐标是像素值,写个脚本除以图片宽高。如果类别从 1 开始,全部减 1。
7. 把评估指标用起来:从曲线反推模型短板
7.1 混淆矩阵告诉你哪个类别在拖后腿
confusion_matrix.png是排查类别问题的第一入口。横轴是预测类别,纵轴是真实类别,对角线越深越好。如果bottle_crack那一行大量落在bottle_ok列,说明裂纹被误判成正常,这是最危险的漏检。反过来如果bottle_ok大量落在bottle_crack,说明误检太多,产线会频繁报警。
针对混淆矩阵的调整策略:把混淆严重的两个类别样本单独拎出来看,通常是标注标准不一致导致的。比如有的裂纹标了,有的类似裂纹没标,模型就懵了。统一标注标准后重训,比调参管用。
7.2 PR 曲线和 F1 曲线定阈值
PR_curve.png里每条曲线对应一个类别,曲线下的面积就是该类别的 AP。如果某个类别的曲线明显靠下,说明这个类别难检,要么加样本要么单独调这个类别的损失权重。
F1_curve.png更实用,它直接告诉你最佳置信度阈值。曲线峰值对应的横坐标就是 F1 最大的conf值。比如峰值在 0.32,那你推理时conf就设 0.32 附近,不要拍脑袋设 0.5。
7.3 一个我常用的验证习惯
每次微调完模型,我不会只看 mAP 一个数。我会固定跑三组测试:一组是训练集里抽的图(看拟合程度),一组是验证集的图(看泛化),一组是产线新采的图(看真实表现)。三组 mAP 差距在 5 个点以内,我才认为模型可以上线。差距太大,说明数据分布有问题,回去补数据比调模型有用。
这个习惯帮我省了很多后悔药。曾经有一次验证集 mAP 0.96,上线后实际只有 0.7,就是因为验证集全是实验室拍的,产线光照完全不同。后来我把产线图按 7:2:1 混进训练、验证、测试,再也没出现过这种翻车。
希望帮到你。
本文还有配套的精品资源,点击获取