资讯详情

资讯详情

基于YOLOv8的瓶子识别检测系统:从源码到产线部署实战

简介本资源面向深度学习目标检测初学者与需要落地瓶子识别项目的开发者提供一套基于YOLOv8的完整检测系统源码覆盖环境搭建、模型训练、推理测试全流程平均准确率达0.95类别为bottle。压缩包共488个文件约89.27MB以173个md说明文档、115个py脚本、41个yaml配置、91个pyc缓存及5个pt权重文件为主另含少量jpg、png、xml、sh、cpp等辅助文件结构清晰便于按模块查阅。资源内含ultralytics-main官方源码涵盖分类、检测、姿态估计与分割四部分实际使用detect目标检测模块并附带训练好的模型与各项评估指标曲线可直接复现或迁移到其他物品检测任务。目前已有2653人学习下载适合希望快速掌握YOLOv8训练与部署、对照指标曲线调优模型的中高级学习者参考。1. 瓶子识别检测系统从一份源码包到能跑起来的产线级方案你拿到一个压缩包名字叫「基于YOLOv8的各种瓶子识别检测系统源码」里面塞着训练好的权重、部署教程和评估曲线。真正要回答的问题不是「YOLOv8 是什么」而是这套东西能不能直接用在分拣线、回收站或者饮料灌装质检上我该从哪一步开始动手。瓶子识别这个场景看着简单实际难点集中在材质反光、瓶型差异大、遮挡堆叠和产线速度上。塑料透明瓶在强光下几乎和背景融为一体玻璃瓶又容易产生高光斑PET 瓶身还有形变。这套源码的价值在于它已经把数据标注、训练配置、评估指标和推理脚本串成了一条链路你不需要从零搭。适合两类人一类是想快速验证瓶子检测可行性的算法工程师另一类是需要在边缘设备上落地分拣系统的嵌入式开发者。下面按「先看懂它给了什么、再跑通训练、再部署到实际硬件、最后调优」的顺序拆开讲。2. 拆开源码包目录结构、模型选型与评估指标怎么读2.1 拿到压缩包先看什么目录树与文件职责解压之后不要急着跑命令先花十分钟把目录结构摸清楚。常见的组织方式是这样bottle_detection/ ├── datasets/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── bottle.yaml ├── weights/ │ ├── best.pt │ └── last.pt ├── runs/ │ └── detect/ │ └── train/ │ ├── results.csv │ ├── confusion_matrix.png │ ├── PR_curve.png │ └── weights/ ├── train.py ├── predict.py ├── export.py └── requirements.txtdatasets/bottle.yaml是数据集的配置文件里面定义了训练集、验证集、测试集路径和类别名称。weights/best.pt是训练好的权重文件直接拿来做推理。runs/detect/train/下面是训练过程产出的所有评估图表。train.py、predict.py、export.py分别是训练、推理和模型导出脚本。提示如果bottle.yaml里的路径写的是绝对路径换一台机器就会报FileNotFoundError先改成相对路径再跑。2.2 模型选型为什么是 YOLOv8n 而不是 YOLOv8x源码包里通常默认用 YOLOv8nnano或者 YOLOv8ssmall。这不是随便选的。瓶子检测在产线上的典型要求是实时性优先30 FPS 以上才能跟上传送带速度。YOLOv8n 在 RTX 3060 上推理一张 640×640 图片大约 2-3msYOLOv8x 要 15ms 以上。精度方面瓶子属于大目标且形状相对固定nano 模型的 mAP 通常只比 x 版本低 2-4 个百分点但速度快 5 倍以上。模型参数量mAP0.5瓶子数据集推理速度RTX 3060适用场景YOLOv8n3.2M0.892.5ms边缘设备、高帧率产线YOLOv8s11.2M0.925ms服务器端、精度优先YOLOv8m25.9M0.9412ms离线质检YOLOv8x68.2M0.9518ms科研对比如果你要部署到 RK3588 这类 NPU 设备上nano 版本几乎是唯一选择因为 NPU 的算力有限大模型跑不动。GTX 1660 Ti 这种 6GB 显存的卡训练时用 YOLOv8n 可以开 batch16用 YOLOv8m 只能开 batch4。2.3 评估指标曲线怎么读别只看 mAPruns/detect/train/目录下的results.csv记录了每个 epoch 的损失和指标。重点看四个train/box_loss 和 val/box_loss训练损失持续下降但验证损失开始上升说明过拟合了需要加数据增强或减模型复杂度。metrics/mAP0.5IoU 阈值 0.5 时的平均精度瓶子检测一般能到 0.90 以上。metrics/mAP0.5:0.95更严格的指标如果这个值明显低于 mAP0.5说明定位精度不够可能是标注框不够紧。PR_curve.png查全率和查准率的权衡曲线。产线上如果漏检代价高就把置信度阈值调低如果误检代价高就调高。import pandas as pd import matplotlib.pyplot as plt # 读取训练日志 df pd.read_csv(runs/detect/train/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], labeltrain_box_loss) axes[0].plot(df[epoch], df[val/box_loss], labelval_box_loss) axes[0].set_xlabel(Epoch) axes[0].set_ylabel(Box Loss) axes[0].legend() # 画 mAP 曲线 axes[1].plot(df[epoch], df[metrics/mAP50(B)], labelmAP0.5) axes[1].plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP0.5:0.95) axes[1].set_xlabel(Epoch) axes[1].set_ylabel(mAP) axes[1].legend() plt.tight_layout() plt.savefig(training_curves.png, dpi150)这段代码把results.csv里的损失和 mAP 画成曲线图。df.columns.str.strip()是必须的因为 YOLOv8 输出的列名有时带空格直接索引会报 KeyError。画图的目的不是好看是判断训练有没有收敛。如果 50 个 epoch 之后 val_box_loss 还在震荡说明学习率太大或者 batch size 太小。3. 从零跑通训练环境配置、数据准备与训练命令3.1 环境配置CUDA、PyTorch 和 ultralytics 的版本对齐环境配置是第一个翻车高发区。YOLOv8 依赖 ultralytics 包而 ultralytics 对 PyTorch 版本有要求。截至我写这篇的时候稳定组合是 Python 3.9-3.10、PyTorch 2.0、CUDA 11.8 或 12.1。# 创建虚拟环境 conda create -n bottle_yolo python3.10 -y conda activate bottle_yolo # 安装 PyTorch以 CUDA 11.8 为例 pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics pip install ultralytics8.1.0 # 验证 GPU 是否可用 python -c import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))如果torch.cuda.is_available()返回 False先检查显卡驱动版本。nvidia-smi显示的 CUDA Version 是驱动支持的最高版本不是你安装的版本。驱动版本低于 470 的话CUDA 11.8 跑不起来要么升级驱动要么降级到 CUDA 11.3 对应的 PyTorch。注意不要用pip install ultralytics不带版本号最新版可能引入不兼容的改动。源码包里如果有requirements.txt优先按里面的版本装。3.2 数据集准备标注格式转换与 bottle.yaml 配置源码包里的数据集通常已经是 YOLO 格式每张图片对应一个.txt标注文件每行是class_id x_center y_center width height坐标都归一化到 0-1。如果你自己标注的数据是 VOC 的 XML 格式需要转换import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_dir, output_dir, classes): 将 VOC XML 标注转换为 YOLO txt 格式 if not os.path.exists(output_dir): os.makedirs(output_dir) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 获取图片尺寸 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 转换为归一化的中心点坐标和宽高 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) # 写入同名 txt 文件 txt_name xml_file.replace(.xml, .txt) with open(os.path.join(output_dir, txt_name), w) as f: f.write(\n.join(lines)) # 使用示例 classes [plastic_bottle, glass_bottle, can, carton] voc_to_yolo(./annotations/xml, ./labels/train, classes)转换逻辑的核心是坐标归一化。VOC 用的是左上角和右下角的绝对像素坐标YOLO 用的是中心点加宽高的相对坐标。x_center (xmin xmax) / 2.0 / img_w这一步如果忘了除以图片宽度训练时损失会直接爆炸。classes列表的顺序必须和bottle.yaml里的names完全一致否则类别会错位。bottle.yaml的典型内容path: ./datasets train: images/train val: images/val test: images/test nc: 4 names: 0: plastic_bottle 1: glass_bottle 2: can 3: cartonnc是类别数names是类别名称映射。如果你的数据集只有塑料瓶和玻璃瓶两类nc改成 2names只保留前两个。3.3 训练命令与关键参数epochs、batch、imgsz 怎么定yolo detect train \ datadatasets/bottle.yaml \ modelyolov8n.pt \ epochs100 \ batch16 \ imgsz640 \ lr00.01 \ patience20 \ device0 \ projectruns/detect \ namebottle_train逐项说明modelyolov8n.pt从预训练权重开始不要用yolov8n.yaml从零初始化除非你的数据集超过 10 万张。epochs100瓶子检测数据集通常 2000-5000 张100 个 epoch 足够收敛。如果验证集 mAP 在 60 个 epoch 后不再提升patience20会提前停止。batch166GB 显存用 168GB 用 3212GB 以上用 64。显存不够就减 batch不要减 imgsz。imgsz640瓶子在图片中的占比如果很小比如监控视角可以提到 1280但推理速度会下降 3-4 倍。lr00.01初始学习率。如果训练损失前几个 epoch 就飙到 nan降到 0.001。device0指定第一块 GPU。多卡用device0,1。训练过程中打开runs/detect/bottle_train/results.csv实时观察。如果val/box_loss在前 10 个 epoch 就停止下降检查标注文件是不是有大量空文件或者坐标越界。4. 部署落地ONNX 导出、RK3588 适配与推理加速4.1 导出 ONNX 与 TensorRT格式选择与精度损失训练完的.pt文件不能直接上产线需要转成推理引擎格式。常见的有 ONNX、TensorRT、OpenVINO。# 导出 ONNX yolo export modelruns/detect/bottle_train/weights/best.pt formatonnx opset12 simplifyTrue # 导出 TensorRT需要 NVIDIA GPU yolo export modelruns/detect/bottle_train/weights/best.pt formatengine halfTrue device0opset12是兼容性最好的版本RK3588 的 NPU 工具链对 opset 12 支持最完整。simplifyTrue会调用 onnx-simplifier 去掉冗余节点减小模型体积。halfTrue启用 FP16 量化精度损失通常在 0.5% 以内速度提升 30-50%。注意导出 TensorRT 时如果报AssertionError: Torch not compiled with CUDA enabled说明 PyTorch 装的是 CPU 版本重新安装 GPU 版本。4.2 RK3588 部署模型转换与 NPU 推理RK3588 的 NPU 算力是 6 TOPS跑 YOLOv8n 可以到 30 FPS 以上。部署流程是ONNX → RKNN → NPU 推理。from rknn.api import RKNN # 创建 RKNN 对象 rknn RKNN(verboseTrue) # 配置模型参数 rknn.config( mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588, quantized_dtypeasymmetric_quantized-8 ) # 加载 ONNX 模型 ret rknn.load_onnx(modelbest.onnx) if ret ! 0: print(Load ONNX failed) exit(ret) # 构建 RKNN 模型 ret rknn.build(do_quantizationTrue, dataset./quant_dataset.txt) if ret ! 0: print(Build RKNN failed) exit(ret) # 导出 RKNN 模型 ret rknn.export_rknn(./best.rknn) rknn.release()mean_values和std_values必须和训练时的预处理一致。YOLOv8 默认是0-1归一化所以 mean 是 0std 是 255。do_quantizationTrue启用 INT8 量化需要一个量化校准数据集quant_dataset.txt里面是 100-200 张训练图片的路径。量化后精度可能掉 1-3 个百分点如果掉太多改用quantized_dtypedynamic_fixed_point-16做 FP16 量化。4.3 推理脚本从图片到检测结果的完整链路from ultralytics import YOLO import cv2 # 加载模型 model YOLO(runs/detect/bottle_train/weights/best.pt) # 单张图片推理 results model.predict( sourcetest_bottle.jpg, conf0.25, iou0.45, imgsz640, device0 ) # 解析结果 for r in results: boxes r.boxes for box in boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) x1, y1, x2, y2 box.xyxy[0].tolist() print(f类别: {model.names[cls_id]}, 置信度: {conf:.2f}, 位置: ({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f})) # 视频流推理 cap cv2.VideoCapture(0) while cap.isOpened(): ret, frame cap.read() if not ret: break results model.predict(frame, conf0.25, verboseFalse) annotated results[0].plot() cv2.imshow(Bottle Detection, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()conf0.25是置信度阈值低于这个值的检测框会被丢弃。产线上如果漏检代价高降到 0.15如果误检多提到 0.4。iou0.45是 NMS 的 IoU 阈值瓶子堆叠严重时调低到 0.3避免相邻瓶子被合并成一个框。results[0].plot()直接在原图上画框和标签适合快速验证。5. 避坑与排查瓶子检测训练部署中最容易翻车的 5 个点5.1 现象训练损失正常下降但 mAP 始终为 0原因标注文件的类别 ID 从 1 开始而 YOLO 要求从 0 开始。或者bottle.yaml里的names顺序和标注文件里的 ID 不对应。解决打开任意一个标注.txt文件确认第一列的数字范围是0到nc-1。如果是1到nc写个脚本把所有 ID 减 1。5.2 现象推理时所有瓶子都被检测成同一个类别原因数据集中某一类别的样本数量远超其他类别模型倾向于把所有目标预测为多数类。解决检查每个类别的图片数量。如果塑料瓶有 3000 张而玻璃瓶只有 200 张对少数类做过采样或者在训练时用cls0.5降低分类损失的权重。5.3 现象RK3588 上推理结果全是乱框原因量化校准数据集和训练数据分布不一致。比如校准集用的是实验室光照图片而实际产线是强光环境。解决从实际部署场景中采集 200 张图片做校准集覆盖不同光照、角度和瓶子类型。量化时加do_quantizationTrue之前先用rknn.build(do_quantizationFalse)跑一遍确认浮点模型结果正常再开量化。5.4 现象训练到一半报 CUDA out of memory原因batch size 太大或者imgsz设得太高。YOLOv8 在 640 分辨率下 batch16 大约占 4GB 显存1280 分辨率下同样 batch 要 12GB 以上。解决先把 batch 减半如果还报错就把imgsz降到 512。另外检查workers参数默认是 8设成 4 可以减少内存占用。5.5 现象导出的 ONNX 模型推理结果和 PyTorch 不一致原因预处理方式不同。PyTorch 推理时 ultralytics 自动做了 letterbox 填充而 ONNX 推理时如果直接 resize 会改变宽高比。解决在 ONNX 推理脚本里手动实现 letterbox保持和训练时一致的填充逻辑。或者直接用 ultralytics 的YOLO(best.onnx)加载它会自动处理预处理。6. 进阶技巧用 SAHI 切片推理提升小目标瓶子检出率产线监控视角下瓶子在 1080P 画面里可能只占 30×60 像素直接 resize 到 640 后只剩 18×36 像素YOLOv8n 的 P3 特征图80×80勉强能覆盖但召回率会明显下降。我一般会用 SAHISlicing Aided Hyper Inference做切片推理把大图切成 640×640 的小块每块单独推理再合并结果。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction # 加载模型 detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/detect/bottle_train/weights/best.pt, confidence_threshold0.25, devicecuda:0 ) # 切片推理 result get_sliced_prediction( high_res_production_line.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 ) # 导出结果 result.export_visuals(export_dir./sahi_output/) print(f检测到 {len(result.object_prediction_list)} 个目标)slice_height和slice_width设成和训练分辨率一致。overlap_height_ratio0.2表示相邻切片有 20% 重叠防止瓶子被切在边界上导致漏检。这个方法的代价是推理时间线性增加——一张 4K 图切成 12 块耗时是单次推理的 12 倍。所以只建议在离线质检或者低帧率场景用实时产线还是老老实实优化模型输入分辨率。另一个技巧是测试时增强TTA。推理时把图片水平翻转、多尺度缩放各跑一遍把结果做 NMS 融合。YOLOv8 内置了augmentTrue参数results model.predict(sourcetest.jpg, augmentTrue, conf0.25)开启 TTA 后 mAP 通常能涨 1-2 个百分点但推理速度慢 3 倍。如果产线帧率要求是 15 FPS 以上不建议开。验证模型有没有真正学到瓶子特征而不是记住了背景有个简单办法把测试集里的瓶子抠出来贴到纯色背景上再推理。如果检测框还在说明模型关注的是瓶子本身如果检测不到了说明模型过拟合了训练集的背景。这个测试我每次交付前都会跑一遍翻车过两次之后就成了固定习惯。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →