PCB缺陷数据集实战:YOLO与VOC双格式训练及避坑指南
简介这份资源面向从事PCB表面缺陷检测的算法工程师、高校研究者与深度学习学习者提供一套可直接用于目标检测训练与验证的标注数据集帮助解决工业质检场景中样本获取难、标注成本高的问题。压缩包共1386个文件由693张jpg图像与693个xml标注文件组成整体约907.52MB标签同时提供VOC的xml格式与YOLO的txt格式便于在Faster R-CNN、YOLO等主流框架间灵活切换。缺陷覆盖Missing_hole、Mouse_bite、Open_circuit、Short、Spur、Spurious_copper六类标注精确、类别分布均匀可支撑较稳定的模型拟合效果。目前已有2904人学习下载适合作为PCB缺陷识别项目的训练底库或算法对比基准也可用于数据增强、类别均衡与检测精度调优等实验。1. 从一批spurious_copper文件名说起这份 PCB 缺陷数据集到底能干什么如果你手头正好有一批04_spurious_copper_12.jpg、04_spurious_copper_16.jpg这样的文件名大概率你拿到的就是一份按缺陷类别前缀命名的 PCB 缺陷数据集。这份资源的核心是 2700 余张 PCB 板面图像覆盖 6 类典型缺陷Missing_hole缺孔、Mouse_bite鼠咬、Open_circuit开路、Short短路、Spur毛刺、Spurious_copper余铜。每张图同时提供 YOLO 格式的 txt 标签和 Pascal VOC 格式的 xml 标签意味着你既可以直接喂给 YOLO 系列做检测训练也能走 VOC 路线接 Faster R-CNN、SSD 这类框架。它解决的是「手头没有工业缺陷样本、自己标注成本高、类别不均衡」这三个最现实的问题适合做 PCB 质检方向的学生、做工业视觉落地的算法工程师以及需要快速搭一个缺陷检测 baseline 的从业者。需要提前说明的是受上传体积限制公开部分约 693 张剩余部分作者通过邮箱补发这一点在动手前要心里有数。2. 数据集结构与两种标签格式先看懂目录再谈训练拿到压缩包后别急着解压完就丢进训练脚本先把目录结构和标签格式吃透否则后面报错你连是哪一层出的问题都定位不到。这一章把「文件怎么摆、两种标签怎么读、怎么互相转」讲清楚这是后面所有训练动作的地基。2.1 目录组织与文件命名规律这类数据集常见的组织方式是按缺陷类别分文件夹或者图像和标签平铺在同一目录靠文件名前缀区分。从给出的文件名看命名规则是「编号_类别名_序号.jpg」比如04_spurious_copper_12.jpg表示第 4 组、余铜缺陷、第 12 张。这种命名有个好处即使标签文件丢了你也能从文件名反推类别做数据校验时非常省事。我一般拿到手先跑一遍统计确认每类数量、有没有空标签、有没有图像和标签对不上的情况。下面这段脚本就是干这个的放在数据集根目录执行即可。import os from collections import Counter root ./PCB_DATASET # 换成你的实际路径 img_dir os.path.join(root, images) lbl_dir os.path.join(root, labels) # 统计每类图像数量按文件名前缀里的类别名 classes [Missing_hole, Mouse_bite, Open_circuit, Short, Spur, Spurious_copper] counter Counter() for f in os.listdir(img_dir): if not f.lower().endswith((.jpg, .png)): continue for c in classes: if c in f: counter[c] 1 break print(每类图像数量:, dict(counter)) # 检查图像与标签是否一一对应 imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print(有图无标签:, imgs - lbls) print(有标签无图:, lbls - imgs)逻辑说明第一段按类别名做子串匹配统计分布能快速看出六类是否均衡第二段用集合差集找出配对异常。参数上root要改成你解压后的真实路径classes列表必须和文件名里的类别拼写完全一致大小写敏感。如果输出里「有图无标签」不是空集说明这批数据需要先清洗别硬着头皮训练否则 YOLO 会直接跳过这些图你以为训了 2700 张实际可能只用了 2000 张。2.2 YOLO txt 与 VOC xml 的字段对照两种格式描述的是同一件事——目标框位置和类别但坐标系和存储方式完全不同。YOLO 的 txt 每行一个目标格式是class_id x_center y_center width height全部归一化到 0~1VOC 的 xml 用绝对像素坐标存xmin ymin xmax ymax。搞混这两个是新手最常见的翻车点训练时 loss 不降、框全跑到角落八成就是坐标系用错了。维度YOLO txtVOC xml坐标类型归一化中心点宽高绝对像素左上右下类别表示数字 id0~5字符串 name单文件目标数多行每行一个多个object节点常用框架YOLOv5/v8/v11Faster R-CNN、SSD是否需要类别映射文件需要classes.txt不需要name 直接写类别 id 的映射顺序必须固定建议按这个顺序建classes.txtMissing_hole、Mouse_bite、Open_circuit、Short、Spur、Spurious_copper对应 0 到 5。一旦训练中途改了顺序之前训的权重就废了这是血泪经验。2.3 两种格式互转的脚本实际项目里经常遇到「只有 VOC 但要训 YOLO」或者反过来。下面这个转换脚本覆盖两个方向读图尺寸拿真实宽高做归一化避免用错基准。import os import xml.etree.ElementTree as ET from PIL import Image classes [Missing_hole, Mouse_bite, Open_circuit, Short, Spur, Spurious_copper] cls2id {c: i for i, c in enumerate(classes)} def voc2yolo(xml_path, img_path, out_txt): tree ET.parse(xml_path) root tree.getroot() w int(root.find(size/width).text) h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in cls2id: continue bb obj.find(bndbox) xmin float(bb.find(xmin).text) ymin float(bb.find(ymin).text) xmax float(bb.find(xmax).text) ymax float(bb.find(ymax).text) # 转成归一化中心点宽高 xc (xmin xmax) / 2 / w yc (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls2id[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines)) def yolo2voc(txt_path, img_path, out_xml): img Image.open(img_path) w, h img.size root ET.Element(annotation) ET.SubElement(root, filename).text os.path.basename(img_path) size ET.SubElement(root, size) ET.SubElement(size, width).text str(w) ET.SubElement(size, height).text str(h) with open(txt_path) as f: for line in f: if not line.strip(): continue cid, xc, yc, bw, bh map(float, line.split()) xmin int((xc - bw / 2) * w) ymin int((yc - bh / 2) * h) xmax int((xc bw / 2) * w) ymax int((yc bh / 2) * h) obj ET.SubElement(root, object) ET.SubElement(obj, name).text classes[int(cid)] bb ET.SubElement(obj, bndbox) for k, v in zip([xmin, ymin, xmax, ymax], [xmin, ymin, xmax, ymax]): ET.SubElement(bb, k).text str(v) ET.ElementTree(root).write(out_xml)逻辑说明voc2yolo从 xml 读绝对坐标除以图像宽高做归一化中心点用(xminxmax)/2算yolo2voc反过来先乘回像素再取整。参数上要注意两点一是cls2id的顺序必须和训练时的classes.txt一致二是yolo2voc里int()截断可能让框比原图小一像素对精度要求高的场景建议用round()。转换完务必抽查几张用可视化脚本画框确认别信脚本不验证。3. 用这份数据训一个 YOLO 检测模型从环境到出权重数据看懂了接下来就是把它跑起来。这一章按「装环境 → 配数据 → 改配置 → 开训 → 看结果」的顺序走每一步都给出可抄的命令和参数含义新手照着能出权重熟手可以对照检查自己的配置有没有埋雷。3.1 环境搭建与依赖版本YOLO 系列对 PyTorch 和 CUDA 版本比较敏感版本对不上轻则警告重则直接崩。我一般用 conda 建独立环境避免污染主环境。conda create -n pcb_yolo python3.10 -y conda activate pcb_yolo # 按你的 CUDA 版本装 torch下面以 cu118 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python pillow lxml逻辑说明python3.10是当前 YOLOv8/v11 兼容性最好的版本torch 的 index-url 要和你显卡驱动支持的 CUDA 版本匹配用nvidia-smi看右上角 CUDA Version。ultralytics一个包就把 YOLOv8/v11 的训练、验证、导出全带了比早年克隆仓库改代码省事得多。装完跑一句yolo checks确认环境它会打印 torch、CUDA、设备信息这一步别省。3.2 数据集配置文件与目录规范YOLO 训练要求固定的目录结构图像和标签分开放且路径要在 yaml 里声明。建议整理成这样pcb_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── pcb.yamlpcb.yaml内容如下path: ./pcb_dataset train: images/train val: images/val nc: 6 names: [Missing_hole, Mouse_bite, Open_circuit, Short, Spur, Spurious_copper]逻辑说明path是数据集根目录train/val是相对路径nc是类别数必须和names长度一致写错了训练时类别索引会越界。划分比例常见做法是 8:2但 PCB 缺陷样本少建议按类别分层抽样保证 val 里六类都有否则验证指标会失真。划分脚本用sklearn.model_selection.train_test_split加stratify参数即可这里不展开。3.3 训练命令与关键参数配置齐了就能开训。下面这条命令是我在 8G 显存上跑通的最小可用配置yolo detect train \ data./pcb_dataset/pcb.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/pcb \ nameexp1逻辑说明modelyolov8n.pt用 nano 版先跑通流程显存不够就降到batch8imgsz640是默认输入尺寸PCB 缺陷目标偏小可以试imgsz1024但显存翻倍lr00.01是初始学习率小数据集别调太大否则 loss 震荡patience20表示 20 轮没提升就早停省时间。训练日志里重点看box_loss和mAP50前者持续不降说明标签有问题后者上不去可能是类别不均衡或学习率不对。3.4 推理与结果验证训完在runs/pcb/exp1/weights/下会有best.pt和last.pt用 best 做推理yolo detect predict \ modelruns/pcb/exp1/weights/best.pt \ source./pcb_dataset/images/val \ conf0.25 \ saveTrue逻辑说明conf0.25是置信度阈值低于它的框不显示工业场景漏检代价高可以降到 0.1 再人工复核saveTrue把画框结果存到runs/detect/predict。验证时别只看 mAP一定要肉眼看几张漏检和误检的图PCB 的 Short 和 Spurious_copper 在低分辨率下容易混这是数据本身的难点不是模型的问题。4. 避坑与排查这份数据集最容易翻车的五个地方数据、代码、环境都摆好了真正让人卡住的往往是些不起眼的细节。这一章把我在类似 PCB 缺陷数据集上踩过的坑按「现象 → 原因 → 解决」列出来遇到问题先对照排查能省下大量瞎试的时间。4.1 训练 loss 不降框全堆在图像中心现象开训几轮后box_loss卡在高位不动可视化预测框全挤在图像中央。原因YOLO 标签坐标系用错把 VOC 的绝对像素坐标直接当归一化坐标喂进去了数值远大于 1模型学不到有效位置。解决确认 txt 里每个数值都在 0~1 之间用 2.3 的转换脚本重新生成标签转换后抽查数值范围。4.2 类别索引错位预测全标成同一类现象模型能框出目标但类别几乎全是Missing_hole。原因classes.txt或 yaml 里names的顺序和生成标签时的cls2id不一致比如生成时 Short 是 3配置里写成了 2。解决全流程统一一份类别顺序文件生成标签、训练配置、推理后处理都读同一个来源别手写多份。4.3 显存溢出 CUDA out of memory现象训练刚开始就报 OOM。原因batch或imgsz超过显存容量PCB 图分辨率高时尤其明显。解决先把batch降到 8 或 4再考虑降imgsz也可以用yolo detect train ... ampTrue开混合精度显存能省三成左右。4.4 验证集 mAP 虚高但实际漏检严重现象mAP50到 0.9 以上实际推理却漏掉很多小缺陷。原因训练集和验证集划分时没分层验证集里恰好都是大目标或简单样本。解决按类别分层抽样重划数据集确保 val 里六类都有且包含小目标样本重新评估。4.5 图像与标签数量对不上训练悄悄丢样本现象明明有 2700 张图训练日志显示的样本数却少了几百。原因部分图像没有对应标签文件YOLO 默认跳过。解决用 2.1 的配对检查脚本找出缺失项要么补标签要么把这些图移出训练集别让它们静默消失。5. 进阶技巧把这份数据用到极致的两三个动作跑通 baseline 只是起点真正决定模型能不能落地的是后面这些细节。这一章讲几个我常用的进阶动作包括数据增强策略、小目标处理和模型导出都是能直接提升实际效果的。5.1 针对 PCB 缺陷的数据增强配置PCB 缺陷里 Spur 和 Spurious_copper 目标很小默认增强可能不够。YOLO 支持在训练命令里直接调增强参数yolo detect train \ data./pcb_dataset/pcb.yaml \ modelyolov8s.pt \ epochs150 \ imgsz1024 \ batch8 \ mosaic1.0 \ scale0.5 \ fliplr0.5 \ hsv_h0.015 \ hsv_s0.7逻辑说明mosaic1.0开启马赛克增强对小目标检测帮助明显scale0.5允许缩放模拟不同拍摄距离fliplr0.5水平翻转PCB 缺陷方向不敏感可以放心用hsv_h和hsv_s调色调饱和度应对不同光照的工业相机。注意imgsz1024时batch要相应降否则 OOM。5.2 小目标检测的切片推理PCB 整板图里缺陷占比很小直接缩到 640 会丢细节。常见做法是切片推理SAHI 思路把大图切成带重叠的小块分别检测再合并。核心参数是切片尺寸和重叠比例参数建议值说明slice_size640与训练输入一致overlap0.2切片间重叠避免边缘目标被切断conf0.1切片后置信度可调低靠 NMS 合并切片推理的代价是速度变慢一张整板图可能切成几十块推理时间线性增长。如果产线节拍要求高得在精度和速度之间权衡我一般先测切片方案的召回提升幅度提升不明显就不上。5.3 模型导出与部署前验证训练完的 pt 权重不能直接上产线通常要导出成 ONNX 或 TensorRT。导出命令yolo export modelruns/pcb/exp1/weights/best.pt formatonnx opset12 simplifyTrue逻辑说明opset12兼容性较好simplifyTrue会做图优化去掉冗余节点。导出后务必用同一批验证图对比 pt 和 onnx 的推理结果确认精度没有明显下降再部署。我见过导出后框偏移的案例原因是预处理里的归一化参数没对齐所以这一步的验证不能省。从那以后我每次拿到新数据集都强制先跑一遍配对检查和类别分布统计再动手训练。这份 PCB 缺陷数据集的价值在于它把六类典型缺陷和两种标签格式都备齐了省掉了最耗时的标注环节剩下的就是你怎么把它用好。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Triton源码解析:Combine Pass如何将碎片化kernel融合为一个GPU内核

