简介YOLO目标检测PCB缺陷数据集面向目标检测初学者、算法工程师及工业质检相关项目开发者可用于PCB板表面缺陷的识别与定位。数据来自真实产线场景场景丰富共1000张高质量图片经LabelImg仔细标注含VOC(xml)、COCO(json)、YOLO(txt)三种格式标签且按不同目录分类存放下载后即可直接接入YOLOv5、YOLOv8等模型训练免去格式转换和重新标注的麻烦。压缩包内共2000个文件除图片与标签外还包含数据集划分脚本可一键将图片和标签按比例划分为训练集、验证集、测试集也可生成ImageSets下的索引txt同时配有环境搭建与训练教程的HTML文档覆盖Windows和Linux系统并附带yaml配置文件教程中以实际案例演示了如何修改配置训练自己的数据集可帮助快速跑通完整训练流程。资源包整体约275.87MB已有713人学习下载适合需要一份标注完整、格式标准且附带实战教程的PCB缺陷数据集的用户可显著缩短数据准备时间集中精力优化模型结构与检测精度。1. 拿到 PCB 缺陷检测数据集先别急着训这套 YOLO 资源能帮你走到哪一步在 PCB 质检场景里最缺的往往不是模型而是标注数据。标题里这份「YOLO目标检测PCB缺陷数据集」做了一件很实在的事一次性把 1000 张缺陷图片对应的 VOC、COCO、YOLO 三种标签都给你备齐了还附了划分脚本和训练教程。它的价值不在于让新手知道目标检测怎么跑通而在于省掉了「把标注统一成 YOLO 格式」这几个月入库时最脏最累的活。适合两类人一类是刚入行想做 PCB 缺陷检测练手的算法工程师另一类是产线 AOI 项目里需要快速验证「这个缺陷用深度学习能不能稳定检出」的硬件工程师——先用这套数据和教程把流程跑通再回来谈自己的板子怎么做。2. 从压缩包到可训练状态三种标签格式的差异、划分脚本与目录核对2.1 同一个 PCB 缺陷在 VOC、COCO、YOLO 里的三种长相目标检测数据集的标签格式五花八门但这套数据集只给了三种VOC、COCO、YOLO。为什么要给三份因为它们的消费方完全不一样VOC 格式是老牌检测框架比如早期的 Faster R-CNN 训练脚本的默认输入COCO 格式被 MMDetection、Detectron2 这类框架直接吃YOLO 格式则是 ultralytics 全家桶YOLOv5/YOLOv8的标准输入。理解格式差异是后面所有操作的前提也是排查「训练时为啥坐标全崩了」的知识储备。拿同一张 640×480 的 PCB 图片举例假设有一个短路缺陷外接框左上角在 (60, 40)、右下角在 (200, 180)。三种格式记录这个框的方式完全不同。VOC 用的是 XML每张图一个文件。!-- 单张图片对应一个同名 XML 文件坐标是绝对像素值 -- annotation filenamepcb_0123.jpg/filename size width640/width height480/height /size object nameshort_circuit/name bndbox xmin60/xmin ymin40/ymin xmax200/xmax ymax180/ymax /bndbox /object /annotationCOCO 格式则是把所有图片的标注写进一个超大 JSON 文件里bbox 用[x, y, width, height]四个数表达且x、y是框左上角坐标。{ images: [ {id: 123, file_name: pcb_0123.jpg, width: 640, height: 480} ], annotations: [ { id: 1, image_id: 123, category_id: 1, bbox: [60, 40, 140, 140], area: 19600 } ], categories: [ {id: 1, name: short_circuit} ] }YOLO 格式最精简每张图一个 txt每一行代表一个目标类别 id、归一化中心点 x、归一化中心点 y、归一化宽、归一化高。同样的这个框换算出来就是下面这行。0 0.203125 0.229167 0.21875 0.291667逻辑说明中心点 x 的计算是(60 200) / 2 / 640 0.203125中心点 y 是(40 180) / 2 / 480 0.229167宽是140 / 640 0.21875高是140 / 480 0.291667。四个数值全部落在 0 到 1 之间这是 YOLO 训练硬性要求的归一化范围。如果你看到某个 txt 里出现大于 1 的数基本可以断定转换脚本或标注环节出了问题这个坑在后面第四章专门讲。很多新手拿到这套数据集后以为 VOC、COCO、YOLO 三种格式只是扩展名不同把 .xml 直接改成 .txt 就想拿去训练这是绝对行不通的。LabelImg 打标完 YOLO 格式的标默认生成的就是 txt 与同名 jpg 一一对应的结构这和 VOC XML 的目录组织也是两码事。格式之间的转换必须写脚本处理不存在「改后缀就能用」的道理。2.2 解压后先做四件事盘点目录、核对数量、随机抽检、统计类别拿到 rar 包别急着把它解压到训练项目里先在临时目录解开看整体文件结构。我一般用 7z 或 unrarWindows 下直接右键解压也行关键是解压后先执行一个快速盘点脚本。常见做法是先用 find 命令把图片和标签的数量、分布摸清楚。# 解压以 7z 为例 7z x YOLO目标检测PCB缺陷数据集.rar -o./pcb_defect_data # 统计图片数量 find ./pcb_defect_data -name *.jpg -o -name *.png | wc -l # 分别统计三种标签文件数量 find ./pcb_defect_data -name *.xml | wc -l find ./pcb_defect_data -name *.json | wc -l find ./pcb_defect_data -name *.txt | wc -l这套命令的意图是先把家底盘清楚。标题里写的是 1000 张图片那么 find 出来的 jpg/png 数量就应该是 1000同时要确认三种标签文件的数量也对得上注意「对得上」指的是每张图在三种格式里都存在对应标注而不是总数恰好相等。如果发现 XML 有 1000 个、txt 只有 998 个那就是有图缺标签后面训练时 ultralytics 会直接报 warning 或跳过部分图片。数量核对完随机抽三五张图把标注画回图上肉眼检查。最简单的方式是直接用 OpenCV 读 YOLO txt把框画出来看贴合度。import cv2 # 随机挑一张图和它的 YOLO 标签 img cv2.imread(pcb_defect_data/images/pcb_0001.jpg) h, w img.shape[:2] with open(pcb_defect_data/labels/yolo/pcb_0001.txt) as f: for line in f: cls, cx, cy, bw, bh map(float, line.split()) # YOLO 是归一化坐标画框前必须乘回原图宽高 x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check_pcb_0001.jpg, img)逻辑说明YOLO 标签里的坐标全部是归一化值所以画框前必须用图片实际宽高把它们还原成像素坐标。这里有个容易出错的细节——OpenCV 读图返回的 shape 是 (高, 宽, 通道)如果你按 (w, h) 的顺序搞反画出来的框位置会整体偏移。PCB 缺陷这种小目标偏移一个框往往就是漏检和误检的天壤之别。最后一步是统计类别数量和各缺陷类别的样本分布。我习惯直接扫 YOLO txt 的第一列。from collections import Counter label_counter Counter() label_names [short_circuit, open_circuit, missing_hole, burr] for txt_path in txt_files: with open(txt_path) as f: for line in f: cls_id int(line.split()[0]) label_counter[label_names[cls_id]] 1 print(label_counter)参数说明label_names要和你数据集标签定义对齐不同 PCB 缺陷数据集的类别叫法差异很大有的叫 short_circuit有的叫 spurious_copper有的把缺孔叫 missing_hole。这一步的主要目的是看类别分布是否均衡——如果某一类缺陷只出现二三十次那后面训练时它大概率学不好得靠数据增强或过采样去补。2.3 划分脚本怎么改训练/验证比例、随机种子与类别平衡标题里附带的划分脚本核心任务就是把这 1000 张图按比例切成训练集和验证集同时为 YOLO 训练生成对应的目录结构或 train.txt / val.txt 文件。这份脚本是整个数据集里最「一次性」的工具但它恰恰是翻车高发区原因在于随机切分不考虑类别平衡。我拿到这类脚本的第一件事是看三个东西train_ratio 默认值、有没有固定随机种子、切的是图片文件还是标签文件。下面是一个我常用的划分脚本骨架。import os import random from glob import glob from sklearn.model_selection import train_test_split random.seed(42) # 固定随机种子保证每次划分结果一致 train_ratio 0.85 # 1000 张图训练集占 85%验证集 15% images sorted(glob(images/*.jpg)) labels sorted(glob(labels/yolo/*.txt)) # 只保留图片和标签都存在的样本 paired [img for img in images if os.path.exists(os.path.join(labels/yolo, os.path.splitext(os.path.basename(img))[0] .txt))] train_imgs, val_imgs train_test_split( paired, train_sizetrain_ratio, random_state42, stratify[get_class_id(img) for img in paired] # 按类别分层 )逻辑说明train_test_split加stratify参数是按类别标签做分层抽样能保证每一类缺陷在训练集和验证集里的占比大致相同。如果 PCB 数据集里某种缺陷天然稀少不做分层抽样最坏情况是某类缺陷全被切进验证集训练时模型压根没见过验证指标自然难看。random.seed(42)和random_state42是双保险固定随机种子之后你调参、复现、对比实验才有意义。这里插一个特别容易踩的坑划分脚本输入的基准必须统一。如果脚本是从图片目录里挑文件名那它只会切出图片路径标签目录是完整 1000 份那么后面的训练就是拿一张图和它不匹配的标签硬学。所以脚本跑完后要顺手做一个配对校验——把训练集图片文件名集合与标签文件名集合做差集差集不为空就回去查脚本逻辑。3. 用 YOLOv8 训练 PCB 缺陷检测模型环境配置、数据集 yaml 与关键训练参数3.1 yolo 环境配置anaconda 虚拟环境与 CUDA 版 torchPCB 缺陷检测现在的标准句式基本是「yolov8 训练自己的数据集」而迈出的第一步就是环境。这里一个很常见的血流成河现场是直接在 base 环境里 pip install ultralytics然后发现 torch 是 CPU 版训练速度慢到怀疑人生。我建议的方案是先用 anaconda 建独立环境再在环境里装 CUDA 版 torch。# 创建独立虚拟环境指定 Python 版本 conda create -n pcb_yolo python3.10 -y conda activate pcb_yolo # 先装 CUDA 版 PyTorch以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 再装 ultralytics它会自动带上 opencv、numpy 等依赖 pip install ultralytics参数说明CUDA 版本号要和你本机显卡驱动支持的版本匹配不是随便装的。装完之后用 Python 验证 torch 能不能真调用 GPU这一步别省。# 验证 CUDA 是否可用 python -c import torch; print(torch.cuda.is_available()) # 输出 True 说明 GPU 可用输出 False 说明 torch 装成了 CPU 版 # 用 yolo 命令测试环境是否完整 yolo predict modelyolov8n.pt sourcetest.jpg注意第一行命令如果输出 False大概率是 torch 装错渠道了回炉重装如果输出 True 但第二行yolo predict报缺这个缺那个通常是 opencv 或 pandas 版本冲突。我的习惯是在虚拟环境里从头装别用 conda 去混装ultralyticsconda 源里这个包的更新速度往往跟不上一线需求。3.2 数据集 yaml 怎么写路径、nc、类名顺序ultralytics 训练不认裸目录它要求你提供一个 yaml 文件声明数据集根目录、训练集和验证集图片路径、类别数量、类别名列表。这个 yaml 是整个训练流程的「总开关」写错一个字段报错信息千奇百怪最常见的是「Dataset not found」与实际路径完全对不上。# pcb_defect.yaml path: /home/yourname/pcb_defect_data # 数据集根目录用绝对路径 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 nc: 4 # 缺陷类别数必须和标签一致 names: [short_circuit, open_circuit, missing_hole, burr] # 顺序必须与标签 id 对应逻辑说明path字段建议写绝对路径这是血泪教训。写相对路径时你在当前目录能跑换台机器换个目录立即报错排查半天发现只是路径没对上。train和val写的是相对 path 的图片目录不是标签目录——ultralytics 会自动找同名的 txt 标签前提是你的标注文件放在与图片同级的 labels 目录里且文件名一一对应。names顺序是另一个高频翻车点。YOLO 标签文件里的类别 id 是一个整数它指的就是names列表里的下标位置。如果标签里0代表短路而 yaml 里names[0]写成毛刺模型不会报错只会傻傻地学错——所有框都标对了但类别名整体串位。所以每次训练前我会先打印一张验证集图片的预测结果肉眼确认类别名没串。3.3 训练命令与四个关键参数imgsz、epochs、batch、patienceyaml 就绪后的标准训练命令长这样按 PCB 小目标场景做了参数调整。yolo train \ modelyolov8n.pt \ datapcb_defect.yaml \ imgsz1024 \ epochs150 \ batch8 \ patience30 \ projectpcb_runs \ namepcb_yolov8n参数说明这四个参数对小数据集尤其关键。imgsz1024是 PCB 缺陷检测最重要的一个决定。工业相机拍的 PCB 原图分辨率往往很高如果按 COCO 默认的 640 来 resize很多缺陷缩小后只剩十几二十个像素别说检测了人眼都难分辨。提到 1024 会显著改善小目标召回但显存占用指数级上涨8G 显存配 batch8 基本是极限。epochs150对 1000 张图来说是够用的量级。训练集小模型学得快也容易过拟合150 轮足够让 mAP 曲线趋于平台期跑多了反而学到的都是训练集噪声。batch8是在显存墙和训练稳定性之间折中的产物。batch 太小比如 2BN 层统计不稳定损失曲线震荡明显batch 太大直接 OOM项目当场变回课本教程。patience30是早停阈值。连续 30 个 epoch 验证集 mAP 没有提升就自动停止省时间还防过拟合。1000 张图通常跑到第 60~100 个 epoch 就会触发早停。训练日志大家都会看但建议额外盯着三个数值训练结束后的 best.pt 生成时间点、验证集 mAP50 值、以及类别维度的 mAP 分布。如果某类缺陷 mAP 明显低于平均值别急着调参首先回看 2.2 节统计的类别样本数——大概率是那类缺陷本身就少不是模型不行。4. PCB 缺陷训练的避坑清单标签错位、小目标漏检、损失函数震荡、越界坐标4.1 现象标签与图像错位训练 loss 飘到 20 且不下降现象训练刚开始几个 epochbox_loss 就高得离谱batch loss 从 20 起步连续迭代几十轮也不见明显下降或者训练过程看起来正常但验证集 mAP 始终是 0模型输出的框和真实缺陷完全对不上。原因图像和标签文件名没有一一对应。YOLO 格式按文件名配对图片pcb_0001.jpg对应pcb_0001.txt文件名错一位、后缀大小写不一致、或者是划分脚本切分时图来自 A 目录、标签来自 B 目录都会导致模型学到的是别人的框。解决训练前补一次文件名配对校验把孤儿文件和缺失文件全揪出来。这个脚本可以放在数据准备阶段跑一次跑完再训练人会踏实很多。import os from glob import glob img_files glob(images/train/*.jpg) labels_dir labels/train missing, orphan [], [] for img in img_files: base os.path.splitext(os.path.basename(img))[0] label_path os.path.join(labels_dir, base .txt) if not os.path.exists(label_path): missing.append(img) else: # 校验标签内容是否还有效 with open(label_path) as f: if f.read().strip() : orphan.append(label_path) print(f缺失标签: {len(missing)} 张, 空标签: {len(orphan)} 个)逻辑说明missing收集没有对应 txt 的图片orphan收集存在但内容为空的标签文件。图片有标而标签为空会让训练时该图被直接跳过等效于少了一张训练样本。1000 张的数据集里出现十几张空标签看起来不多但对本来样本量就小的一类缺陷可能是灭顶之灾。4.2 现象缺陷目标太小mAP 卡在 0.5 以下现象训练日志看起来一切正常loss 稳步下降但验证集 mAP50 卡在 0.4~0.5曲线从第 40 个 epoch 开始基本走平怎么调学习率都没用。原因PCB 缺陷检测是典型的小目标场景。短路桥、缺孔、毛刺这类缺陷在原图里往往只占几十到一两百像素经过 1024 resize 后再进网络特征层上的有效响应区域小得可怜。YOLOv8 默认的 anchor 参数是从 COCO 数据集迁移来的COCO 里小目标占比远低于 PCB 缺陷图像这就是模型「迁移不适配」的表现。解决按优先级做三件事。第一步是确认自己的 imgsz 确实提到了 1024 以上这是性价比最高的一步第二步是统计一下数据集中所有标注框的尺寸分布看看小目标到底占多少比例第三步是开启 mosaic 增强让模型在训练时反复看到多个小目标被拼贴进同一张图里。import os import numpy as np size_list [] label_files glob(labels/train/*.txt) for f in label_files: with open(f) as fh: for line in fh: cx, cy, bw, bh map(float, line.split()[1:]) size_list.append((bw, bh)) arr np.array(size_list) # 打印框尺寸的中位数和 25% 分位宽度小于 0.1 说明小目标占比高 print(宽度中位数:, np.median(arr[:, 0])) print(高度中位数:, np.median(arr[:, 1])) print(宽度 25% 分位:, np.percentile(arr[:, 0], 25))逻辑说明YOLO 标签里的宽高是归一化值宽度中位数 0.05 在 1024 尺寸下相当于 50 像素对 640 输入相当于 32 像素这就是为什么同样模型在 1024 下表现远好于 640。这个统计脚本跑完你对自己数据集的「小目标病」有多重会有量化判断后面调参就不用全靠玄学。4.3 现象yolo 损失函数三个分支震荡val 指标不升反降现象训练日志里 box_loss、cls_loss、dfl_loss 三条曲线在后半程大幅震荡不像正常情况那样平缓收敛更诡异的是训练集 loss 还在下降验证集 mAP 反而往下走典型的过拟合唱双簧。原因原因有三个按命中率排序。第一是学习率在后程过大模型在最优解附近反复横跳第二是训练集和验证集分布不一致常见于划分脚本没做分层抽样第三是标签存在噪声——比如同一个特征区域一张图标了缺陷另一张没标模型学到的是自相矛盾的信息。解决先从成本最低的学习率入手。ultralytics 支持在训练命令里直接加热身和余弦退火先看曲线是否变平顺。如果调完学习率还震荡就要怀疑是数据层面的问题此时把手动随机抽出的 20 张验证图逐个看预测结果确认是否有模型输出框与真实缺陷位置漂移的共性规律。# 调低初始学习率并开余弦退火前 50 轮不看曲线对比平滑度 yolo train modelyolov8n.pt datapcb_defect.yaml \ imgsz1024 epochs150 batch8 \ lr00.005 lrf0.01 warmup_epochs3参数说明lr0是初始学习率默认 0.01PCB 小数据集我习惯降到 0.005 附近起步更稳lrf0.01让学习率衰减到初始值的 1%给后期留足微调空间warmup_epochs3是前三轮热身避免模型在随机初始化阶段被大步长带偏。学习率调完还震荡就要回到数据层面排查而不是继续堆训练技巧。4.4 现象VOC 格式转 YOLO 时坐标越界归一化数值大于 1现象用自己写的脚本把数据集里 VOC XML 批量转成 YOLO txt 后发现生成的 txt 里有大于 1 的坐标值或者训练时 ultralytics 打印两条 warning点名某几个 txt 存在越界坐标直接跳过对应图片的训练。原因VOC 的 xmin、ymax 是绝对像素值除以图片宽高才是归一化值。越界的根源通常是标注框画出了图片边界比如 xmax 标到 645 而图片宽只有 640。另一个隐蔽原因是读取的图片尺寸和实际尺寸不一致一些手机或工业相机拍的图带 EXIF 旋转信息会造成宽高读取错误。解决转换脚本里加一道防御把所有坐标 clamp 到图片范围内。这是不看人品的写法import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map, out_path): tree ET.parse(xml_path) root tree.getroot() # 从图片文件读真实宽高别信 XML 里的 size 字段 img_w, img_h Image.open(img_path).size lines [] for obj in root.findall(object): cls_name obj.find(name).text cls_id class_map[cls_name] xmin float(obj.find(bndbox/xmin).text) ymin float(obj.find(bndbox/ymin).text) xmax float(obj.find(bndbox/xmax).text) ymax float(obj.find(bndbox/ymax).text) # 将坐标限制在图像范围内防止越界 xmin max(0, min(xmin, img_w - 1)) xmax max(0, min(xmax, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) ymax max(0, min(ymax, img_h - 1)) # 转 YOLO 归一化格式 cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))逻辑说明这个脚本的要点有三个。一是Image.open(img_path).size从图片本身读宽高而不是从 XML 的size字段读避免 EXIF 旋转导致的宽高颠倒二是clamp操作把越界坐标拉回边界内宁可框稍微紧一点也不能让模型读到一个超过 1 的归一化值三是转换后统一把宽高比极不合理的框过滤掉若 w 或 h 小于 0.005 直接丢弃这种小到不可思议的框多半是标注噪声。5. 训练完不等于能用在测试图上看效果、调推理参数、导 ONNX 部署5.1 用 model.val() 复现验证集指标注意 imgsz 对齐训练日志里那串 mAP 数字只是「官方成绩」上线前必须自己复现一遍。ultralytics 的 val 接口提供了最直接的复现方式重点是推理参数要跟训练时完全对齐。from ultralytics import YOLO # 加载训练得到的最佳权重 model YOLO(pcb_runs/pcb_yolov8n/weights/best.pt) # 在验证集上复现指标imgsz 必须和训练一致 results model.val( datapcb_defect.yaml, splitval, imgsz1024, conf0.25, iou0.45, batch8 ) print(results.box.map50) # 打印 mAP50 print(results.box.map) # 打印 mAP50-95参数说明imgsz1024必须和训练时一致否则复现出的 mAP 毫无可比性——很多人用 640 去验证一个在 1024 下训练的模型指标会掉一截然后误以为模型训练失败了。conf0.25是置信度阈值验证时它决定一个预测框是否算做正例iou0.45是 NMS 阈值。这两项和训练时保持相同复现出的指标才说得清。5.2 推理参数 conf、iou、imgszPCB 质检场景怎么调模型在手参数在口。真正到了产线推理环节conf 和 iou 就不再是「训练时默认就好」的事而是要跟实际缺陷成本挂钩。# 对一张 PCB 测试图做推理置信度阈值调到 0.2 以降低漏检 yolo predict modelpcb_runs/pcb_yolov8n/weights/best.pt \ sourcetest_pcb.png conf0.2 iou0.45 imgsz1024参数说明conf0.2是刻意压低置信度阈值。PCB 质检是「宁错杀不放过」的场景漏掉一个短路缺陷整批板子可能报废而多标几个误检边框后道复检人工扫一眼就滤掉了。iou0.45是 NMS 交并比阈值调低会保留更多相互重叠的候选框这对缺陷紧挨着的情况更宽容——两块铜桥挨得近时一个 iou 设 0.7 的 NMS 可能把另一个真缺陷的框给压没了。还有一个细节值得留意推理时imgsz与训练不一致不只会掉精度还会让输出的框坐标产生系统性偏差。在实际项目中我习惯把 imgsz 作为固定常量写进部署配置不允许在推理侧随意改动凡是动这个值都要重跑一遍 val 确认指标没掉。5.3 导出 ONNX 到产线 CPU 推理避开 export 参数坑训练和验证都过关接下来考虑的是部署。产线环境不一定有 GPU一套 CPU 只跑单张板卡推理很常见。ultralytics 提供了 ONNX 导出能力导出后配合 onnxruntime 就能脱离 torch 环境独立运行。# 导出 ONNXimgsz 必须与训练一致 yolo export modelpcb_runs/pcb_yolov8n/weights/best.pt formatonnx imgsz1024这行命令会生成一个best.onnx文件。注意export 阶段很多参数默认是 640如果训练时用的 1024 而忘了在导出命令里写imgsz1024导出的模型输入尺寸就是 640×640部署阶段如果不额外对齐精度表现和训练时根本不在一个水平线上。导出成功后用 onnxruntime 做一次 CPU 推理确认数值流是通的。import onnxruntime as ort import cv2 import numpy as np # 加载 ONNX 模型cpu 设备推理 sess ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) input_name sess.get_inputs()[0].name input_shape sess.get_inputs()[0].shape # [1, 3, 1024, 1024] img cv2.imread(test_pcb.png) img cv2.resize(img, (input_shape[2], input_shape[3])) img img.astype(np.float32) / 255.0 img img.transpose(2, 0, 1)[None] # HWC 转 CHW out sess.run(None, {input_name: img})[0] # 输出 [1, 6, 8400]逻辑说明ONNX 输出张量的形状是[batch, 6, num_candidates]每列的前 4 行是检测框坐标xywh第 5 行是类别得分第 6 行是置信度后续还需要自己写后处理做 NMS。这里主要验证模型能否正常加载和推理真正落地还要做 letterbox 预处理和坐标还原。CPU 上跑 1024 尺寸的单张推理大概在三五十毫秒量级静态板卡质检完全够用。6. 给 1000 张 PCB 缺陷数据补增强从数据集到稳定模型的最优取舍1000 张图做深度学习说到底就是小样本训练增强做不做、怎么做直接决定模型到产线的路有多长。我的底线原则是几何增强里只用平移、缩放和轻微旋转不用上下翻转——PCB 正反面纹理不对称翻转过后的样本等于教模型去学一块反了的板子这在工艺上不成立。YOLOv8 的内置增强参数在训练时按需开启。我会在原有划分好的 train 数据上把hsv_h从默认 0.015 提到 0.03让模型对产线不同批次板卡的颜色差异更鲁棒translate设到 0.2模拟板卡在镜头里偏离中心的情况scale设到 0.5让模型在多种尺度下都见过同一类缺陷。mosaic 建议默认打开它能把四张图拼成一张一张训练样本里同时出现多个缺陷对小目标密集的 PCB 缺陷尤其有效但注意训练后期可以手动降低 mosaic 概率因为拼接过度的样本和真实单板图像状态差异太大会拖累最终精度。# 增强参数写在训练命令里或写进 yaml 的 hyperparams 段 hsv_h: 0.03 # 色相扰动增强对板面颜色差异的鲁棒性 hsv_s: 0.05 # 饱和度扰动 hsv_v: 0.4 # 亮度扰动适应产线光照波动 translate: 0.2 # 平移比例 scale: 0.5 # 尺度缩放范围 mosaic: 1.0 # 前 90 个 epoch 开启后期可调低参数说明hsv_v0.4是光照扰动的核心产线打光角度、锡面反光的差异往往比缺陷本身的差异还大这一步能显著提升模型的域内稳定性translate0.2意味着目标有 10% 概率平移出原生位置配合随机裁剪能缓解小目标边界被截断的问题。增强做完后的核心动作不是直接看 mAP而是做一次 A/B 对比用同一套验证集分别评估「无增强」和「有增强」两个模型的类别 mAP。如果增强后某类缺陷 mAP 掉了多半是增强参数对这个缺陷形态产生了破坏性影响逐项缩回即可。我自己的习惯是先跑 20 个 epoch 看趋势再定增强参数的最终值从不一上来就全量训练。小数据集训练本就是一步一个脚印的活每次改动只动一个变量翻车时才有后悔药可吃。这套数据集的价值不在于给你一个完美的模型而在于让你用最小的成本把这条路完整走通一遍——格式、划分、训练、验证、部署每一步的坑都在上面了希望帮到你。本文还有配套的精品资源点击获取
