news 2026/9/2 3:16:28

YOLOv8+PySide6实现PCB缺陷检测系统开发实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv8+PySide6实现PCB缺陷检测系统开发实战

在PCB制造与电子组装行业里,外观质检一直是产能瓶颈。过去依赖人工目检,效率低、漏检率高,而且招工困难。传统机器视觉方案需要针对每类缺陷单独写规则,遇到光照变化、板面脏污、器件遮挡时鲁棒性很差。深度学习目标检测模型的出现,让“用数据替代规则”成为可能。YOLO系列模型因为速度快、精度高、部署简单,非常适合落地到PCB缺陷检测场景。而PySide6作为Qt for Python的官方绑定,可以在短时间内开发出可交付的桌面检测工具,不用把模型服务化也能本地运行。

这篇文章基于我实际落地的一个小项目来复盘:使用YOLOv8和YOLOv5作为检测模型,配合PySide6开发PCB印制板缺陷检测系统,实现了图片上传、模型推理、缺陷定位、结果可视化全流程。整个项目包含数据集整理、模型训练、权重导出、界面编写、推理联调五个环节。无论你是刚入门深度学习的小白,还是正在找课题方向的在校生,或者是在工厂做过视觉项目的一线工程师,都能从这套流程里拿走可以直接复用的代码。

先说明本文的技术边界。缺陷检测不等于工业视觉的全部,它只是AOI(自动光学检测)流程中的算法环节。本文聚焦的是“如何用YOLO训练一个缺陷检测模型”,以及“如何用PySide6把这个模型包装成桌面软件”。不涉及PLC通信、运动控制、光源选型、相机SDK采集这些硬件层面的内容。如果你需要做完整的产线方案,可以把本文的检测模块作为一个独立组件集成进上位机。

1. 背景与核心概念

1.1 PCB缺陷检测为什么要用深度学习

PCB印制板在制造过程中,经过钻孔、蚀刻、镀铜、阻焊、丝印等十几道工序,每一道都可能引入缺陷。常见的缺陷包括短路、断路、铜渣、毛刺、划伤、漏铜、缺孔等。这些缺陷在高密度板上往往只有毫米甚至微米级别,而且背景纹理复杂,传统视觉算法很难用固定阈值做判断。

传统算法思路通常依赖灰度阈值分割、连通域分析、模板匹配。这套方案对“均匀光照 + 标准板面”的样本有效,但PCB板面的铜箔纹理、玻璃纤维底色、阻焊油墨颜色都会干扰算法判断。更关键的是,传统算法无法泛化:换一种板子、换一种颜色,就要重新调一轮参数。

深度学习目标检测算法直接把“图像像素”映射到“缺陷类别 + 坐标框”。模型通过学习大量标注样本,自行提取缺陷的纹理、边缘、形状特征,对光照和板面变化的鲁棒性明显更强。训练好的模型可以直接处理整张PCB图像,同时输出多个缺陷的位置和类别,一个模型可以胜任多种缺陷的检测任务。

1.2 YOLOv8与YOLOv5怎么选

YOLOv5是Ultralytics公司推出的经典目标检测模型,在工业界使用非常广泛,社区资料丰富,部署方案成熟。YOLOv8是Ultralytics在2023年初发布的YOLO系列新版本,在骨干网络、颈部结构、检测头和解耦方式上都做了改进,精度和速度相比YOLOv5都有提升,而且官方直接提供了训练、验证、导出、部署的一体化API。

从实际工程角度出发,做PCB缺陷检测时YOLOv8是更省事的选择。理由有三个:第一,YOLOv8以ultralytics包形式发布,训练和推理代码比YOLOv5的detect.py脚本更简洁;第二,YOLOv8在COCO数据集上的mAP普遍优于同量级YOLOv5模型;第三,YOLOv8的导出流程更顺畅,可以导出ONNX、TensorRT、CoreML等格式,方便后续部署。

但YOLOv5也没有被淘汰。如果你的生产环境已经跑了YOLOv5的ONNX或TensorRT推理服务,或者你的显卡显存极小,YOLOv5s、YOLOv5n仍然是可选方案。本文以YOLOv8为主线,YOLOv5的配置和训练命令我也会在文末做一并说明,因为两个框架在数据处理和标注格式上几乎没有差别。

1.3 PySide6在检测工具中扮演什么角色