Triton源码解析:Combine Pass如何将碎片化kernel融合为一个GPU内核

最近在系统性过一遍Triton源码,第一篇就挑了Combine这个Pass。起因很实际:我写的Triton kernel里按逻辑拆了两个triton.jit函数,编译完dump出MLIR,发现IR里是两个tt.func互相call。如果按这个IR直接发射到GPU,就是两次…

2026/10/13 11:18:36 阅读更多 →
LSTM时间序列预测实战:用深度学习预测病毒感染人数的完整路线

LSTM时间序列预测实战:用深度学习预测病毒感染人数的完整路线

算起来,用深度学习做病毒感染人数预测这个方向,我前前后后摸索了大半年。最初是在一个数据分析任务里,需要根据每天更新的新增感染人数,预测接下来一周的感染规模变化趋势。这个任务听起来就是典型的时间序列预测,但真…

2026/10/13 13:17:56 阅读更多 →
周志华《机器学习》代码练习包实战:从环境配置到算法实现与避坑指南

周志华《机器学习》代码练习包实战:从环境配置到算法实现与避坑指南

简介:这份资源是周志华《机器学习》一书的配套代码练习包,面向正在系统学习机器学习算法、希望动手复现经典模型的本科生、研究生及自学者。内容围绕线性模型、决策树、集成学习与支持向量机等核心章节展开,涵盖逻辑回归、LDA、Friedman 决策…

