ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PCB缺陷检测实战:VOC与YOLO双格式数据集训练YOLOv8全流程

PCB缺陷检测实战:VOC与YOLO双格式数据集训练YOLOv8全流程 简介这份资源面向从事PCB表面缺陷检测的算法工程师、深度学习学习者与工业质检方向的研究人员提供一套可直接用于目标检测训练与验证的标注数据集帮助解决缺陷样本采集难、标注成本高的问题。压缩包共1386个文件以693张jpg图像与693个xml标注文件为主整体约907.52MB图像与标注一一对应便于直接读取与转换。缺陷覆盖Missing_hole、Mouse_bite、Open_circuit、Short、Spur、Spurious_copper六类标签同时提供yolo格式txt与voc格式xml可适配YOLO系列与两阶段检测框架。数据标注精确、类别分布均匀适合训练拟合效果较好的检测模型也可用于数据增强、模型对比与消融实验。目前已有2904人学习下载具备一定参考价值。1. 从 2700 张 PCB 缺陷图说起这份数据集到底解决什么问题PCB 表面缺陷检测是工业视觉里最典型的落地场景之一但真正动手训练模型时卡住大多数人的往往不是网络结构而是数据。公开可用的 PCB 缺陷数据要么类别不全要么标注格式单一要么样本分布严重倾斜。这份数据集把 6 类常见缺陷——Missing_hole、Mouse_bite、Open_circuit、Short、Spur、Spurious_copper——整理成 2772 张图像同时提供 VOC 的 xml 和 YOLO 的 txt 两套标签省掉了格式转换这一步。它适合两类人一是想跑通 YOLO 训练全流程、但手头没有真实工业数据的学生和转行者二是需要快速验证检测方案、做 baseline 对比的算法工程师。文件名里出现的04_spurious_copper_12.jpg这类命名说明数据按缺陷类别做了前缀分组方便你按类抽样检查标注质量。下面从格式解析讲到训练、评估和排错把这份数据真正用起来。2. VOC 与 YOLO 双格式标签的解析与互转拿到压缩包后第一件事不是急着训练而是搞清楚两种标签格式的坐标体系差异。VOC 用绝对像素坐标记录左上角和右下角YOLO 用归一化后的中心点加宽高。理解这一点后面无论是写转换脚本还是排查框偏移都有依据。2.1 VOC xml 的字段结构与读取VOC 格式每张图对应一个 xml核心信息在object节点里。用 Python 解析时bndbox的四个值是绝对坐标name是类别名。import xml.etree.ElementTree as ET import os def parse_voc(xml_path): tree ET.parse(xml_path) root tree.getroot() # 图像尺寸转换 YOLO 时归一化要用 size root.find(size) w int(size.find(width).text) h int(size.find(height).text) boxes [] for obj in root.iter(object): cls_name obj.find(name).text bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) boxes.append((cls_name, xmin, ymin, xmax, ymax)) return w, h, boxes w, h, boxes parse_voc(04_spurious_copper_12.xml) print(w, h, boxes)这段代码先取图像宽高再逐个读取目标框。注意xmin等字段在部分标注工具里可能带空格float()前最好strip()一下。如果 xml 里出现difficult或truncated字段训练时可以选择性过滤但这份数据集标注较干净一般直接全用。2.2 YOLO txt 的归一化坐标与类别索引YOLO 每行是class_id cx cy w h全部归一化到 0~1。类别索引依赖一个classes.txt或data.yaml里的names顺序顺序错了模型学到的就是错类别。# 典型目录结构 dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml内容大致如下nc是类别数names顺序必须和标注时的索引一致path: ./dataset train: images/train val: images/val nc: 6 names: [Missing_hole, Mouse_bite, Open_circuit, Short, Spur, Spurious_copper]2.3 两种格式互转的脚本与常见坑从 VOC 转 YOLO 是最常见的需求核心是坐标归一化。下面这个脚本批量处理整个目录import os, glob def voc_to_yolo(xml_dir, out_dir, class_map): os.makedirs(out_dir, exist_okTrue) for xml_path in glob.glob(os.path.join(xml_dir, *.xml)): w, h, boxes parse_voc(xml_path) lines [] for cls_name, xmin, ymin, xmax, ymax in boxes: cid class_map[cls_name] cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cid} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) name os.path.splitext(os.path.basename(xml_path))[0] with open(os.path.join(out_dir, name .txt), w) as f: f.write(\n.join(lines)) class_map {Missing_hole:0,Mouse_bite:1,Open_circuit:2, Short:3,Spur:4,Spurious_copper:5} voc_to_yolo(Annotations, labels, class_map)转换时最容易踩的坑有三个一是class_map顺序和data.yaml不一致导致类别错乱二是坐标越界xmax超过图像宽度时归一化后大于 1训练会报错建议加min(max(v,0),1)裁剪三是文件名对不上图片和标签必须同名否则训练时会被当成无标签样本丢弃。对比项VOC xmlYOLO txt坐标类型绝对像素归一化 0~1单文件目标数多目标多行多目标类别表达字符串名整数索引常用框架Faster R-CNN、SSDYOLO 系列提示转换完成后随机抽 10 张图用可视化脚本画框确认框位置和类别都对再进入训练能省掉大量返工。3. 用 YOLOv8 训练 PCB 缺陷检测模型格式理清后训练本身反而是流程化的事。这一章按环境、配置、启动、监控四步走把这份数据真正喂进模型。3.1 环境配置与依赖版本YOLOv8 通过 ultralytics 包安装Python 建议 3.8~3.10。显卡驱动和 CUDA 版本要匹配否则会退回 CPU 训练速度差几十倍。conda create -n pcb python3.10 -y conda activate pcb pip install ultralytics8.1.0 # 验证 GPU 是否可用 python -c import torch; print(torch.cuda.is_available())输出True才说明 GPU 可用。如果为False检查 CUDA 版本和 torch 是否匹配常见做法是去 PyTorch 官网按驱动版本选对应安装命令重装。3.2 data.yaml 与训练参数设置数据按 8:2 划分训练和验证集。PCB 缺陷目标普遍偏小输入尺寸建议不低于 640小缺陷多时可以提到 1024但显存占用会明显上升。yolo detect train \ datadataset/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/pcb \ nameexp1参数说明model选yolov8s是精度和速度的折中数据量 2700 张用 s 或 m 都合理epochs100配合patience20表示 20 轮无提升就早停batch根据显存调整8G 显存跑 640 尺寸一般能到 16lr0是初始学习率默认 0.01 对这个小数据集够用。3.3 训练过程监控与指标解读训练启动后重点看三个指标box_loss是否稳定下降、mAP50是否上升、验证集 loss 是否过拟合。如果训练 loss 降但验证 mAP 停滞多半是数据分布或增强不够。# 训练结束后在验证集上评估 yolo detect val modelruns/pcb/exp1/weights/best.pt datadataset/data.yaml输出里mAP50和mAP50-95是核心。PCB 缺陷这类形状规整的目标mAP50 通常能到 0.9 以上如果某类特别低比如 Short 或 Spur去看该类样本量和标注框是否过小。常见做法是把混淆矩阵导出来看类别之间是否互相误判。3.4 数据增强对小缺陷的影响YOLOv8 默认开启 mosaic、HSV 抖动和随机翻转。PCB 图像背景相对固定颜色抖动幅度不宜过大否则会破坏铜箔和基板的颜色特征。# 在 data.yaml 同级建 hyp.yaml 覆盖默认增强 hsv_h: 0.010 hsv_s: 0.5 hsv_v: 0.3 mosaic: 0.5 scale: 0.3mosaic0.5表示一半概率拼接四图对小目标召回有帮助scale0.3控制缩放幅度PCB 缺陷尺寸相对稳定缩放太猛反而引入噪声。改完在训练命令里加hyphyp.yaml即可。注意增强参数没有万能值改完必须重新跑验证集对比 mAP凭感觉调参是训练里最常见的浪费。4. 推理部署与漏检误检排查模型训完只是开始真正上线要看推理速度和误检情况。这一章讲导出、推理和典型问题的定位方法。4.1 模型导出为 ONNX 与推理生产环境常用 ONNX Runtime 或 TensorRT 部署先导出再验证精度是否掉点。yolo export modelruns/pcb/exp1/weights/best.pt formatonnx opset12导出后用 onnxruntime 跑单张图对比 PyTorch 输出确认框位置一致。如果 ONNX 精度明显下降检查opset版本和输入尺寸是否和训练一致。4.2 单图与批量推理命令# 单张图推理并保存结果 yolo detect predict modelruns/pcb/exp1/weights/best.pt \ sourcetest_images/ conf0.25 saveTrue # 批量推理整个目录 yolo detect predict modelruns/pcb/exp1/weights/best.pt \ sourcetest_images/ conf0.25 iou0.45 save_txtTrueconf0.25是置信度阈值漏检多就调低到 0.15误检多就调高到 0.4iou0.45控制 NMS 重叠阈值同类目标密集时适当调高避免框被抑制。4.3 漏检与误检的定位思路漏检优先查三处标注框是否过小被增强裁掉、该类样本量是否过少、conf阈值是否过高。误检优先查背景样本是否混入、类别索引是否错位。下面这段脚本可以统计每个类别的检出数量和标注数量对比from collections import Counter import glob, os cnt Counter() for txt in glob.glob(runs/pcb/exp1/labels/*.txt): with open(txt) as f: for line in f: cnt[int(line.split()[0])] 1 print(cnt) # 对比各类标注总数偏差大的类重点排查如果某类检出数远低于标注数基本可以判定该类漏检严重回去看该类样本的框尺寸分布。现象可能原因处理方向某类全漏类别索引错位核对 data.yaml 顺序小目标漏检输入尺寸偏小imgsz 提到 1024背景误检负样本不足加入无缺陷图框偏移坐标转换错误重查归一化脚本5. 提升 PCB 缺陷检测精度的一个实用技巧前面流程跑通后想把 mAP 再往上推一档最有效的往往不是换更大的模型而是处理类别不均衡和难例。这份数据集 6 类缺陷分布相对均匀但 Spur 和 Spurious_copper 在视觉上接近容易互相误判这是精度瓶颈的主要来源。一个具体做法是把这两类的混淆样本单独抽出来做针对性增强。先用验证结果生成混淆矩阵定位误判对再对易混类别做 copy-paste 增强把一类目标贴到另一类背景上强制模型学习区分特征。import cv2, random, os def paste_aug(img_path, label_path, out_img_dir, out_lbl_dir, times3): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: lines [l.strip() for l in f if l.strip()] for i in range(times): aug img.copy() new_lines lines[:] # 随机选一个框做小幅平移后重新贴回模拟位置变化 for line in lines: cid, cx, cy, bw, bh map(float, line.split()) dx random.uniform(-0.05, 0.05) dy random.uniform(-0.05, 0.05) new_lines.append(f{int(cid)} {cxdx:.6f} {cydy:.6f} {bw:.6f} {bh:.6f}) name faug_{i}_ os.path.basename(img_path) cv2.imwrite(os.path.join(out_img_dir, name), aug) with open(os.path.join(out_lbl_dir, name.replace(.jpg,.txt)), w) as f: f.write(\n.join(new_lines))这段脚本对每个样本生成若干带位置扰动的副本增加模型对位置变化的鲁棒性。times控制扩增倍数一般 2~3 倍即可太多会导致过拟合到合成样本。扩增后重新训练重点观察 Spur 和 Spurious_copper 的混淆是否下降。另一个技巧是推理时用 TTA测试时增强YOLO 支持通过augmentTrue开启yolo detect predict modelbest.pt sourcetest_images/ augmentTrue conf0.2TTA 会对输入做多尺度翻转推理再融合mAP 通常能涨 1~2 个点代价是推理速度下降约 3 倍适合对精度敏感、对延迟不敏感的场景。上线前用同一批测试图对比开启前后的漏检率再决定是否保留。本文还有配套的精品资源点击获取
返回列表