PySide6是Qt for Python的官方绑定库,基于Qt 6开发,功能覆盖了窗口、布局、按钮、表格、绘图、文件对话框等桌面应用开发所需的全部组件。相比tkinter,PySide6界面更现代,控件更丰富;相比PyQt,PySide6的许可证是LGPL,对商业应用更友好。

在检测系统里,PySide6主要负责三件事:一是搭建图形界面,让操作人员可以选中图片文件、点击按钮、看到检测结果;二是调用YOLO模型进行推理,界面和模型之间通过Python代码结合;三是在界面上绘制检测框、标签、置信度,直观展示模型预测结果。

为什么不用Web前端?因为产线环境经常没有公网环境,浏览器部署会引入服务器成本,而且桌面程序在离线环境下启动更快,文件系统访问也更直接。PySide6这种方式特别适合做内部工具。

2. 环境准备与项目结构

2.1 推荐环境与依赖版本

本文的核心依赖是ultralytics和PySide6。建议使用Python 3.9到3.11之间的版本,太老的Python版本无法安装新版PySide6,太新的Python版本可能遇到PyTorch轮子尚未适配的问题。

我用的是以下组合:

依赖版本建议
Python3.10
PyTorch2.0以上
ultralytics8.0以上
PySide66.4以上
opencv-python4.8以上
numpy1.24以上

如果你使用的是YOLOv5,需要额外安装torch、torchvision,并从YOLOv5仓库获取环境依赖。YOLOv5官方使用requirements.txt管理依赖,安装命令如下。

环境安装的具体版本以你本机的CUDA版本和PyTorch官方兼容表为准。如果只做CPU推理演示,即使没有NVIDIA显卡也可以完成环境搭建和界面开发,只是训练步骤会非常慢。

为了保证最终程序的依赖清晰干净,强烈建议使用虚拟环境。下面命令以conda为例。

conda create -n pcb_yolo python=3.10 -y conda activate pcb_yolo

2.2 安装PySide6与ultralytics

激活虚拟环境后,依次安装依赖包。如果你有NVIDIA显卡,先安装与CUDA版本匹配的PyTorch。如果没有,直接使用PyTorch官方CPU版本即可。

pip install ultralytics pip install pyside6 pip install opencv-python

由于ultralytics会同时安装torch、torchvision、numpy等基础依赖,所以第二步安装PySide6时一般不会出现依赖冲突。如果安装过程中遇到numpy版本冲突,可以调整安装顺序,优先安装PySide6再安装ultralytics。

安装完成后验证一下版本:

python -c "import ultralytics; print(ultralytics.__version__)" python -c "import PySide6; print(PySide6.__version__)" python -c "import cv2; print(cv2.__version__)"

如果三个包都能正常打印版本号,说明环境基本可用。

2.3 项目目录结构

整个项目建议按照下面目录组织:

pcb_defect_detection/ ├── dataset/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── pcb_defect.yaml ├── models/ ├── runs/ │ └── detect/ ├── main.py ├── detector.py └── requirements.txt

其中dataset目录存放标注后的训练数据和验证数据;models目录存放预训练权重和训练好的best.pt;runs/detect是YOLO训练过程的默认输出目录;main.py是PySide6界面入口;detector.py封装YOLO模型推理逻辑。

3. PCB缺陷数据集准备

3.1 PCB常见缺陷类别

PCB缺陷检测按制造工艺可以分为两类:一类是图形转移过程中的缺陷,比如短路、断路、缺口、毛刺;另一类是表面工艺缺陷,比如铜渣、锡珠、划伤、氧化。在做目标检测标注时,每类缺陷作为独立类别,标注文件只记录缺陷的边界框和类别编号。

公开的PCB缺陷数据集通常包含六类典型缺陷:missing_hole(缺孔)、mouse_bite(鼠咬)、open_circuit(断路)、short(短路)、spur(毛刺)、spurious_copper(铜渣)。这个分类方案在PCB缺陷检测论文和竞赛中非常常见,可以作为项目初始数据集。

如果你的生产环境板子有特殊的缺陷形态,需要自己采集数据并标注。建议每类缺陷至少标注500张以上图片,包含不同光照和不同板面版本。

3.2 YOLO格式目录组织

YOLO训练要求数据按照images和labels两个大目录组织,每个大目录下再分为train和val两个子目录,标签文件和图片文件一一对应,文件名相同,扩展名不同。图片统一使用jpg或png,标签统一使用txt文本,每个txt文件里每行表示一个目标。