2026/10/12 1:51:02 阅读更多 →

最新新闻

SpringBoot体育馆预约系统设计与性能优化实践

SpringBoot体育馆预约系统设计与性能优化实践

1. 项目背景与核心价值体育馆场地预约系统是体育场馆数字化管理的核心工具。过去三年我参与过7个同类系统的开发实施,发现传统电话预约和纸质登记方式存在三大痛点:预约冲突频发(平均每周3-5起)、场地利用率不足(高峰时…

2026/10/14 9:06:48 阅读更多 →
USN日志+SQLite重写Everything索引:低内存搜索实现与参数优化

USN日志+SQLite重写Everything索引:低内存搜索实现与参数优化

简介:一份针对 Everything 搜索工具内存占用过高问题的优化源码包,面向遇到同类性能困扰的普通用户及软件开发者。资源基于实际使用近四年的场景,通过调整索引设置——排除系统文件、隐藏文件及特定目录,将索引文件压缩至 60K&…

2026/10/14 9:06:48 阅读更多 →
SpringBoot构建诗词平台:技术实现与传统文化融合

SpringBoot构建诗词平台:技术实现与传统文化融合

1. 项目背景与核心价值 中华诗词作为传统文化瑰宝,在数字化时代面临着传承与传播的新挑战。这个基于SpringBoot的诗词文化交流平台,本质上解决的是三个核心问题:一是经典诗词资源的数字化整合难题,二是诗词爱好者互动交流的渠道缺…

2026/10/14 9:06:48 阅读更多 →
SpringBoot诗词平台开发:智能检索与格律校验实践

SpringBoot诗词平台开发:智能检索与格律校验实践

1. 项目概述 中华诗词文化交流平台是一个基于SpringBoot框架开发的传统文化数字化项目,旨在为诗词爱好者构建集创作、鉴赏、学习、互动于一体的专业社区。这个平台解决了传统诗词文化传播中的三个核心痛点:一是线下交流渠道有限,二是初学者缺…

2026/10/14 9:06:48 阅读更多 →
Android开发:接口设计与数据共享最佳实践

Android开发:接口设计与数据共享最佳实践

1. Android接口与数据共享概述在Android应用开发中,接口设计与数据共享机制是构建复杂应用的基础能力。作为一名有五年Android开发经验的工程师,我经常需要处理不同组件间的通信和数据流转问题。合理的接口设计能让代码更易维护,而高效的数据…

2026/10/14 9:06:48 阅读更多 →
Three.js加载Gltf模型并播放动画

Three.js加载Gltf模型并播放动画

老规矩:初始化相机,场景,渲染器等,这里不过多赘述,详情看上一篇文章。 从0搭建一个3D立体场景:光影与交互全解析-CSDN博客 基本使用 只要在文件中引入这个即可: const loader new GLTFLoad…

2026/10/14 9:05:48 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →