基于YOLOv8与PySide6的PCB缺陷检测系统实战

基于YOLOv8与PySide6的PCB缺陷检测系统实战
用YOLOv8/YOLOv5做PCB印制板缺陷检测再用PySide6套一个桌面界面是很多做视觉检测的人会走的完整路线。它解决的问题不是把模型训练出来就结束而是让检测能力变成现场人员真正能用的工具。这篇文章适合刚入门YOLO、准备做检测小系统或者需要给实验室和产线交付一个PCB缺陷识别工具的人。下面按实际落地顺序拆环境准备、数据集、模型训练、PySide6界面、批量检测、常见报错排查和优化方向。我不会一上来就讲界面有多炫先花精力把“单张图片能稳定检测出来”这件事跑通再谈界面和批量。PCB缺陷检测尤其不能只看能不能跑还要看小缺陷漏检、光照变化、数据分布一致性和阈值设置这些实际问题。1. 先说清楚这套方案解决什么问题和直接跑YOLO有什么区别1.1 PCB缺陷检测到底在检什么PCB印制板在生产过程中会出现多种表面缺陷常见的有缺孔应该钻孔的位置没有钻透或漏钻。鼠咬铜箔边缘出现不规则的缺口。开路印刷线路断开电流无法通过。短路相邻线路之间不该连接的地方连在了一起。毛刺铜箔边缘出现细小凸起。余铜应该被刻蚀掉的铜箔残留下来。除了这些实际产线上还会有划伤、铜渣、异物、错位、孔偏等情况。缺陷形态差异很大而且往往是小目标。一块PCB上有大量细线、焊盘和过孔缺陷占比小背景纹理又很复杂这就导致传统机器视觉方案很难用一套固定规则覆盖所有情况。用YOLO这类目标检测模型核心思路是让模型自己学习“正常区域”和“缺陷区域”的区别。训练好之后输入一张PCB图片模型输出每个缺陷的位置、类别和置信度。相比传统的阈值分割和模板匹配YOLO对光照、角度、形态变化的容忍度更高后续维护也相对简单。1.2 为什么要加PySide6做图形界面模型训练好之后如果只用命令行推理开发阶段问题不大。但实际使用场景中操作的人可能是质检员、产线技术员不是写代码的人。这时候就需要一个图形界面打开软件选择模型拖入图片看到检测框和缺陷类别点导出保存结果。PySide6是Qt for Python的正式版本控件丰富跨平台和OpenCV处理后的图像数据衔接也比较方便。用它做这个项目不需要引入很重的前后端框架单机桌面工具完全够用。界面要解决的事情很明确加载训练好的检测权重。打开一张图片或整个文件夹。显示检测结果包括类别、置信度、目标框。调节置信度阈值和IoU阈值。导出标注图和结果表。1.3 系统整体流程整个项目可以拆成两条线第一条是模型训练线采集或下载图片 - 标注 - 划分数据集 - 训练YOLOv5或YOLOv8 - 验证指标 - 导出权重。第二条是桌面应用线加载权重 - 读取图片 - 推理 - 绘制检测框 - 展示给用户 - 导出结果。两条线通过一个模型文件连接。训练阶段关注的是数据质量和模型指标界面阶段关注的是用户体验、批量处理稳定性和参数可调节性。不要把两条线混在一起否则调试会很乱。2. 开始前准备环境、依赖和硬件条件2.1 开发环境与依赖推荐使用Python 3.9或3.10Windows和Linux都可以。PySide6是跨平台的训练部分如果在GPU上跑Windows下也能正常使用。如果是纯Python环境管理不太好建议先用venv或conda建一个独立环境不要直接装在系统Python里。基础依赖包括pip install ultralytics pyside6 opencv-python pillow numpy如果只需要YOLOv5也可以安装YOLOv5的requirements但这里使用ultralytics包对YOLOv8和部分YOLOv5模型都更省事。安装完成后先检查一下是不是都能导入import ultralytics from PySide6.QtWidgets import QApplication import cv2 print(ultralytics.__version__)这里能正常输出说明基础环境没问题。之后安装PyTorch时建议先确认CUDA是否可用。如果只是CPU版也能跑但训练和推理都会慢一些。2.2 硬件与推理性能的判断标准很多人问“GTX 1660Ti能不能跑YOLOv8”答案是能但要看怎么跑。做推理完全没问题训练时建议选择YOLOv8n或YOLOv8s这种小模型输入分辨率控制在640batch不要开太大。这里给一个比较保守的判断标准硬件条件适合做什么需要注意什么4GB以下显存推理为主小模型训练训练时batch要很小尽量用yolov8n8GB左右显存yolov8n/s训练批量推理batch可以从8开始OOM就减半16GB及以上显存尝试更大模型、更高分辨率硬件条件更宽松但也不要无脑开大参数纯CPU单张图片推理界面调试跑批量会很慢不建议训练大模型判断性能不能只看显存还要看单张推理耗时和训练一个epoch的时间。我一般会先跑一张图记录推理耗时再跑20张图连续测试看内存有没有持续上涨、有没有中间卡死。如果只是单张图片能跑通不代表批量任务稳定。2.3 数据集准备用公开数据集还是自建数据如果只是学习流程可以直接使用公开的PCB缺陷检测数据集。这类数据集里面通常已经有标注好的图片类别包括缺孔、鼠咬、开路、短路、毛刺、余铜等直接拿来训练可以快速验证整个链路。如果目标是给实际产线用就必须自己采集数据。原因是每个工厂的PCB板、打光方式、相机角度、传送速度都不一样通用数据集很难覆盖真实场景。采集图片时要注意使用和产线一致的光源和相机。多收集缺陷样本尤其是小缺陷和边缘缺陷。保存原始大图不要一开始就压缩。让质检人员参与标注明确哪些是缺陷哪些是正常纹理。标注工具可以选择labelImg或者labelme输出YOLO格式的txt文件也可以。每个txt文件里一行代表一个目标格式是类别id 中心点x 中心点y 宽度 高度。坐标是归一化后的范围在0到1之间。3. 模型训练YOLOv5 / YOLOv8 的选择、配置与训练3.1 选YOLOv8还是YOLOv5这个项目标题里同时出现了YOLOv8和YOLOv5实际使用时选一个就好。YOLOv8的优点是API统一使用ultralytics包就可以完成训练、验证、导出和推理模型结构上有改进各种复杂度的模型都有新项目用起来比较顺手。YOLOv5的优点是社区资料多很多老项目用的都是v5网上能找到大量部署和优化方案。如果你的目标是把项目接入已有v5环境继续用v5也完全合理。我的建议是如果你是新开始直接选YOLOv8如果你手头已经有YOLOv5的代码、数据管道和部署环境就没有必要迁移。模型的效果差距没有大到必须换的程度真正影响结果的是数据质量和调参。3.2 数据目录和配置文件YOLO训练时对目录结构有约定推荐下面这种datasets/ ├── PCB/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/图片放在images目录标注文件放在labels目录文件名必须一一对应。比如图片叫001.jpg标注文件就叫001.txt。还需要一个数据配置文件比如pcb.yamlpath: ./datasets/PCB train: images/train val: images/val nc: 6 names: - missing_hole - mouse_bite - open_circuit - short - spur - copper这里nc是类别数names是类别名称列表。类别id必须从0开始和标注txt里写的第一个数字一致。如果类别顺序乱了训练不会成功但检测结果会完全错位。3.3 训练流程与关键参数先下载预训练权重可以直接用模型自带的yolo detect train datapcb.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0如果你用的是YOLOv5命令大概是python train.py --data pcb.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --img 640下面这几个参数最需要理解参数作用建议model决定模型结构n/s/m/l/x代表从小到大新项目从n或s开始epochs训练轮数小数据集100轮左右重点看曲线是否收敛imgsz输入图片分辨率PCB缺陷小建议640起步batch每批图片数量显存不够时优先调小device使用GPU还是CPUGPU为0CPU为cpupatience早停轮数超过指定轮数指标不再提升就停止workers数据加载线程数Windows下不要开太大容易卡PCB缺陷检测有一个容易忽略的地方小目标。如果输入分辨率太低缺陷可能只有几个像素模型很难学。有条件时可以把imgsz调到800甚至更高但显存和推理速度会跟着变化。普通电脑上可以先用640跑通如果漏检严重再提分辨率。训练时我建议先把样本量降下来比如每个类别只取几十张先确认流程能跑通再上全量数据。这样可以避免因为标签格式错误或目录写错导致跑了一夜才发现问题。3.4 训练结果验证与导出训练完成后结果会保存在runs/detect/train目录下。重点看这几个文件results.png训练loss和验证指标的变化曲线。confusion_matrix.png混淆矩阵看哪些类别容易混淆。val_batch_pred.jpg验证集预测样例快速看检测框是否合理。weights/best.pt验证集上表现最好的权重。weights/last.pt最后一轮权重。结论判断不要只看训练集loss。训练集loss很低很可能只是因为模型记住了训练样本。最终看的是验证集的mAP50、mAP50-95、precision和recall。对于PCB缺陷检测我会更关注recall因为漏掉一个缺陷比多报一个疑似缺陷更麻烦。导出到GUI使用直接加载best.pt就够。如果后面要做更快部署可以导出ONNXyolo export modelbest.pt formatonnx导出的ONNX可以用ONNX Runtime或OpenCV DNN加载环境要求比PyTorch轻。4. PySide6 桌面端开发把模型包装成能用的小工具4.1 界面功能拆解PySide6部分不需要一开始就做完整系统先做一个最小版本。我建议按功能模块拆模型选择区选择训练好的pt或onnx文件。图片操作区打开单张图片、打开文件夹。检测参数区置信度阈值、IoU阈值。图片显示区显示原图和检测结果。日志输出区显示当前操作状态和错误信息。界面布局越简单越好。左侧放操作按钮和参数右侧大块区域放图片显示底部放日志。这样使用逻辑清楚排查问题也方便。4.2 加载模型与单图检测单图检测是整个应用的地基。先把这个功能跑通再谈批量处理。下面是一个最简单的界面骨架import sys from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QFileDialog, QVBoxLayout, QWidget from PySide6.QtGui import QPixmap from ultralytics import YOLO class PCBApp(QMainWindow): def __init__(self): super().__init__() self.model None self.open_model_btn QPushButton(加载模型) self.open_image_btn QPushButton(打开图片) self.image_label QLabel(图片显示区域) self.image_label.setMinimumSize(800, 600) layout QVBoxLayout() layout.addWidget(self.open_model_btn) layout.addWidget(self.open_image_btn) layout.addWidget(self.image_label) container QWidget() container.setLayout(layout) self.setCentralWidget(container) self.open_model_btn.clicked.connect(self.load_model) self.open_image_btn.clicked.connect(self.open_image) def load_model(self): path, _ QFileDialog.getOpenFileName(self, 选择模型, , Model Files (*.pt *.onnx)) if path: self.model YOLO(path) def open_image(self): path, _ QFileDialog.getOpenFileName(self, 选择图片, , Image Files (*.jpg *.png *.bmp)) if path and self.model: results self.model.predict(path, conf0.25, iou0.45) annotated_frame results[0].plot()[..., ::-1] # 转成 QPixmap 显示到 image_label这段代码只是一个骨架实际显示QImage的转换需要再处理一步但逻辑已经清楚了按钮触发事件调用模型预测渲染结果。这里有两个容易踩的坑。第一模型路径不要包含中文和特殊字符虽然PySide6本身能处理中文路径但底层OpenCV和文件流有时会出问题。第二加载模型和推理都是耗时操作不要在界面线程里直接做大量推理否则按钮点了之后窗口会卡住。4.3 批量检测与结果导出单图跑通之后批量检测就是一个遍历文件夹加结果汇总的问题。流程是选择要扫描的文件夹。遍历所有.jpg、.png、.bmp图片。对每张图片调用模型检测。保存标注图片到输出目录。把检测记录写入CSV或JSON。遇到处理失败的文件单独记录不中断整个任务。批量检测的难点不是循环本身而是稳定性。如果1000张图片中间有一张因为编码问题或路径问题报错整批中断用户体验会很差。所以必须做失败隔离和日志记录。结果导出可以先输出CSV字段包括文件名缺陷类别置信度目标框坐标x1, y1, x2, y2这样后续可以用Excel筛选也方便和质检系统对接。4.4 多线程处理与参数调节界面卡顿是最常见的GUI问题。处理方式是把检测任务放到QThread中执行主线程只负责接收结果并更新界面。下面是思路from PySide6.QtCore import QThread, Signal class DetectThread(QThread): result_ready Signal(str, object) def __init__(self, model, image_list, conf, iou): super().__init__() self.model model self.image_list image_list self.conf conf self.iou iou def run(self): for image_path in self.image_list: results self.model.predict(image_path, confself.conf, iouself.iou) # 释放结果给主线程 self.result_ready.emit(image_path, results)注意QThread里创建信号时尽量不要发送超大图像对象本身而是发送保存后的图片路径或只发送坐标数据主线程再去读取图片显示。这样可以减少界面线程压力。置信度阈值和IoU阈值在界面上做成可调控件很有用。现场图片光照、角度不同同一个模型在不同阈值下表现差异很大。比如漏检严重时可以先把置信度阈值从0.25降到0.15试试误检多时再把阈值调高到0.5以上。但阈值只是弥补手段根本问题还是数据。5. 常见问题与排查思路5.1 启动报错与依赖问题这类项目最常见的报错不是模型问题而是环境问题。如果import ultralytics失败先检查是不是装了多个Python环境当前终端用的Python和pip是不是同一个。如果import PySide6失败可以用pip重新安装注意不要和PyQt混用混装会导致Qt插件冲突。如果在运行时提示缺少OpenCV或numpy直接用pip安装即可。Windows下部分Qt平台插件缺失会报could not load platform plugin windows一般是安装不完整重装PySide6可以解决。5.2 训练阶段显存不足、训练不收敛训练时显存不足是新手最容易遇到的问题。出错信息里通常包含CUDA out of memory。处理顺序把batch减半比如从16减到8。把输入分辨率imgsz从640减到512。换成更小的模型比如从yolov8s换成yolov8n。启用梯度累积但效果有限。如果还不行改为CPU训练先验证流程。训练不收敛的情况要复杂一些。先看loss曲线有没有持续下降如果loss一直不降大概率是数据问题比如标签类别写反、标注文件大量为空、类别id越界。再看验证集的precision和recall如果训练集指标很高但验证集很低说明过拟合可以考虑增加数据、数据增强、减小模型。5.3 检测不准、漏检、误检怎么排查PCB缺陷检测里精度不够是常态不要一开始就怀疑模型不行。按下面顺序排查先在小验证集上看是全部检测得差还是特定类别差还是只有小缺陷差。检查标注用可视化工具把训练集的标注画出来看框和类别有没有标错。检查输入数据现场图片和训练图片的光照、分辨率、背景是不是不一致。提高输入分辨率小缺陷在640分辨率下可能只有几个像素。增加该类样本比如短路样本特别少重点收集。调节阈值先试不同的conf和iou组合。如果单张图都能检测出来批量处理时偶尔漏检优先看图片顺序和命名确认没有缩略图、重复文件或者损坏图片混进去。5.4 GUI卡顿和界面线程问题GUI卡顿基本可以确定是检测任务占用了主线程。解决方式是使用QThread把耗时操作放到子线程主线程只处理按钮点击和结果刷新。另一个常见问题是图片显示过大导致卡顿。显示前要用QPixmap按比例缩放到显示区域大小不要直接把5000x5000的原始大图塞给QLabel。还有一点批量处理时不要把所有结果都存在内存里可能会导致内存暴涨。正确的做法是每处理完一张就写盘只保留当前显示用到的图片数据。6. 落地建议与后续优化方向6.1 从Demo到产线工具的差距训练跑通了界面也能显示检测框这还只是Demo。真正放到产线环境会遇到更多问题相机是连续拍摄的怎么触发采集检测结果怎么传到上层系统误检率能不能控制在可接受范围新出现的缺陷样本怎么快速补充进模型模型更新后历史结果怎么对比和追踪这些问题不是YOLO或者PySide6本身能解决的而是一套完整的工程链路。所以先明确目标如果只是做一个离线质检工具批量检测加CSV导出基本够用。如果要在线检测需要多考虑相机接入、帧率、缓冲区、报警联动和日志。6.2 优化方向数据、模型和工程数据层面最值得投入。PCB缺陷检测里增加真实缺陷样本、优化打光方式、补充不同角度和背景的数据效果往往比换更大模型更明显。模型层面可以做切片检测。把一张大PCB图切成多个小块每个小块独立检测再把结果合并回原图。这样做能缓解小目标漏检问题但推理时间会增加需要在速度和召回之间做选择。如果训练完成后模型太大部署不方便可以尝试剪枝、量化和蒸馏。量化到INT8之后模型体积变小推理速度更快但精度可能会有轻微下降需要在验证集上重新评估。工程层面建议做好三件事日志、输出目录、失败重试。日志记录每次检测的文件、耗时、结果数量输出目录按日期和批次组织失败文件单独列出允许人工重新处理。6.3 最后一点经验做这类项目我最大的体会是一定先把单条检测跑稳再开批量先从最小模型开始验证数据再逐步加大模型不要一上来就把参数拉满很多时间浪费在OOM和调试环境上。PCB缺陷检测这个方向模型只是其中一部分数据质量、标注一致性、界面稳定性和缺陷漏检的成本才是真正决定项目能不能用的关键。建议第一次做的时候先按最小闭环走通一遍几十张图片跑完训练PySide6加载权重检测一张图导出一次结果。链路通了后面再慢慢优化也不迟。

最新新闻

日新闻

周新闻

月新闻