下面是数据集目录的规范示例:

dataset/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── 002.jpg │ └── val/ │ ├── 101.jpg │ └── 102.jpg └── labels/ ├── train/ │ ├── 001.txt │ └── 002.txt └── val/ ├── 101.txt └── 102.txt

标签txt文件内容格式如下,每行五个数字:类别编号、归一化中心点x坐标、归一化中心点y坐标、归一化宽度、归一化高度。四个坐标值范围都是0到1。

0 0.234375 0.356770 0.045524 0.078256 1 0.612548 0.584215 0.032118 0.067423

标注工具推荐使用LabelImg或X-AnyLabeling。前者是经典YOLO格式标注工具,后者支持自动标注和辅助标注,可以大幅提升标注效率。标注完成后,记得用脚本检查标注文件和图片是否一一对应,防止出现空标签文件或者坐标越界的问题。

3.3 数据集配置文件

YOLO训练时需要指定一个yaml文件,里面包含数据集的根目录、训练集图片路径、验证集图片路径和类别名称列表。以六类PCB缺陷为例,配置如下。

# 文件路径:dataset/pcb_defect.yaml path: ./dataset train: images/train val: images/val names: 0: missing_hole 1: mouse_bite 2: open_circuit 3: short 4: spur 5: spurious_copper

path字段相对于执行训练命令的工作目录,如果你把训练脚本放在项目根目录,而dataset也在项目根目录下,这个配置可以直接使用。如果数据集存放在其他路径,建议写成绝对路径,避免路径解析问题。

4. YOLOv8模型训练与评估

4.1 模型文件选择

YOLOv8官方提供了五个不同规模的模型:yolov8n、yolov8s、yolov8m、yolov8l、yolov8x,其中n是纳诺版本,参数量最小,推理速度最快;s是小版本,精度稍微高一些。PCB缺陷检测这种任务类别少、目标尺寸有大有小,使用yolov8n或yolov8s已经可以满足大多数场景。

如果使用YOLOv5,对应模型文件是yolov5n.pt、yolov5s.pt、yolov5m.pt等。两者的网络结构不同,但训练命令和数据集要求基本一致。

4.2 训练命令与参数说明

使用ultralytics的YOLO训练非常简单,一条命令即可启动。下面以yolov8n.pt作为预训练权重,训练100轮。

yolo detect train data=dataset/pcb_defect.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16 device=0

参数说明如下:

参数含义
data数据集yaml文件路径
model预训练权重,也可以是完整模型结构yaml
epochs训练轮数
imgsz输入图片尺寸,默认640
batch批量大小
device使用设备,0表示第一张GPU,cpu表示CPU

如果你只有CPU环境,建议把epochs减少到50,batch改为4,否则训练时间会非常长。如果你的显存充足,batch可以尝试32,配合数据增强策略能更快收敛。

训练完成后,最后几个epoch的模型和验证集上表现最好的模型会自动保存到runs/detect/train/weights/目录下,其中best.pt是验证集指标最优的模型,last.pt是最后一轮模型。部署时使用best.pt

4.3 验证与结果分析

训练结束后可以运行验证命令,查看模型在验证集上的表现。

yolo detect val model=runs/detect/train/weights/best.pt data=dataset/pcb_defect.yaml

程序会输出mAP50、mAP50-95、precision、recall等指标,并生成混淆矩阵、PR曲线、F1曲线等可视化图片。这些指标可以帮助判断模型是否存在漏检和误检:precision低说明误检多,recall低说明漏检多。PCB缺陷检测对漏检非常敏感,实际项目中宁可放宽置信度阈值,让操作人员二次确认,也不要漏掉真缺陷。

如果发现某些缺陷类别的识别精度偏低,优先检查标注质量,再看该类别的样本数量是否足够。PCB缺陷样本不均衡是常态,可以对少样本类别做过采样或数据增强。

4.4 导出ONNX格式

界面程序推理使用的是PyTorch权重,但如果你后续要部署到工业相机工控机,ONNX格式更通用。导出命令如下。

yolo export model=runs/detect/train/weights/best.pt format=onnx

导出后的best.onnx文件可以直接用ONNX Runtime加载。从PySide6界面项目角度来说,直接加载PyTorch的best.pt比较简单,因为ultralytics已经封装了推理逻辑,不用额外写前处理和后处理代码。

5. PySide6桌面检测界面开发

5.1 GUI功能设计

在动手写代码之前,先把界面功能梳理清楚。本文演示的检测工具具备以下功能:

  • 选择图片:通过文件对话框选择本地PCB图片,支持jpg、png、bmp格式。
  • 模型加载:启动时自动加载训练好的best.pt权重,为后续推理做准备。
  • 图片显示:显示原始图片和带检测框的推理结果图。
  • 执行检测:点击按钮触发模型推理,在结果图上绘制检测框和标签。
  • 检测信息输出:在文本区域记录推理耗时、检测到的缺陷数量、类别和置信度。
  • 异常提示:图片读取失败或模型加载失败时弹出提示。

这个功能集看起来简单,但已经覆盖了一次完整检测的全部流程。界面布局采用左右分区:左侧为操作面板,右侧为大面积图像显示区。

5.2 界面布局设计

布局使用Qt的垂直布局和水平布局嵌套实现。主窗口使用QVBoxLayout作为顶层面板,内部再分两个水平区域:左侧控制栏和右侧图像显示区域。控制栏固定宽度,图像显示区域自动拉伸。

界面组件清单如下:

组件属性作用
QPushButton选择图片打开文件对话框
QPushButton开始检测执行模型推理
QLabel图像显示显示原始图和结果图
QTextEdit日志输出显示检测信息和错误信息
QComboBox模型选择可选预训练模型或best.pt

5.3 推理逻辑封装

为了让界面代码更清晰,把模型推理逻辑单独放到detector.py文件中。Detector类负责加载模型、执行检测、返回结果。这样做的好处是后续如果要接入摄像头实时检测,只需要修改Detector的输入接口,不需要改动界面代码。

Detector类的核心方法代码如下:

# 文件路径:detector.py from ultralytics import YOLO class Detector: def __init__(self, model_path: str = "best.pt", conf: float = 0.25): self.model = YOLO(model_path) self.conf = conf def predict(self, image_path: str): results = self.model.predict( source=image_path, conf=self.conf, save=False, verbose=False ) return results def get_annotated_img(self, image_path: str): results = self.predict(image_path) if len(results) == 0: return None # results[0].plot() 返回带标注框的 BGR numpy 数组 annotated = results[0].plot() return annotated

这里需要注意,results[0].plot()返回的是BGR格式的numpy数组,因为ultralytics内部基于OpenCV处理图像,所以显示时要注意通道顺序。

如果你要在界面上同时显示缺陷类别与置信度,可以直接从results[0].boxes中读取数据。

boxes = results[0].boxes.xyxy.cpu().numpy() # 检测框坐标 clss = results[0].boxes.cls.cpu().numpy() # 类别编号 confs = results[0].boxes.conf.cpu().numpy() # 置信度

5.4 主窗口完整代码

下面是main.py的完整代码。这个文件包含了窗口、布局、信号槽和图像显示逻辑。为了便于阅读和复制,我保持了必要的注释。

