(1)数据集简介
PKU-Market-PCB 印刷电路板 (PCB) 瑕疵数据集是一个公共合成 PCB 数据集,包含 1,386 张图像,具有 6 种缺陷(漏孔、鼠咬、开路、短路、杂散、杂铜),可用于图像检测、分类和配准任务。

图1 原图
(2)数据集下载
北京大学智能机器人开放实验室
https://robotics.pkusz.edu.cn/resources/dataset/pcb_cnn数据集_数据集-飞桨AI Studio星河社区
https://aistudio.baidu.com/datasetdetail/320762 其中,第一种方法是百度云下载(速度慢),第二种方法是飞桨(速度快,格式是适合YOLO的)-----推荐第2种下载方式。
![]()
图2 下载结果

图3 解压原件


图4 (a)images文件夹内容;(b)pcb_cocoanno文件夹内容
(3)数据集转换(json格式转换)
步骤1:前期数据分析,对数据做进一步了解。(此步骤可省略)【其中train.json文件地址为图4中的文件地址】
import json
from collections import defaultdict
import matplotlib.pyplot as plt# 修改1
with open("E:\\datasets\\PCB\\PCB_DATASET\\Annotations\\train.json") as f:data = json.load(f)imgs = {}
for img in data['images']:imgs[img['id']] = {'h': img['height'],'w': img['width'],'area': img['height'] * img['width'],}hw_ratios = []
area_ratios = []
label_count = defaultdict(int)
for anno in data['annotations']:hw_ratios.append(anno['bbox'][3]/anno['bbox'][2])area_ratios.append(anno['area']/imgs[anno['image_id']]['area'])label_count[anno['category_id']] += 1print(label_count, len(data['annotations']) / len(data['images']))plt.hist(hw_ratios, bins=100, range=[0, 2])
plt.show()plt.hist(area_ratios, bins=100, range=[0, 0.005])
plt.show()
'''
结果如下:
(defaultdict(int, {3: 399, 5: 416, 2: 435, 6: 447, 4: 412, 1: 418}),4.261382799325464)
1、从标签来看,总共6个类别,如果加上背景类,总共7个类别;
2、各类别之间的框数量相对较平均,不需要调整默认的损失函数。(如果类别之间相差较大,建议调整损失函数,如BalancedL1Loss);
3、平均每张图的框数量在4张左右,属于比较稀疏的检测;
4、真实框的宽高比,可以看到大部分集中在1.0左右,但也有部分在0.5-1之间,少部分在1.25-2.0之间;
5、真实框在原图的大小比例,可以看到大部分框只占到了原图的0.1%,甚至更小,因此基本都是很小的目标。
'''
步骤2:转换代码(将图4中的train.json和val.json文件夹的代码转换为标签,转换前建立相应的路径结构。如图5所示)

图5 数据集
其中images是存放图片的,labels存放对应图片的标签的。
代码:
import json
import os# 注意运行2次,train/val
# 修改1 json存储地址
json_path = "D:\\project\\yolov5\\yolov5-5.0\\yolov5-5.0-1\\data\\pcb\\pcb_cocoanno\\val.json"
# # 修改2,保存位置yolo存储地址
yolo_paths = "D:\\project\\yolov5\\yolov5-5.0\\yolov5-5.0-1\\dataset\\labels\\val2017"with open(json_path) as f:data = json.load(f)imgs = {}
for img in data['images']:imgs[img['id']] = {'h': img['height'],'w': img['width'],'file_name': img['file_name'],}tmp = ''
for anno in data['annotations']:print(imgs[anno['image_id']]['file_name'])if imgs[anno['image_id']] != tmp:txt_path = os.path.join(yolo_paths, imgs[anno['image_id']]['file_name'].split('.')[0] + '.txt')txt_file = open(txt_path, 'w')# xywh --> xywh(归一化)bbox = [anno['bbox'][0] / imgs[anno['image_id']]['w'],anno['bbox'][1] / imgs[anno['image_id']]['h'],anno['bbox'][2] / imgs[anno['image_id']]['w'],anno['bbox'][3] / imgs[anno['image_id']]['h']]cls_id = anno['category_id']# 保存txt_file.write(str(cls_id) + ' ' + " ".join([str(a) for a in bbox]) + "\n") # 生成格式0 cx,cy,w,htmp = imgs[anno['image_id']]else:# xywh --> xywh(归一化)bbox = [anno['bbox'][0] / imgs[anno['image_id']]['w'],anno['bbox'][1] / imgs[anno['image_id']]['h'],anno['bbox'][2] / imgs[anno['image_id']]['w'],anno['bbox'][3] / imgs[anno['image_id']]['h']]cls_id = anno['category_id']# 保存txt_file.write(str(cls_id) + ' ' + " ".join([str(a) for a in bbox]) + "\n") # 生成格式0 cx,cy,w,h
注释:
json_path指的是图4中文件val.json的地址。
json_paths指的是图5中,labels文件夹下,val文件夹的地址。
此代码运行2次,分别将train.json和val.json文件代码进行转换。
步骤3:生成训练集和验证集
注意:由于已有train2017和val2017的labels文件夹,直接按名字移动图像到对应文件夹即可。
代码:
import os
import shutilImages_path = 'E:\\datasets\\PCB\\PCB_DATASET\\images' # 源图路径train_labels = 'E:\\datasets\\PCB\\PCB_DATASET\\labels\\train2017' # train标签路径
val_labels = 'E:\\datasets\\PCB\\PCB_DATASET\\labels\\val2017' # val标签路径train_images = 'E:\\datasets\\PCB\\PCB_DATASET\\images\\train2017' # 保存train图像路径
val_images = 'E:\\datasets\\PCB\\PCB_DATASET\\images\\val2017' # 保存val图像路径# 判断文件夹是否存在,不存在即创建
if not os.path.exists(train_images):os.mkdir(train_images)
if not os.path.exists(val_images):os.mkdir(val_images)# 按照标签名移动对应图像
for label_name in os.listdir(train_labels):img_name = label_name[:-3] + 'jpg' # txt2jpgshutil.move(os.path.join(Images_path, img_name), os.path.join(train_images, img_name))for label_name in os.listdir(val_labels):img_name = label_name[:-3] + 'jpg' # txt2jpgshutil.move(os.path.join(Images_path, img_name), os.path.join(val_images, img_name))
到此,数据集已经制作好,包括images(train2017与val2017)和labels(train2017与val2017)文件夹!
4 模型训练及可视化
4.1 创建数据集yaml文件
注意:路径一定填对,类别与id一定要对应!!!
创建ultralytics\cfg\datasets\PCB.yaml文件,内容如下:
path: E:\\datasets\\PCB\\VOCdevkit\\VOC2007 # dataset root dir
train: images/train2017 # train images (relative to 'path') 4 images
val: images/val2017 # val images (relative to 'path') 4 images# Classes for DOTA 1.0
names:0: missing_hole1: mouse_bite2: open_circuit3: short4: spur5: spurious_copper
视频参考:
6-PCB电路板缺陷检测_模型训练_哔哩哔哩_bilibili
资料参考:
飞桨PaddlePaddle-源于产业实践的开源深度学习平台
接下来,以fast rcnn为例进行演示
代码:
项目目录预览 - PaddleDetection:PaddleDetection - 一个基于 PaddlePaddle 的目标检测开发套件,提供丰富的模型和工具,适用于进行计算机视觉和深度学习研究的程序员。 - GitCode

在此路径下,新建一个目录,名为work.