1、主要参考
(1)大佬教程
基于PaddleDetection的PCB瑕疵检测_AI Studio的博客-CSDN博客
(2)blibli视频
253-14_PCB电路板缺陷检测_项目配置文件_dec_哔哩哔哩_bilibili
(3)coco数据集说明
『深度应用』目标检测coco数据集格式介绍 - 腾讯云开发者社区-腾讯云
2、模型的下载
(1)下载地址
北京大学智能机器人开放实验室
印刷电路板(PCB)瑕疵数据集。它是一个公共合成PCB数据集,包含1386张图像,具有6种缺陷(漏孔、鼠咬、开路、短路、杂散、杂铜),用于图像检测、分类和配准任务
3、模型的特征查看
(1)查看各个缺陷的分布情况(类别数是否均匀,如果不均匀可以考虑调整loss的计算方法)
(2)查看锚框的长宽比,看看都是什么形状的
(3)看看锚框的大小(和原图大小的比值,看看是不是都是小物体)
(4)文件pcb_dataset_analysis.py如下
import json
from collections import defaultdict
import matplotlib.pyplot as plt
%matplotlib inline
with open("/home/aistudio/work/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']] += 1
#查看各个缺陷的分布情况(类别数是否均匀,如果不均匀可以考虑调整loss的计算方法)
print( 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()
4、下载paddle的object项目
4.1 下载
(1)paddle官网
飞桨PaddlePaddle-源于产业实践的开源深度学习平台
(2)下载指定PaddleDetection
(3)对应的github地址如下
https://github.com/PaddlePaddle/PaddleDetection
4.2安装相关环境
#(1)在对应目录下
conda activate chenpaddle_cp310
#(2)安装相关环境
pip install -r requirements.txt
5、配置和训练
???
6、基于PP-YOLOE+的PCB缺陷检测
(1)以下引用参考来自paddle官网
基于PP-YOLOE+的PCB缺陷检测 - 飞桨AI Studio基于PP-YOLOE+实现的PCB缺陷检测方案全流程实战,覆盖训练、调优、部署等 - 飞桨AI Studiohttps://aistudio.baidu.com/aistudio/projectdetail/4670836
黑盒教程真有意思 :(
(2)其中ppyoloe_plus_crn_m_80e_obj365_pretrained_pcb.yml内容如下
_BASE_: [
'./_base_/pcb_detection.yml',
'../../runtime.yml',
'../_base_/optimizer_80e.yml',
'../_base_/ppyoloe_plus_crn.yml',
'../_base_/ppyoloe_plus_reader.yml',
]
log_iter: 100
snapshot_epoch: 5
weights: output/ppyoloe_plus_crn_m_80e_coco_pretrained_pcb/model_final
pretrain_weights: https://bj.bcebos.com/v1/paddledet/models/ppyoloe_plus_crn_m_80e_coco.pdparams
depth_mult: 0.67
width_mult: 0.75
(3)'./_base_/pcb_detection.yml',文件如下
metric: COCO
num_classes: 6
TrainDataset:
!COCODataSet
image_dir: images
anno_path: pcb_cocoanno/train.json
dataset_dir: dataset/PCB_coco/
data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']
EvalDataset:
!COCODataSet
image_dir: images
anno_path: pcb_cocoanno/val.json
dataset_dir: dataset/PCB_coco/
TestDataset:
!ImageFolder
anno_path: pcb_cocoanno/val.json # also support txt (like VOC's label_list.txt)
dataset_dir: dataset/PCB_coco/ # if set, anno_path will be 'dataset_dir/anno_path'
(4)'../../runtime.yml',文件内容如下
use_gpu: true
use_xpu: false
log_iter: 20
save_dir: output
snapshot_epoch: 1
print_flops: false
# Exporting the model
export:
post_process: True # Whether post-processing is included in the network when export model.
nms: True # Whether NMS is included in the network when export model.
benchmark: False # It is used to testing model performance, if set `True`, post-process and NMS will not be exported.
fuse_conv_bn: False
(5) '../_base_/optimizer_80e.yml',内容如下
epoch: 80
LearningRate:
base_lr: 0.001
schedulers:
- !CosineDecay
max_epochs: 96
- !LinearWarmup
start_factor: 0.
epochs: 5
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0005
type: L2
(6)ppyoloe_plus_crn.yml
architecture: YOLOv3
norm_type: sync_bn
use_ema: true
ema_decay: 0.9998
ema_black_list: ['proj_conv.weight']
custom_black_list: ['reduce_mean']
YOLOv3:
backbone: CSPResNet
neck: CustomCSPPAN
yolo_head: PPYOLOEHead
post_process: ~
CSPResNet:
layers: [3, 6, 6, 3]
channels: [64, 128, 256, 512, 1024]
return_idx: [1, 2, 3]
use_large_stem: True
use_alpha: True
CustomCSPPAN:
out_channels: [768, 384, 192]
stage_num: 1
block_num: 3
act: 'swish'
spp: true
PPYOLOEHead:
fpn_strides: [32, 16, 8]
grid_cell_scale: 5.0
grid_cell_offset: 0.5
static_assigner_epoch: 30
use_varifocal_loss: True
loss_weight: {class: 1.0, iou: 2.5, dfl: 0.5}
static_assigner:
name: ATSSAssigner
topk: 9
assigner:
name: TaskAlignedAssigner
topk: 13
alpha: 1.0
beta: 6.0
nms:
name: MultiClassNMS
nms_top_k: 1000
keep_top_k: 300
score_threshold: 0.01
nms_threshold: 0.7
(7)ppyoloe_plus_crn.yml
worker_num: 4
eval_height: &eval_height 640
eval_width: &eval_width 640
eval_size: &eval_size [*eval_height, *eval_width]
TrainReader:
sample_transforms:
- Decode: {}
- RandomDistort: {}
- RandomExpand: {fill_value: [123.675, 116.28, 103.53]}
- RandomCrop: {}
- RandomFlip: {}
batch_transforms:
- BatchRandomResize: {target_size: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768], random_size: True, random_interp: True, keep_ratio: False}
- NormalizeImage: {mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none}
- Permute: {}
- PadGT: {}
batch_size: 8
shuffle: true
drop_last: true
use_shared_memory: true
collate_batch: true
EvalReader:
sample_transforms:
- Decode: {}
- Resize: {target_size: *eval_size, keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none}
- Permute: {}
batch_size: 2
TestReader:
inputs_def:
image_shape: [3, *eval_height, *eval_width]
sample_transforms:
- Decode: {}
- Resize: {target_size: *eval_size, keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none}
- Permute: {}
batch_size: 1