# 文件路径:main.py import sys import cv2 from PySide6.QtCore import Qt, QTimer from PySide6.QtGui import QPixmap, QImage from PySide6.QtWidgets import ( QApplication, QMainWindow, QWidget, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog, QTextEdit, QComboBox, QMessageBox, QProgressBar ) from detector import Detector def numpy_to_qpixmap(img_bgr): """将OpenCV的BGR numpy数组转换为QPixmap""" h, w, ch = img_bgr.shape bytes_per_line = ch * w # BGR格式直接使用Format_BGR888 qimg = QImage( img_bgr.data, w, h, bytes_per_line, QImage.Format.Format_BGR888 ).copy() return QPixmap.fromImage(qimg) class PCBDetectWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("PCB缺陷检测系统 - YOLOv8 + PySide6") self.setMinimumSize(1000, 700) self.image_path = None self.original_img = None self.result_img = None self.detector = None self.init_ui() self.load_default_model() def init_ui(self): central_widget = QWidget() self.setCentralWidget(central_widget) # 根布局 root_layout = QVBoxLayout(central_widget) # 水平主布局 main_layout = QHBoxLayout() root_layout.addLayout(main_layout) # 左侧控制面板 control_widget = QWidget() control_widget.setFixedWidth(260) control_layout = QVBoxLayout(control_widget) self.btn_select = QPushButton("1. 选择图片") self.btn_select.clicked.connect(self.select_image) self.model_combo = QComboBox() self.model_combo.addItem("best.pt", "best.pt") self.model_combo.addItem("自己选择模型", "custom") self.btn_load_model = QPushButton("2. 加载/切换模型") self.btn_load_model.clicked.connect(self.load_model_from_combo) self.btn_detect = QPushButton("3. 开始检测") self.btn_detect.clicked.connect(self.run_detect) self.log_text = QTextEdit() self.log_text.setReadOnly(True) self.log_text.setPlaceholderText("检测日志输出区...") control_layout.addWidget(self.btn_select) control_layout.addWidget(self.model_combo) control_layout.addWidget(self.btn_load_model) control_layout.addWidget(self.btn_detect) control_layout.addWidget(QLabel("检测日志:")) control_layout.addWidget(self.log_text) control_layout.addStretch() # 右侧图像显示区域 image_widget = QWidget() image_layout = QVBoxLayout(image_widget) self.image_label = QLabel("请选择PCB图片") self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.image_label.setMinimumSize(700, 600) self.image_label.setStyleSheet( "border: 1px solid #cccccc; background-color: #f8f8f8;" ) image_layout.addWidget(self.image_label) main_layout.addWidget(control_widget) main_layout.addWidget(image_widget, stretch=1) def load_default_model(self): """启动时默认加载best.pt""" try: self.detector = Detector(model_path="best.pt") self.log("模型加载成功:best.pt") except Exception as e: self.log(f"模型加载失败:{e}") def select_image(self): file_path, _ = QFileDialog.getOpenFileName( self, "选择PCB图片", "", "图片文件 (*.jpg *.jpeg *.png *.bmp);;所有文件 (*)" ) if not file_path: return self.image_path = file_path self.original_img = cv2.imread(file_path) if self.original_img is None: QMessageBox.warning(self, "错误", "图片读取失败,请确认文件格式是否正确。") return pixmap = numpy_to_qpixmap(self.original_img) self.image_label.setPixmap( pixmap.scaled( self.image_label.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation ) ) self.log(f"已加载图片:{file_path}") def load_model_from_combo(self): selected = self.model_combo.currentData() if selected == "custom": model_path, _ = QFileDialog.getOpenFileName( self, "选择模型权重", "", "PyTorch模型 (*.pt)" ) else: model_path = selected if not model_path: return try: self.detector = Detector(model_path=model_path) self.log(f"模型加载成功:{model_path}") except Exception as e: QMessageBox.critical(self, "模型加载失败", str(e)) def run_detect(self): if self.detector is None: QMessageBox.warning(self, "提示", "请先加载模型。") return if self.image_path is None or self.original_img is None: QMessageBox.warning(self, "提示", "请先选择PCB图片。") return try: self.log("开始检测...") results = self.detector.predict(self.image_path) if len(results) == 0: self.log("检测完成,但未获取到结果。") return boxes = results[0].boxes.xyxy.cpu().numpy() clss = results[0].boxes.cls.cpu().numpy() confs = results[0].boxes.conf.cpu().numpy() # 获取类别名称 names = results[0].names self.log(f"检测到 {len(boxes)} 个目标") for i in range(len(boxes)): cls_name = names.get(int(clss[i]), "unknown") conf = confs[i] self.log(f" - {cls_name}, 置信度: {conf:.4f}") # 绘制结果图 annotated = self.detector.get_annotated_img(self.image_path) if annotated is not None: pixmap = numpy_to_qpixmap(annotated) self.image_label.setPixmap( pixmap.scaled( self.image_label.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation ) ) except Exception as e: QMessageBox.critical(self, "检测失败", str(e)) self.log(f"检测异常:{e}") def log(self, msg): self.log_text.append(msg) if __name__ == "__main__": app = QApplication(sys.argv) window = PCBDetectWindow() window.show() sys.exit(app.exec())

这段代码可以直接复制使用。需要注意,程序默认从当前工作目录加载best.pt,如果你把模型放在models目录,需要把默认路径改为models/best.pt

6. 完整运行与验证

6.1 启动程序

在项目根目录下运行以下命令启动程序。

python main.py

程序启动后会自动加载best.pt模型,控制台显示“模型加载成功”的日志。如果没有加载到模型文件,程序会打印模型加载失败信息,但界面仍会正常弹出,你可以在界面右上角模型下拉框中选择“自己选择模型”,然后手动指向训练好的权重文件。

6.2 检测流程演示

先点击“选择图片”,找到一张验证集图片,程序会立即在右侧显示原始图片。此时点击“开始检测”,程序执行模型推理,在日志区输出每个检测框的类别和置信度,右侧图片更新为带标注框的结果图。

整个流程如果使用CPU推理,一张640x640的图片大约需要0.2到2秒,具体时间和模型大小、CPU性能有关。如果使用GPU,推理时间通常在几十毫秒级别。

6.3 结果说明

结果图中每一个检测框都由绿色边框、类别名称和置信度三部分组成。置信度越高,颜色越清晰,说明模型对这个框更有把握。对于漏检风险高的缺陷,建议把Detector中的conf参数调低到0.15甚至0.1,宁可多标记候选框,也不放过真缺陷。

7. 常见问题与排查思路

我在开发过程中踩过不少坑,这里把最容易遇到的问题整理成表格,方便排查。

问题现象常见原因解决思路
训练时报错“CUDA out of memory”显存不足减少batch、降低imgsz、改用yolov8n
训练时验证集mAP一直很低标注框方向不对或数据集划分有问题检查标签归一化坐标,确保train/val划分无重叠
加载权重时提示loss函数不存在模型与代码版本不匹配确保使用同一版本的ultralytics库
PySide6窗口弹出后画面不更新图片显示比例拉伸导致错觉检查pixmap是否被setScale重新覆盖;使用日志确认推理完成
CPU推理速度过慢默认使用CPU推理在Detector创建时传入device="cuda:0"
读图显示颜色异常图片通道混淆确认numpy_to_qpixmap使用Format_BGR888
标注文件打开后检测结果为空图片尺寸过大、模型输入尺寸受限imgsz设为640或1280,分块检测或缩小图片

以最常见也最容易被新手忽略的“CPU推理慢”问题为例,解决方法很简单。在detector.py里修改YOLO的device参数:

self.model = YOLO(model_path)

如果检测到GPU存在,可以手动指定:

import torch device = "cuda:0" if torch.cuda.is_available() else "cpu" self.model = YOLO(model_path) self.model.to(device)

另外一个容易踩坑的地方是PySide6的QImage生命周期问题。OpenCV读出的numpy数组在传递给QImage后,如果numpy数组被垃圾回收,QPixmap可能出现空白。所以我在numpy_to_qpixmap中调用了.copy(),确保图像数据被复制到Qt管理的缓冲区。如果你在开发中发现图片时有时无,优先检查这一块。

8. 工程化最佳实践与优化方向

8.1 数据标注管理

PCB缺陷检测的精度上限由数据质量决定。标注时要遵循一条准则:宁可多标,不可漏标,边界框尽量贴近缺陷边缘。多张图片中同一类缺陷的标注风格要保持统一,否则模型会学到不稳定的特征边界。标注完成之后建议统计每个类别的样本数量,如果某个类别样本明显偏少,可以通过复制、旋转、亮度增强等方式扩充。

8.2 模型训练策略

从YOLOv8n开始训练,先跑一个baseline,然后再考虑升级到YOLOv8s或YOLOv8m。如果baseline已经达到95%以上的mAP50,就没有必要换更大的模型。PCB缺陷检测属于少类别检测任务,过大的模型会带来推理性能损耗。迁移学习可以显著缩短训练时间,如果不是特殊场景,没有必要从零训练模型。

8.3 界面工程化

实际交付给产线使用之前,建议在界面上增加几项功能:批量检测一个文件夹内所有图片;检测结果自动导出为CSV文件;设置置信度阈值滑块;增加识别历史查询。批量检测在生产中非常重要,因为操作员经常需要一次检测一批图片,而不是一张张点按钮。可以把Detector.predict改成接收图像目录,然后用循环处理。

8.4 推理性能优化

在工业部署端,如果推理延时要求高,建议把模型导出为TensorRT格式,在GPU上运行。TensorRT对YOLO模型有专门的优化,推理速度可以提升数倍。如果只能使用CPU推理,可以使用OpenVINO格式的模型,在Intel平台上也有明显的加速效果。

8.5 安全与权限边界

如果程序需要接收生产数据,建议遵循最小权限和可审计原则:所有检测记录保留时间戳和原始图片引用,方便追溯;不要默认删除任何图片;所有批量操作前先备份数据。涉及数据库写入时,确保有事务回滚机制,避免异常中断造成数据损坏。产线环境不要以管理员身份运行检测程序,尽量使用低权限的专用账户运行服务。

