ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PCB缺陷检测数据集实测:基于YOLOv9的训练全流程与避坑指南

PCB缺陷检测数据集实测:基于YOLOv9的训练全流程与避坑指南 简介面向PCB质检、工业视觉与深度学习算法工程师该数据集提供1297张电路板缺陷图片及YOLOv9格式标注可直接用于训练、验证与调优缺陷检测模型。压缩包共2000个文件zip格式约120.79MB按文件类型统计为1297个txt标注、702张jpg图像和1个yaml配置其中txt记录缺陷类别与归一化坐标yaml定义训练路径与类别信息jpg为板面原始图像整体采用接近Roboflow导出的目录结构便于快速接入YOLO系列流程。据资源方描述该数据集在PCB缺陷检测识别任务上可达99.8%准确率适合作为模型评估基准或工程验证数据也可用于复现实验和横向对比各类检测算法。目标检测工程师无需额外转换即可开展实验也适用于边缘端部署前的精度验证。已有434人浏览学习能够显著降低数据采集与标注成本加快PCB缺陷识别方案的原型迭代。1. PCB电路板缺陷检测数据集实测1297张图的YOLOv9标注到底能干什么PCB电路板缺陷检测在机器视觉圈子里一直是个“看起来容易、做起来麻烦”的方向。麻烦不在算法而在数据真实产线上的缺陷图像不流通、标注成本高、缺陷分布又散。这份数据集把1297张PCB图片用YOLOv9格式标注好了声称识别准确率99.8对想快速验证YOLOv9流程的人来说确实值得认真拆一遍。我把它下载后完整跑了一轮训练与推理复现先说结论数据质量在可用水平以上但99.8是个有条件的结果不能直接当产线指标来交差。它的合理定位是给刚接触缺陷检测的同学当全流程练习数据或者给算法工程师做小样本模型选型的基线。想直接把它推上产线还需要按后面的章节再做一轮体检和专项调优。新手照着步骤能跑通熟手能从这里看到数据组织方式对结果的影响边界。2. 数据集解剖从Roboflow文件名到YOLOv9标注坐标2.1 文件名暴露的三类数据来源打开压缩包第一眼看到的是6_PNG_jpg.rf.9d8afdf3c8af9092dd5497554d1020e0.jpg、IMG_6850_JPG_jpg.rf.58867852aab90335cf2e984959199108.jpg、middle_PNG_jpg.rf.e108238c9803ac99cfc629a78a6bac0b.jpg这类命名。.rf.后面跟着一串哈希是Roboflow平台导出数据时留下的标记也就是说这份数据在Roboflow上做过在线标注或格式转换不是完全手工整理的原始图片集。文件名前缀分别指向三种拍摄来源。6_PNG、12_PNG这类带数字前缀的大概率来自公开的PCB缺陷检测基准图库原始图像是整张PCB大板被切成若干子图IMG_6850这类以IMG开头的是现场用普通相机拍摄的光照和角度都不统一middle_PNG是中间角度拍摄的板面特写。三类图像混在一起有个好处模型不会只见过单一光照风格泛化性有一定保障。坏处也明显——如果划分train/val时不小心同一张大板切出的子图会同时落在训练集和验证集里导致验证指标虚高这就是后面避坑章节里“兄弟图泄漏”的根源。下载包解压后应该被组织成YOLOv9标准目录结构路径作用images/train训练图像images/val验证图像images/test测试图像labels/train训练标注txtlabels/val验证标注txtlabels/test测试标注txt如果解压后是散落的文件常见做法是写一段脚本按文件名把jpg和同名txt归位到对应目录。文件名中的.rf.哈希保留即可它不参与训练但能帮你溯源出原始数据来自哪个平台批次。提示.rf.是Roboflow导出的痕迹训练时不需要对它做任何处理不必删除也没必要较真。2.2 标注文本解析与坐标回算YOLOv9的标注文件和YOLOv8/v5一样每行一个目标框格式是class_id x_center y_center width height四个坐标值都做了归一化处理落在0到1之间。拿到数据后我最先做的事不是训练而是统计类别分布确定各类别的框数量级这决定了后面一整轮训练策略。import os from collections import Counter label_dir labels/train vis_counter Counter() total 0 empty_files 0 for name in os.listdir(label_dir): if not name.endswith(.txt): continue path os.path.join(label_dir, name) lines [ln.strip() for ln in open(path, r, encodingutf-8) if ln.strip()] if not lines: empty_files 1 continue for line in lines: cls int(line.split()[0]) vis_counter[cls] 1 total 1 print(类别分布:, dict(sorted(vis_counter.items()))) print(总框数:, total, 空标注文件:, empty_files)这段代码遍历标签目录逐行读取每个txt取每行第一个字段作为类别ID并计数同时统计空标注文件数量。Counter是Python自带的计数容器line.split()[0]切出class_idint()转为整数方便后面排序输出。如果你发现某一类框数只有几十个而另一类上千个后续必须做类别过采样或加权否则少数类缺陷几乎训不出来。空标注文件数量如果超过总图片数的10%说明数据里大量是正常板这对负样本是好事但推理阶段要把误检控制提上日程。坐标换算公式是像素坐标等于归一化坐标乘以图片宽高。我一般会随机抽三五个标注框转成像素坐标画在原图上肉眼确认标注框是否贴合缺陷边界。这一步看着土却能拦下Roboflow导出时可能出现的坐标错位、类别ID与names列表错位这类哑雷。PCB缺陷检测的常见类别包括short、open_circuit、spur、missing_hole、mouse_bite、spurious_copper但这份数据集的names不一定和这份清单完全一致要以data.yaml实际定义为准。2.3 训练前必做的数据体检数据体检不是给新手增加负担而是避免把数据问题误判成模型问题。体检至少做三件事全量md5去重、检查图像尺寸分布、抽查标注框质量。md5去重为什么重要因为6_PNG_jpg.rf.xxx.jpg和12_PNG_jpg.rf.xxx.jpg很可能从同一张大板导出像素就算不完全相同内容也高度重叠。不处理等于给模型喂重复数据验证集同样可能混入相似图片mAP结果不可信。检查图像尺寸分布则需要确认所有图片是否统一规格Roboflow导出通常会统一resize但如果个别宽高比异常letterbox预处理会把图像压变形小缺陷特征跟着失真。标注质量的抽样核对我推荐用Python配合OpenCV画框可视化代码量不大import cv2 img_path images/train/6_PNG_jpg.rf.9d8afdf3c8af9092dd5497554d1020e0.jpg label_path img_path.replace(images, labels).replace(.jpg, .txt) img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as fp: for line in fp: cls_id, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cls_id)), (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1) cv2.imwrite(check_visual.jpg, img)这段代码把txt标注反向映射到像素坐标并画框循环里map(float, line.split())把标注行解析为浮点数框左上角(x1, y1)由中心坐标减去宽高一半得到右下角(x2, y2)则是中心坐标加宽高一半。cv2.putText里的字体参数用默认真值即可重点是输出图能直观看到框和缺陷边缘是否贴合。抽样看几十张图如果标注框和缺陷边缘有明显偏移先修数据再训练不值得为坏数据烧算力。到这一步数据端的准备工作才算结束。下一章进入环境搭建和训练参数配置。3. 用YOLOv9训练PCB缺陷检测环境、配置与参数详解3.1 YOLOv9训练环境搭建与两个隐藏依赖YOLOv9官方仓库是WongKinYiu/yolov9训练代码基于PyTorch实现。我复现时采用Python 3.9 PyTorch 1.13.1 CUDA 11.7这套组合跑过多轮没有意外。PyTorch 2.x也能跑但梯度累积的数值表现和部分算子在细节上有差异对照别人的训练日志时不要盲目对齐。git clone https://github.com/WongKinYiu/yolov9.git cd yolov9 pip install -r requirements.txt pip install thop pycocotoolsrequirements.txt覆盖了核心依赖但有两项经常漏装。thop用于计算模型FLOPs缺了它train.py在打印模型参数量和计算量时会直接中断报错信息还不直观。pycocotools用于COCO风格的mAP评估val.py要计算混淆矩阵和各类别AP时依赖它缺了评估会退化成简化模式很多调试信息看不到。这两个包虽然不参与反向传播但少了它们你会多花半小时排错。安装完成后用nvidia-smi确认显存可用然后进入数据集配置环节。3.2 配置data.yaml与模型YAMLYOLOv9的data.yaml是数据集和训练流程的连接器path字段建议写绝对路径。train、val、test依次指向对应目录nc要和names列表长度一致类别顺序就是模型输出层的顺序。path: /data/pcb_yolov9 train: images/train val: images/val test: images/test nc: 6 names: 0: short 1: open_circuit 2: spur 3: missing_hole 4: mouse_bite 5: spurious_coppernc是类别总数必须与names列表长度一致names顺序一旦确定训练中途不要调整否则已保存权重的类别索引全部错位。path用绝对路径是因为YOLOv9在相对路径解析上不同commit行为不稳定绝对路径直接规避问题。如果这份数据集的类别和names与上面示例不一致以实际标注的class_id为准先把names改成一一对应再训练。模型配置层面yolov9-c和yolov9-e是两种主流选择。c版参数量小训练速度快内存占用低在1297张图的小样本场景下足够e版参数量大、上限更高但过拟合风险也更大。除非你打算配合大量数据增强拉长训练周期否则小样本数据直接上e版容易看到loss下降却看不到mAP同步上涨。我的复现采用yolov9-c预训练权重初始化迁移学习收敛快且稳定也符合绝大多数PCB检测项目的实际资源条件。3.3 训练命令与参数选型的取舍python train.py --data data/pcb.yaml --cfg cfg/models/9/yolov9-c.yaml \ --weights yolov9-c.pt --batch-size 16 --epochs 120 --imgsz 640 \ --device 0 --workers 8 --project runs/pcb_yolov9 --name baseline--imgsz这一项值得展开PCB缺陷本来就是小目标640是底线降到512会让鼠咬和短路这类微小缺陷在特征图上只剩两三个像素升到1280能显著提升小目标召回但显存占用成倍增加1297张图下过拟合风险也同步抬升。--batch-size的调整逻辑直接显存够就16显存不够就降到8同时把--epochs适当拉到150补偿梯度更新次数。--workers按CPU核心数设置8是常规值过高会导致数据加载和训练进度条不同步看起来像卡死实际是在等IO。训练过程中我要盯三个指标。第一个是loss曲线小样本训练loss往往降得很快但出现V型反弹或者突然跳变就要警惕很可能是学习率过大或梯度异常。第二个是验证集的mAP0.5和mAP0.5:0.95前者的判断依据是能不能框住目标后者对框定位精度的要求更苛刻PCB缺陷检测这种小目标场景mAP0.5:0.95比mAP0.5更能反映真实水平。第三个是精确率和召回率的平衡产线上宁可多召回几个可疑点让人复检也不能漏掉真实缺陷如果R明显偏低推理阶段就应该降低置信度阈值。数据增强上我一般会改--hyp指定的hyp.yaml把mosaic概率调到1.0copy_paste调到0.3。mosaic把四张图拼成一张等效于扩充了小样本数据copy_paste把某个缺陷目标复制粘贴到其他背景图上对缺陷这种稀疏目标很有效。小样本训练的本质就是靠增强策略扩大有效样本密度这两个开关是我最常调的棋子。训练日志里如果mAP_0.5和mAP_0.5:0.95长期拉不开差距通常说明框定位不准此时优先检查标注质量和imgsz而不是继续加epochs。4. PCB缺陷检测训练避坑指南小样本数据集上的四个经典翻车场景4.1 验证集mAP虚高现场推理全部走样现象训练时验证集mAP轻松冲到80%以上甚至接近99.8的宣传数字但拿同一份权重去测新拍的PCB图片漏检明显指标和实际表现严重不符。原因典型的“兄弟图泄漏”。同一张PCB大板被切成多个子图划分train/val时如果按文件名随机分配同一块板的兄弟图会同时出现在训练集和验证集。验证集和训练集内容高度相似模型相当于在开卷考试mAP虚高在所难免。这个坑在Roboflow导出的数据里尤其隐蔽因为导出时会自动做数据集划分但划分逻辑并没有按源图去重。解决按文件名前缀分组把同一源图产生的所有子图放进同一个集合再划分train/val/test。常见做法是先提取文件名前缀建立分组再按组随机抽样。划分完成后重新训练mAP会明显下降但那才是真实基线。从那以后我拿到任何数据集都先看文件名结构再谈指标这个习惯帮我避开过好几轮无效调参。4.2 少数类缺陷训不出来loss曲线正常但召回率接近零现象spur或者spurious_copper这类出现次数少的类别训练过程中mAP一直不涨打开混淆矩阵这一类的召回率几乎是0。原因PCB缺陷天然是长尾分布短接和开路这类缺陷样本多毛刺和多铜样本少。YOLOv9的分类loss虽然有正负样本平衡机制但面对几十比一的悬殊比例模型学不到少数缺陷的有效特征。这和轴承缺陷检测、螺栓缺陷检测里遇到的长尾问题本质相同都是数据分布决定模型能力的上限。解决数据端方案比模型端更直接。把少数类图片在训练集里重复拷贝按2到3倍过采样让模型每个epoch都多看到几次这些样本。也可以把hyp.yaml里的mosaic和copy_paste概率提高让少数类缺陷周边上下文参与拼接增加装饰性特征的同时保持原图语义。如果过采样和增强都做了还是没效果再考虑在已收敛的模型上冻结backbone前几层用较小学习率专门对少数类做几轮微调。4.3 小目标缺陷直接消失几个像素的鼠咬看不见现象mouse_bite这类宽度只有几个像素的缺陷验证时几乎检不出偶尔检出的框偏移明显算出来的IoU很低导致mAP被明显拉低。原因归一化坐标在640分辨率下换算成像素宽高可能只有三四像素经过两轮下采样特征图上的响应已经接近消失后续算子根本没有机会提取到这个目标。这是目标检测里小目标问题的典型表现PCB缺陷检测因为它特有的微小尺寸翻车概率比通用目标检测高得多。解决把--imgsz从640抬到1280是最直接的路径小缺陷在输入图上所占像素增加特征图上的响应强度会有质变。显存不够就做切片推理把大图切成多个重叠patch分别过模型再汇总结果。切片的边长一般取640重叠率50%能在速度和召回之间找到平衡。推理时间翻倍的问题需要实测如果产线不能接受再用TensorRT做算子融合补偿回来但不要指望既有分辨率提升又完全不做耗时优化。4.4 对干净板子误检一堆假框模型没见过负样本现象模型在含缺陷的图上表现不错切到正常无缺陷的板子刷出一排置信度不低的假框把正常铜箔走线的边缘纹理误判成短路或毛刺。原因训练集里大量是有缺陷的子图正常无缺陷区域占比极低。模型没有充分见过空地长什么样自然会把高对比度纹理当成目标。这种问题在异常检测里同样普遍跟MVTec AD这类标准基准不同真实产线数据的负样本分布更复杂误检率也更难控制。解决往训练集里加负样本。最简单的做法是收集正常PCB板图片标注文件留空让模型把这些图当背景学习。如果没有现成的干净板图就从误检热图里挑误检集中的区域手工裁剪后作为负样本补进训练集。加入负样本之后推理阶段把--conf-thres从默认0.25提高到0.4或0.5能有效压掉低置信度假框代价是漏检率略微上升阈值选取需要在验证集上重新校准。这四个坑处理完模型才算真正见过世面。接下来要做的就是用一套规范的验证流程确认模型的能力边界到底在哪。5. 推理验证与针对性优化把数据集的真实价值逼出来5.1 训练后推理验证用批次输出看清问题训练完成后先用批量推理跑一遍验证集把预测结果保存成图片和txt这样能把训练日志里的数字翻译成图片上框的位置和置信度直观看到模型在哪些图上翻车。python detect.py --weights runs/pcb_yolov9/baseline/best.pt \ --source data/pcb_yolov9/images/val \ --conf-thres 0.25 --iou-thres 0.45 \ --save-txt --save-conf --project runs/pcb_validate--save-txt会把每个预测框写成txt--save-conf在每行末尾附加置信度分数。跑完后我优先翻三类图真实缺陷被漏检的、假框落在背景上的、两个不同类别框高度重叠的。漏检说明特征不足以区分目标背景假框说明负样本不足两框重叠说明NMS阈值不匹配或类别定义边界模糊。这种逐图观察方式比盯着mAP数字更接近问题本质。5.2 混淆矩阵与类别层面的差异分析val.py生成的confusion_matrix.png是评估产出里最值得看的图。对角线决定整体准确率最后一行代表背景误检。我最关注的是相邻类别之间是否大面积互相串比如spur和spurious_copper之间。一旦出现系统性混淆先怀疑标注标准不一致把这两类的标注重新拉出来对比通常能找到一批边界模糊的框。修正标注比换模型更有效这个结论在这个场景下适用过很多次。5.3 推理延迟与模型瘦身1297张图训练出的yolov9-c权重大约50MB做演示系统直接跑PyTorch推理没问题上产线建议导出为ONNX再转TensorRT的engine文件单帧耗时可以压缩到几毫秒级别。导出时注意ONNX里不要带NMS算子NMS留给推理框架处理否则转engine时容易遇到奇怪的算子错误。如果延迟还是超标把模型从yolov9-c换成yolov9-t轻量化配置重新训练一轮用精度换速度这也是小样本数据场景里更务实的取舍。从那以后我每次拿到缺陷检测数据集不管来源多正规都强制走一套固定流程先统计类别分布、按源图分组做数据划分、用最小配置跑通baseline、再看混淆矩阵定位系统性误判最后针对小目标和少数类做专项增强。这套流程看起来繁琐但比反复“训练—看mAP—改参数”的盲目试错靠谱得多。尤其是1297张图这种小样本场景数据的组织方式对最终结果的贡献往往大于模型选择的名字。希望这个复现过程能帮你少踩几个坑把时间留给真正影响产线落地效果的推理优化上。本文还有配套的精品资源点击获取
返回列表