ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于YOLOv8的流水线产品质量检测系统:从训练到部署的完整方案

基于YOLOv8的流水线产品质量检测系统:从训练到部署的完整方案 简介这份资源是面向计算机、人工智能、自动化等专业学生与教师的YOLOv8流水线产品质量检测完整项目包可直接用于毕业设计、课程设计或大作业也适合作为目标检测入门进阶的实战案例。压缩包共97个文件约24.21MB以70个Python源码文件为核心辅以4个pt权重文件、5个xml配置、12个pyc缓存及txt说明、mp4演示视频等涵盖模型训练、推理检测、可视化界面与部署脚本结构完整。项目已跑通并附带数据集与部署说明可生成核心指标曲线、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图便于答辩展示与结果分析。目前已有33人学习下载读者可据此快速复现流水线质检流程理解YOLOv8训练与推理细节并在此基础上修改扩展功能。1. 流水线质检为什么盯上了 YOLOv8一套能跑起来的毕设方案长什么样工厂流水线上的质检工位本质上是一个高频二分类问题合格品放行缺陷品剔除。传统做法靠人眼盯一条线三班倒至少六个人漏检率还随疲劳度往上走。换成机器视觉方案核心诉求就三条——快、准、能落地。YOLOv8 之所以在这类场景里被反复提起是因为它在精度和推理速度之间给了一个足够好的平衡点而且 Ultralytics 这套框架把训练、验证、导出、推理的链路压得很短一个学生或者一个刚转视觉的工程师几天内就能从零跑到能演示的状态。这套「基于 YOLOv8 的流水线产品质量检测系统」要解决的就是把检测模型、数据集、可视化界面和部署流程打包成一个可复现的整体。适合谁做毕设的学生、做课程设计的同学、以及想快速验证产线缺陷检测可行性的工程师。它不追求工业级的高可用架构但追求一件事拿到源码和数据集之后能在自己的机器上把训练跑通、把界面点开、把检测结果看到。下面从环境、数据、训练、界面、部署几个环节拆开讲每一步都给到能抄的命令和参数。2. 环境配置与 YOLOv8 安装CPU 和 GPU 两条路怎么选2.1 先确认你的硬件和系统底座在动手之前先花两分钟确认三件事操作系统、显卡型号、Python 版本。这套方案最常见的运行环境是 Ubuntu 20.04 和 Windows 10/11Python 建议 3.8 到 3.10 之间太新的版本比如 3.12在部分依赖上会碰到编译问题。显卡方面如果你有 NVIDIA 的卡比如 GTX 1660 Ti、RTX 3060 这类可以走 GPU 路线训练速度会快很多如果没有独显或者只有核显走 CPU 路线也能跑只是训练时间要按小时甚至按天算。先看显卡和驱动状态# 查看显卡型号和驱动版本 nvidia-smi # 查看 CUDA 版本如果有 nvcc --version # 查看 Python 版本 python --versionnvidia-smi能正常输出表格说明驱动装好了右上角的 CUDA Version 是驱动支持的最高版本不是你当前装的版本。如果这条命令报「command not found」要么没装驱动要么是 CPU 环境直接走 CPU 路线即可。Python 版本用python --version确认如果系统里同时有 python 和 python3统一用 python3 来操作避免后面 pip 装错解释器。2.2 用 conda 建一个干净的环境不要在主环境里直接 pip install ultralytics依赖冲突是新手翻车的高发区。用 conda 建独立环境# 创建名为 yolo8 的环境指定 Python 3.9 conda create -n yolo8 python3.9 -y # 激活环境 conda activate yolo8 # 安装 PyTorchCPU 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 如果有 GPU 且 CUDA 版本是 11.8用这条 # pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118这里的关键参数是--index-url它决定了你装的是 CPU 版还是对应 CUDA 版本的 GPU 版。装完之后验证一下import torch print(torch.__version__) print(torch.cuda.is_available()) # GPU 环境应输出 True如果torch.cuda.is_available()返回 False但你有显卡大概率是 PyTorch 版本和 CUDA 版本不匹配回到上一步换对应的 index-url 重装。CPU 环境返回 False 是正常的不用管。2.3 安装 ultralytics 并验证# 安装 ultralytics pip install ultralytics # 验证安装会打印版本号 yolo versionyolo version能打印出版本号就说明装好了。如果报错检查是不是在 conda 环境里执行的以及 pip 是不是指向了当前环境的解释器。常见做法是用pip -V看一下 pip 的路径确认它在yolo8环境目录下。提示CPU 环境下训练小数据集几百到几千张图是可行的但要把 epochs 控制在 50 到 100 之间imgsz 用 640 或更小否则一个 epoch 可能要跑十几分钟。3. 数据集准备从原始图片到 YOLO 格式的完整转换3.1 流水线质检数据集长什么样流水线产品质量检测的数据集通常按缺陷类型分几类比如划痕、凹陷、脏污、变形加上合格品本身。标注格式上YOLOv8 用的是 YOLO 格式的 txt 文件每行一个目标格式是类别编号 中心点x 中心点y 宽度 高度这四个坐标值都是归一化到 0 到 1 之间的浮点数。比如一张 640x480 的图里有个缺陷框在 (100, 200) 到 (300, 400)那么中心点是 (200, 300)宽 200高 200归一化后就是0.3125 0.625 0.3125 0.4167。数据集目录结构建议这样组织dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml是数据集配置文件内容如下# 数据集路径建议用绝对路径避免找不到 path: /home/user/dataset train: images/train val: images/val # 类别数量 nc: 4 # 类别名称顺序要和标注时的编号对应 names: 0: scratch 1: dent 2: stain 3: deformnc是类别数names里的编号从 0 开始必须和标注文件里的类别编号严格对应。顺序错了模型学出来的类别就是乱的这是血泪经验里最常见的一类问题。3.2 用 labelme 标注后转 YOLO 格式如果你手头的数据是用 labelme 标的输出 json需要转成 YOLO 的 txt。常见做法是写一个转换脚本import json import os from PIL import Image def labelme_to_yolo(json_dir, output_dir, class_map): json_dir: labelme json 文件目录 output_dir: 输出 txt 目录 class_map: 类别名到编号的映射如 {scratch: 0, dent: 1} os.makedirs(output_dir, exist_okTrue) for filename in os.listdir(json_dir): if not filename.endswith(.json): continue with open(os.path.join(json_dir, filename), r, encodingutf-8) as f: data json.load(f) # 读取图片尺寸 img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue cls_id class_map[label] points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] # 计算边界框 x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 归一化中心点和宽高 cx (x_min x_max) / 2 / img_w cy (y_min y_max) / 2 / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) # 写出同名 txt txt_name os.path.splitext(filename)[0] .txt with open(os.path.join(output_dir, txt_name), w) as f: f.write(\n.join(lines)) # 调用示例 labelme_to_yolo( json_dirraw_json, output_dirdataset/labels/train, class_map{scratch: 0, dent: 1, stain: 2, deform: 3} )这段脚本的核心逻辑是读 json 里的多边形点取外接矩形再归一化。class_map必须和data.yaml里的names一致。转换完之后建议随机抽几张图用可视化脚本检查一下框的位置对不对别等到训练完才发现标注全偏了。3.3 数据集划分和检查训练集和验证集一般按 8:2 或 7:3 划分。划分脚本很简单但要注意图片和标签必须同名同目录结构import os import random import shutil def split_dataset(img_dir, label_dir, out_dir, ratio0.8): 按比例划分训练集和验证集 img_dir: 原始图片目录 label_dir: 原始标签目录 out_dir: 输出根目录 ratio: 训练集比例 images [f for f in os.listdir(img_dir) if f.endswith((.jpg, .png))] random.shuffle(images) split_idx int(len(images) * ratio) train_imgs images[:split_idx] val_imgs images[split_idx:] for subset, files in [(train, train_imgs), (val, val_imgs)]: img_out os.path.join(out_dir, images, subset) lbl_out os.path.join(out_dir, labels, subset) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for f in files: shutil.copy(os.path.join(img_dir, f), os.path.join(img_out, f)) # 对应的标签文件 lbl_name os.path.splitext(f)[0] .txt lbl_src os.path.join(label_dir, lbl_name) if os.path.exists(lbl_src): shutil.copy(lbl_src, os.path.join(lbl_out, lbl_name)) split_dataset(raw_images, raw_labels, dataset, ratio0.8)划分完之后检查一下有没有图片没有对应标签、或者标签是空文件的情况。空标签文件在 YOLOv8 里会被当成负样本如果数量太多会影响训练效果。注意数据集里如果有大量无缺陷的合格品图片不要全部删掉保留一部分作为负样本有助于降低误检率但比例不要超过总样本的 20%。4. 训练自己的流水线缺陷检测模型参数怎么设、曲线怎么看4.1 启动训练的最小命令YOLOv8 的训练入口非常简洁一条命令就能跑yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/train \ nameexp1逐个参数说明data指向数据集配置文件model是预训练权重yolov8n.pt是最小的 nano 版本适合快速验证如果精度不够可以换yolov8s.pt或yolov8m.ptepochs是训练轮数小数据集 100 轮通常够用imgsz是输入尺寸640 是默认值如果缺陷目标很小可以提到 1280但显存占用会翻倍batch是批大小显存不够就往下调8 或 4 都行device0表示用第一块 GPUCPU 环境改成devicecpu。4.2 关键参数怎么调训练效果不好八成是这几个参数没设对参数作用建议值调整方向lr0初始学习率0.01不收敛就降到 0.001patience早停轮数50过拟合就减小conf置信度阈值0.25漏检多就降低iouNMS 的 IoU 阈值0.7重叠框多就降低mosaic马赛克增强1.0小目标多就保持lr0是最容易出问题的参数。默认 0.01 对大多数场景够用但如果你的数据集很小几百张学习率太大会导致 loss 震荡不下降这时候降到 0.001 再试。patience控制的是多少轮没有提升就停止训练设 50 意味着连续 50 轮验证指标不涨就停能省时间。4.3 看损失曲线判断训练状态训练过程中会在runs/train/exp1/下生成results.csv和损失曲线图。重点看三条线train/box_loss、val/box_loss、metrics/mAP50。如果train/box_loss持续下降但val/box_loss开始上升说明过拟合了解决办法是增加数据增强、减少 epochs、或者加 dropout。如果两条 loss 都不降检查学习率是不是太大、标注是不是有问题。mAP50是验证集上的平均精度正常情况应该随着训练轮数上升并逐渐趋于平稳。import pandas as pd import matplotlib.pyplot as plt # 读取训练日志 df pd.read_csv(runs/train/exp1/results.csv) df.columns df.columns.str.strip() # 去掉列名空格 # 画损失曲线 plt.figure(figsize(10, 5)) plt.plot(df[epoch], df[train/box_loss], labeltrain_box_loss) plt.plot(df[epoch], df[val/box_loss], labelval_box_loss) plt.xlabel(Epoch) plt.ylabel(Loss) plt.legend() plt.savefig(loss_curve.png)这段脚本把results.csv里的损失值画出来比在终端里看数字直观得多。如果曲线抖动特别厉害可以开plotsTrue让 YOLOv8 自动生成平滑后的曲线图。4.4 用训练好的模型做推理训练完成后权重保存在runs/train/exp1/weights/best.pt。用这个权重做单张图片推理yolo detect predict \ modelruns/train/exp1/weights/best.pt \ sourcetest_images/ \ conf0.25 \ saveTruesource可以是单张图、一个目录、甚至一段视频。conf0.25是置信度阈值低于这个值的检测框会被过滤掉。如果发现漏检多把 conf 降到 0.1 试试如果误检多提到 0.5。结果默认保存在runs/detect/predict/下。5. 可视化界面与部署从脚本到能演示的系统5.1 用 Gradio 快速搭一个检测界面毕设和课程设计通常需要一个能点开的界面Gradio 是最省事的方案几十行代码就能搞定import gradio as gr from ultralytics import YOLO from PIL import Image import numpy as np # 加载训练好的模型 model YOLO(runs/train/exp1/weights/best.pt) def detect(image): 接收 PIL 图片返回带检测框的图片和统计信息 if image is None: return None, 请上传图片 # 推理 results model(image, conf0.25) # 绘制结果 annotated results[0].plot() # 统计各类别数量 boxes results[0].boxes cls_names results[0].names counts {} for cls_id in boxes.cls.tolist(): name cls_names[int(cls_id)] counts[name] counts.get(name, 0) 1 info 检测结果\n \n.join([f{k}: {v} 个 for k, v in counts.items()]) if not counts: info 未检测到缺陷 return annotated, info # 构建界面 demo gr.Interface( fndetect, inputsgr.Image(typepil, label上传产品图片), outputs[ gr.Image(label检测结果), gr.Textbox(label缺陷统计) ], title流水线产品质量检测系统, description上传产品图片自动检测缺陷类型和数量 ) demo.launch(server_name0.0.0.0, server_port7860)gr.Interface把输入输出直接映射到函数上detect函数里调用 YOLO 模型推理results[0].plot()返回带框的 numpy 数组Gradio 会自动渲染。server_name0.0.0.0让局域网内其他设备也能访问方便演示时用手机或另一台电脑打开。5.2 部署到服务器或本地机器的注意事项如果要在 Ubuntu 服务器上长期运行建议用nohup或者screen把进程挂后台# 后台运行日志输出到 app.log nohup python app.py app.log 21 # 查看进程 ps aux | grep app.py # 停止进程 kill PID端口被占用的话改server_port参数即可。如果服务器有防火墙记得放行对应端口。CPU 环境下推理速度大概每张图几百毫秒到一两秒GPU 环境下能压到几十毫秒演示时建议用 GPU 机器或者提前准备好结果图。提示Gradio 默认会在127.0.0.1上启动外部访问不了。加server_name0.0.0.0才能从其他机器访问这是部署时最常踩的坑。6. 避坑与排查训练和部署中最容易翻车的五个点6.1 报错「No labels found」——路径或格式问题现象训练启动后提示找不到标签或者 mAP 一直是 0。原因通常是data.yaml里的路径写错了或者标签文件不是 YOLO 格式。解决先用ls dataset/labels/train/ | head确认标签文件存在再打开一个 txt 看内容是不是类别 x y w h的格式。如果是 labelme 的 json 没转换回到第 3 章的转换脚本重新跑一遍。6.2 训练 loss 不下降——学习率或标注问题现象跑了几十轮train/box_loss一直在 1.0 以上震荡。原因有两个学习率太大或者标注框位置严重偏移。解决先把lr0从 0.01 降到 0.001 试 20 轮如果还是不降用可视化脚本把标注框画到原图上检查大概率是归一化算错了或者坐标顺序搞反了。6.3 显存不足「CUDA out of memory」——batch 和 imgsz 太大现象训练刚开始就报显存错误。原因batch或imgsz超过了显卡承载能力。解决先把batch减半比如从 16 降到 8还不够就把imgsz从 640 降到 416。另外可以开ampTrue用混合精度训练能省不少显存。6.4 界面能打开但检测没反应——模型路径或输入格式问题现象Gradio 界面正常显示上传图片后一直转圈或者返回空。原因模型路径写错或者输入图片格式不是 PIL 能识别的。解决在detect函数里加一行print(image.size)确认图片读进来了再确认YOLO(...)的路径是绝对路径或相对于启动目录的正确路径。相对路径在换目录启动时会失效建议统一用绝对路径。6.5 部署后外部访问不了——绑定地址或防火墙现象本机localhost:7860能打开同事的电脑打不开。原因Gradio 默认绑定127.0.0.1只监听本机。解决demo.launch(server_name0.0.0.0, server_port7860)然后确认服务器防火墙放行了 7860 端口。如果是云服务器还要检查安全组规则。7. 把模型导出成 ONNX 再部署一个能提速的进阶技巧训练和演示跑通之后如果你想让推理再快一点或者想把模型嵌到别的语言写的系统里导出 ONNX 是最常见的一步。YOLOv8 自带导出命令yolo export \ modelruns/train/exp1/weights/best.pt \ formatonnx \ imgsz640 \ simplifyTrue \ opset12formatonnx指定导出格式simplifyTrue会对计算图做简化opset12是 ONNX 的算子集版本兼容性比较好。导出完成后会在同目录下生成best.onnx。用 ONNX Runtime 推理的代码大概长这样import onnxruntime as ort import numpy as np import cv2 # 加载 ONNX 模型 session ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) def preprocess(image_path, imgsz640): 读取图片并做 letterbox 预处理 img cv2.imread(image_path) h, w img.shape[:2] scale min(imgsz / w, imgsz / h) new_w, new_h int(w * scale), int(h * scale) resized cv2.resize(img, (new_w, new_h)) # 填充到正方形 canvas np.full((imgsz, imgsz, 3), 114, dtypenp.uint8) canvas[:new_h, :new_w] resized # 转成 NCHW 格式并归一化 blob canvas[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 blob np.expand_dims(blob, axis0) return blob, scale # 推理 blob, scale preprocess(test.jpg) outputs session.run(None, {session.get_inputs()[0].name: blob}) print(outputs[0].shape) # 输出形状通常是 [1, 4nc, 8400]ONNX 推理比 PyTorch 原生推理在 CPU 上通常快 20% 到 50%具体取决于模型大小和硬件。导出时如果报算子不支持把opset降到 11 再试。另外注意ONNX 模型的输出是原始张量后处理NMS、坐标还原需要自己写不像 Ultralytics 那样直接返回带框的结果。如果你只是做演示用 PyTorch 权重就够了如果要嵌到 C 或者边缘设备上ONNX 是绕不开的一步。我自己在这个环节踩过的坑是导出时忘了加simplifyTrue结果 ONNX 图里多了一堆冗余节点推理速度反而比 PyTorch 还慢。后来养成习惯导出后先用onnxsim检查一遍确认图是干净的就基本没问题。另一个习惯是每次训练完先把best.pt和last.pt都备份一份别问为什么问就是后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表