9. 总结与学习路线

本文从PCB缺陷检测的实际需求出发,完整走了一遍使用YOLOv8 + PySide6开发检测工具的流程。环境准备、数据集组织、YOLOv8训练、PySide6界面开发、推理联调,每一步都以可运行的代码作为依托。对于YOLOv5的用户,数据格式和界面调用逻辑完全一致,只需要把best.pt换成YOLOv5训练出来的权重文件,其他部分不用改动。

如果你是新手,建议先不要直接上手GUI项目,而是把这个项目拆成两步:第一步,独立完成YOLOv8的训练和验证流程,跑通自己的数据集;第二步,再尝试用PySide6包装模型。如果训练和推理逻辑不熟练,界面排错会和模型排错混在一起,定位问题会非常痛苦。

如果你已经有训练经验,可以继续深入三个方向:第一,多尺度检测优化,PCB上的小目标缺陷可以通过增加P2层或者使用Tiling策略处理;第二,模型量化,把PyTorch模型转换成INT8格式,大幅提升产线推理速度;第三,异常检测方法,当缺陷样本不足时,可以尝试基于重建误差的缺陷分割方案作为补充。

缺陷检测这个方向门槛不算高,但工程坑很多。希望这篇笔记能让你少走几步弯路,如果代码在运行中遇到问题,欢迎在评论区带上报错信息一起交流。也可以把文章收藏起来,后面做AOI项目时直接当工具书查阅。动手跑一遍,比看十篇文章更有价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 3:16:00

单片机Proteus仿真入门到进阶:300例源码的拆解与避坑指南

简介:这是一套面向单片机初学者和进阶者的 Proteus 仿真实例合集,涵盖 C51 编程、LCD1602 液晶显示、矩阵键盘、数码管、中断、PWM、ADC 及电机控制等常见嵌入式开发知识点。300 个实例均配有可运行的源代码和注释,适合在虚拟仿真环境中边学边…

作者头像 李华
网站建设 2026/9/2 3:15:13

浏览器端跑LLM?WebGPU本地推理实战与验证指南

如果你的电脑已经装了 Python、配好了 CUDA、下载了好几个 GB 的模型文件,才发现代码在服务器上跑得很顺,换个环境就崩了——那你会不会想过:能不能直接在浏览器里把模型跑起来?这不是异想天开。近几年 WebGPU、WebAssembly、WebN…

作者头像 李华
网站建设 2026/9/2 3:14:16

STM32H743基础例程实战:从时钟配置到OV2640图像采集

简介:面向STM32H743高性能MCU开发者的基础例程代码合集,覆盖GPIO输入中断、看门狗、定时器、PWM输出与捕获、LCD显示、SRAM管理7类关键外设,示例基于ARM Cortex-M7内核,帮助嵌入式开发者在官方库或HAL库基础上快速理解寄存器配置与…

作者头像 李华
网站建设 2026/9/2 3:13:51

基于YOLOv8的交通标志识别系统实战:从模型训练到Jetson Nano部署

简介:这是一套基于C与OpenCV实现的交通标志检测与识别完整项目,面向中高级视觉开发者和课程设计,配套可运行工程源码与数据集,可直接编译使用。项目自带图形化界面,左侧支持导入图片或视频并实时显示画面,右…

作者头像 李华
网站建设 2026/9/2 3:12:24

Arduino无源蜂鸣器演奏《千本樱》:从频率表到代码实现

很多人的 Arduino 启蒙项目是 Blink:让板载 LED 一秒一闪。但灯会闪之后,真正让朋友觉得“有点东西”的,往往是让蜂鸣器唱歌。用 UNO 板和无源蜂鸣器演奏《千本樱》,在嵌入式社区已经被玩过很多轮,但它至今仍然是一个值…

作者头像 李华
网站建设 2026/9/2 3:08:04

ZLG CAN驱动实战拆解:从安装避坑到高负载稳定传输

简介:ZlgCanDriver.zip是一套面向创芯科技USB_CAN-2A/CANalyst-II分析仪的Python驱动资源,适合汽车电子、工业自动化等领域开发者快速搭建CAN总线收发环境。文件共36个,约3.25MB,以23个DLL动态库为核心,配合Python脚本…

作者头像 李华