
简介面向工业视觉与电子制造质检场景这套PCB缺陷检测数据集覆盖桥接、缺件、短路、断路、偏移、极性错误六类典型线路板瑕疵共680张已标注图像可直接用于YOLO系列模型训练与算法验证适合高校《机器视觉》课程实训、电子制造企业质检算法预研及入门学习者实践。包体内共1376个文件693个txt为YOLO格式标注框680张jpg为原始图像另含data.yaml配置与训练缓存文件整体压缩后77.85MB目录结构清晰便于批量读取。每张图像均采用归一化五元组标注按7:2:1划分训练、验证与测试集类间分布均衡并附中文使用指南、MD5校验清单及缺陷分布分析脚本可帮助快速完成从数据加载、模型微调到结果可视化的完整流程。此数据集在YOLOv8n模型上测试集mAP达到86.3%可作为入门基准参考。目前已有26人学习下载是轻量级、可直接落地的PCB缺陷检测实训数据集。1. PCB缺陷检测数据集为什么680张图也能撑起一个YOLO项目做过产线AOI相关的朋友都懂真正麻烦的不是算法选型是手里根本没有像样的缺陷样本。PCB板上的开路、短路、鼠咬这类缺陷良品率一高想攒一套带标注的数据比登天还难。所以当我看到这套6类、680张的PCB缺陷检测数据集时第一反应是量不大但够用了。它是标准的YOLO格式每张图对应同名txt标注文件类别覆盖了PCB缺陷检测里最常碰到的六种情况拿到就能直接喂给YOLOv5或YOLOv8训练不用自己费劲去转格式。适合谁如果你是做课程设计、算法预研、或者想验证某个缺陷检测思路能不能跑通这套数据正好卡在麻雀虽小五脏俱全的档位上。下面我从数据格式讲起把训练、推理、踩坑一条龙过一遍。2. 数据集结构与YOLO标注格式先搞懂文件布局再动手2.1 六类缺陷分别是什么类名与典型特征这套数据集的类别设计沿用了PCB缺陷检测里最经典的六分类体系分别对应板卡制造过程中最常见的六类异常。识别这六类缺陷靠的是图像上的形态差异断路open表现为本该连通的走线中间出现断开缺口短路short则是两条不该碰到的走线粘连在一起鼠咬mousebite是走线边缘出现规则的小半圆缺口像被老鼠啃过毛刺spur是走线上多出来一小段尖锐凸起铜面异物copper是铜箔区域出现多余的铜渣或异常沉积针孔pin-hole是铜面上出现极小的圆孔反射特征和周围明显不同。从检测难度上看open和short这类缺陷面积相对大、纹理结构清晰YOLO模型学起来比较容易而pin-hole和mousebite目标尺寸小、特征弱是拉低mAP的主要来源。680张图里这六类并不是均匀分布的open和short的样本量通常明显多于其他四类这一点在训练之前心里要有数后面避坑章节我会专门讲类别不平衡的处理。至少拿到数据后第一件事不是直接开训而是按下面脚本统计一下每个类到底有多少框。2.2 YOLO标签文件解读归一化坐标不是像素坐标YOLO格式的标签文件是纯文本每行代表一个目标框格式是五个字段class_id x_center y_center width height。这里最容易翻车的地方是后面四个数不是像素值而是相对图像宽高的归一化比例。比如一行标签是2 0.5234 0.3187 0.0821 0.0458意思是这个目标属于类别2鼠咬框的中心点落在图像宽度52.34%、高度31.87%的位置框的宽度占图像宽度8.21%、高度占图像高度4.58%。为什么YOLO非要这么设计因为训练时dataloader会把图像统一缩放到imgsz尺寸如果标注存的是原始像素坐标缩放后坐标全错乱了归一化坐标是比例值图像不管缩放到多大比例关系不变。这一点如果你之前用过VOC格式的XML标注存的是绝对像素坐标转YOLO时容易踩坑。常用的转换公式是center_x (x_min x_max) / 2 / img_widthcenter_y (y_min y_max) / 2 / img_heightwidth (x_max - x_min) / img_widthheight (y_max - y_min) / img_height。四舍五入保留6位小数足够训练用了。在动手训练之前建议把标签文件打开看几行。一般数据集目录结构是images/放原图、labels/放同名txt、classes.txt里按行写六类名称、data.yaml里配置路径和类别数。拿到资源后先把目录结构敲一遍确认别直接往训练代码里灌路径。2.3 标签质量校验一个脚本看出所有问题我拿到任何标注数据第一步永远不是训练而是写脚本全量扫一遍标签。680张图说多不多但手工标注难免有框出界、类别号错了、宽高为零等问题。这些脏数据直接进YOLO训练轻则loss异常重则训练直接崩。下面这个脚本可以统计每类框数量、检查坐标越界和宽高非法建议放在数据集根目录下运行。from pathlib import Path from collections import Counter def validate_labels(label_dir: Path, img_w: int 640, img_h: int 640): issues [] class_counter Counter() total_boxes 0 for txt_path in sorted(label_dir.glob(*.txt)): for line_no, line in enumerate(txt_path.read_text(encodingutf-8).splitlines(), 1): parts line.split() if len(parts) ! 5: issues.append((txt_path.name, line_no, f字段数不是5实际为{len(parts)})) continue try: cls_id, cx, cy, w, h map(float, parts) except ValueError as e: issues.append((txt_path.name, line_no, ffloat解析失败: {e})) continue class_counter[cls_id] 1 total_boxes 1 if not (0 cls_id 5): issues.append((txt_path.name, line_no, fclass_id越界: {int(cls_id)})) if w 0 or h 0: issues.append((txt_path.name, line_no, f宽高非正: w{w:.4f}, h{h:.4f})) if max(abs(cx - 0.5), abs(cy - 0.5)) 0.52 or w 1.02 or h 1.02: issues.append((txt_path.name, line_no, f归一化坐标疑似越界: {line})) print(f总框数: {total_boxes}) for cls_id in sorted(class_counter.keys()): print(f类别 {int(cls_id)}: {class_counter[cls_id]} 个框) if issues: print(f发现 {len(issues)} 个问题:) for name, line_no, desc in issues[:30]: print(f {name}:{line_no} - {desc}) else: print(所有标签文件检查通过) return class_counter, issues if __name__ __main__: validate_labels(Path(labels))这段脚本的核心逻辑是逐行解析五个字段先检查字段数量是否等于5再做float转换最后做三类合法性判断类别号是否在0到5之间、框宽高是否大于0、归一化坐标是否严重越界。第三类判断用了中心点偏离阈值和宽高上限因为实际标注时偶尔会有轻微越界比如框贴边超出0.5%超过2%的越界基本就是标注失误了这类样本要么退回重标要么手动改掉。脚本跑完会输出每类的框数量和前30条问题记录方便定位具体是哪个文件哪一行出错。跑完这个脚本你对这份数据集的健康状况就有底了。如果open和short占了过半的框剩下四类每类只有几十个框那训练策略就得往数据增强和类别平衡方向倾斜。3. 基于YOLOv8的PCB缺陷检测实战从训练到推理全流程3.1 环境准备ultralytics版本与显卡选型训练这套数据集推荐直接用ultralytics库YOLOv8和YOLO11都支持接口一致。装环境这一步很简单但容易出幺蛾子我习惯用Python 3.9以上的干净虚拟环境来装。执行下面的命令就能把推理和训练依赖一次装齐。pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple如果只是训练这个680张的小数据集CPU也能跑但一个epoch可能要几分钟到十几分钟100个epoch下来很折磨。建议有NVIDIA显卡就装上CUDA版的PyTorch显存6GB以上跑yolov8n和yolov8s都够。装完用下面命令确认GPU可用python -c import torch; print(torch.cuda.is_available())输出True说明CUDA环境没问题输出False就先去装对应版本的PyTorch。注意PyTorch的CUDA版本要跟显卡驱动匹配别上来就装最新版老卡配新CUDA容易翻车。3.2 数据集划分与data.yaml配置数据集里的680张图默认不会给你分好train/val/test。我的习惯是用脚本按8:1:1划分划分前先pip install scikit-learn用train_test_split做分层随机抽样确保每个子集里六类框的比例跟全集接近。import shutil from pathlib import Path from sklearn.model_selection import train_test_split base_dir Path(.) images sorted((base_dir / images).glob(*.jpg)) train_imgs, val_imgs train_test_split(images, test_size0.2, random_state42) val_imgs, test_imgs train_test_split(val_imgs, test_size0.5, random_state42) for split in [train, val, test]: (base_dir / split / images).mkdir(parentsTrue, exist_okTrue) (base_dir / split / labels).mkdir(parentsTrue, exist_okTrue) def move_files(img_list, split): for img in img_list: label base_dir / labels / (img.stem .txt) shutil.move(str(img), str(base_dir / split / images)) shutil.move(str(label), str(base_dir / split / labels)) move_files(train_imgs, train) move_files(val_imgs, val) move_files(test_imgs, test)划分完了之后项目目录结构就变成train/images、train/labels、val/...、test/...这样。random_state42是为了让你的随机结果可复现方便和别人对实验结论如果你第一次划分后模型效果很差换一个seed重新划分对比是个可行的调优思路。接下来写data.yaml配置文件。注意路径建议写绝对路径省的每次换机器都要改。文件内容如下path: /data/pcb_defect # 数据集根目录的绝对路径 train: train/images val: val/images test: test/images nc: 6 names: 0: open 1: short 2: mousebite 3: spur 4: copper 5: pin-holenc是类别总数6names里的顺序必须和标签txt里的class_id严格对应。如果classes.txt的排序是另一回事务必改data.yaml的映射而不是去改几百个txt文件。3.3 训练参数为什么从yolov8n开始很多新手一上来就选yolov8x觉得模型越大约好结果680张图训出来的效果甚至不如yolov8n。小数据集配大模型模型参数远多于样本蕴含的信息量妥妥过拟合。我的做法是以yolov8n.pt为起点它只有约300万参数训练速度快还能加载COCO预训练权重做迁移学习。yolo detect train \ datapcb.yaml \ modelyolov8n.pt \ epochs120 \ imgsz640 \ batch16 \ patience20 \ lr00.005 \ save_dirruns/pcb_train训练命令的参数解释如下epochs120给足迭代空间配合patience20让它在验证集连续20轮不涨时自动早停省时间也防过拟合imgsz640是标准输入分辨率PCB缺陷属于中小目标这个尺寸够用batch16是显存限制下的保守值6GB显存跑yolov8n毫无压力lr00.005比默认的0.01低一半小数据集用稍低学习率能避免前期震荡。训练过程要盯着两个指标训练loss和验证集mAP。loss稳步下降说明模型在拟合mAP在验证集上逐步上升说明泛化在变好。如果train_loss降很快但val_mAP一直不动就是过拟合信号提前停或换更小的模型。训练结束后所有结果在runs/pcb_train/目录下weights里同时有best.pt验证集最优和last.pt最后一轮实际用best.pt。3.4 推理验证单张图和批量测试训练完用best.pt对测试集跑一轮推理看看模型在没参与训练的数据上表现如何。yolo detect predict \ modelruns/pcb_train/weights/best.pt \ sourcetest/images \ conf0.35 \ iou0.45 \ saveTrueconf0.35是对应置信度阈值低于这个值的检测结果会被过滤掉iou0.45是NMS去重阈值同一位置多个重叠框时只保留分数最高的。这两个参数不是固定的缺陷检测场景如果漏检多就把conf调低到0.25如果误检多就调到0.5试。saveTrue会把标好框的图片存到runs/detect/predict/。推理完一定要人眼看图尤其是测试集里的每张图都翻一遍。YOLO的mAP是数值指标但落在具体图片上可能有些框位置偏得离谱。我见过mAP挺高但所有pin-hole框都往右下偏移半个身位的情况这种系统误差只能靠看图发现。4. 避坑680张小数据集最容易翻车的五个场景4.1 类别不平衡mAP好看某一类全漏现象训练完看results.png里mAP0.5有0.78画面上挺好看但翻开每类的PR曲线mousebite的recall只有0.3pin-hole甚至0.2都不到。原因680张图里open和short占了将近一半框而mousebite和pin-hole一共只有几十个框模型把大部分容量花在了学大类特征上。解决第一选择是补充小类样本没有渠道的话就用增强硬顶。ultralytics里把copy_paste开大一点数据loader会在线做随机复制粘贴增强把小类目标复制到其他图上等于变相扩充了小类样本量。训练完看confusion_matrix.png而不是只看results.png能直观看出哪些类互相混。4.2 标签坐标越界导致训练异常现象训练到中途突然报AssertionError或loss变成nan而且报错每次出现在不同epoch。原因标签txt里存在越界框归一化坐标超过了0~1范围比如手工标注时把框拖到了画布外面存下来cx1.12。dataloader在做目标匹配时遇到这种异常数据就崩了。解决训练前先跑一遍2.3节的校验脚本把越界报错的文件全部找出来。修复方案是把越界坐标clip到合法范围内对每个框执行cx min(max(cx, 0), 1)注意clip完之后w和h可能超出边界需要同步修正中心点。这种问题在买来的数据里不罕见必须提前扫。4.3 模型过拟合train_loss掉得飞快val不再涨现象train_loss大概第30轮就降到0.05但val mAP卡在0.6左右再也上不去后边甚至往下掉。原因680张图的信息量有限yolov8m以上规模的模型参数量远超过数据所能约束的范围就开始背训练集细节。解决先从yolov8n开始这是我在小数据集上屡试不爽的起点同时用早停patience20防止在过拟合区间空跑。如果n模型mAP正常再考虑按顺序试s、m每换一个型号必须对比val指标不是越大越好。4.4 图像尺寸不一模型稳定但检测飘忽现象训练过程loss正常没有报错但检测效果总是不稳定同一块板子换个角度测就漏检。原因数据集里混了不同分辨率的图片有的640x640有的1920x1080训练时dataloader统一缩放到640后小图上清晰的目标在大图上被严重压缩特征丢失。解决训练前把所有图片统一处理推荐批量resize到640x640再启动训练这一步顺便把标注的相对坐标验证一遍。做法是遍历images目录用OpenCV的resize统一尺寸标签不用动归一化坐标天然适配resize。4.5 数据增强参数过猛把PCB纹理都改了现象训练loss收敛得漂亮但实际拍的新板子检测效果差一截。原因增强参数设置太激进hsv_h0.5把铜面的色调随机改得面目全非mosaic1.0把四张图拼在一起时缺陷框被裁掉或缩小。PCB缺陷检测场景和自然图像不同铜面颜色和纹理是检测的重要线索过度增强会把特征抹掉。解决把hsv增强调低hsv_h0.01、hsv_s0.3左右mosaic降到0.5到0.6开启close_mosaic10让最后10轮训练不用mosaic用完整图像做精调。这套参数在PCB铜面缺陷上比默认增强稳得多。5. 把680张图用出性价比迁移学习半冻结与验证习惯5.1 半冻结训练先训head再全量微调小数据集从头训YOLO风险太大但直接全量微调预训练权重也不是最优。我会先冻结backbone只更新检测头跑30轮等loss降到平稳区域再解冻全部层用更低学习率微调。这个策略在ultralytics里通过代码控制比较方便它在训练小数据集时能把过拟合风险压到很低的水平。我一般在跑这个PCB数据集时会单独做一组对比半冻结策略和直接全量训练后者val mAP通常低3到5个点。5.2 增强参数的定量参照给一组经过验证的参数参考适合PCB铜面缺陷这类小目标场景hsv_h0.01、hsv_s0.2、hsv_v0.2、degrees15、scale0.3、mosaic0.5、copy_paste0.3、close_mosaic10。这套参数主要是保住PCB板原始的铜面和纹理特征同时通过mosaic和copy_paste补足小类样本。旋转角度控制在15度以内是因为PCB走线有强方向性转过90度后断路和短路的特征语义会发生混淆训练出来的模型更容易误判。5.3 验证时的三个习惯我跑完一轮训练不会直接下结论。第一打开results.png和confusion_matrix.png对比每一类的PR和误判方向第二从测试集里挑一个batch的推理结果图用肉眼确认框的位置和尺寸是否贴合缺陷轮廓第三单独统计每一类的mAP而不是只看整体平均——整体mAP被大类拉高之后小类缺陷的漏检问题很容易被掩盖。这个习惯是吃过亏才养成的。有一次我训练完看到mAP有0.76就兴冲冲上线实测结果pin-hole一个都没抓住返工了大半天才意识到单类指标才是关键。从那以后我每次跑完PCB缺陷检测训练都强制走一遍校验脚本、单类PR曲线、肉眼抽查推理图的流程一步都不省。希望帮到你。本文还有配套的精品资源点击获取