基于PaddleX的钢铁缺陷检测挑战赛实现方案
比赛链接 https://aistudio.baidu.com/aistudio/competition/detail/114

本程序是基于 https://aistudio.baidu.com/aistudio/projectdetail/442375 实现的钢铁缺陷检测挑战赛的目标识别代码,需要注意的是PaddleX已经推出2.0,有需要的小伙伴可以基于 https://aistudio.baidu.com/aistudio/projectdetail/2160238 更新一下操作内容

本文主要的代码篇幅在于进行数据预处理,真正的应用PaddleX的代码非常简单,并且新手友好!

根据官方文档,所有的PaddleX都由三步组成:

步骤 说明
第1步 定义transforms 用于定义模型训练、验证、预测过程中,输入图像的预处理和数据增强操作
第2步 定义datasets 用于定义模型要加载的训练、验证数据集
第3步 定义模型开始训练 选择需要的模型,进行训练
为了快速展示整个代码,代码中epoch为10,实际上我2021-08-29 16:21提交的csv对应的学习器使用epoch=300,得分为4.49872

epoch=300训练的模型保存在Trained300model.zip,想要验证训练后的模型效果直接解压,并在 章节:进行检测 将读取模型的代码model=pdx.load_model(saved_model_dir) 中的模型路径 saved_model_dir 换为解压后的模型路径即可。

如解压后模型路径为’Trained300model/output/yolov3_darknet53/best_model’ 则读取模型应写为 model = pdx.load_model(‘Trained300model/output/yolov3_darknet53/best_model’)

本文的代码流程为 准备工作(下载包+解压数据+其他准备工作)->正式进行训练工作(配置训练参数+训练)->预测->写文件

准备工作
安装需要的PaddleX版本
In [3]

安装paddlex

需要注意paddlex1对于版本有所要求,所以最好更新对应的包版本

!pip install “numpy<=1.19.5” -i https://mirror.baidu.com/pypi/simple
!pip install “paddlex<2.0.0” -i https://mirror.baidu.com/pypi/simple
解压数据
数据集已经直接被放在./work/目录下,直接解压即可

In [1]

解压文件并移除多余的目录

! unzip work/train.zip -d ./work/
! rm -f -r work/__MACOSX
! unzip work/test.zip -d ./work/
! rm -f -r work/__MACOSX
准备配置文件
PaddleX的使用需要提供分类标签文件label.txt在这里插入图片描述
以及图片-xml的链接文件train_list.txt val_list.txt,分别用于验证和训练在这里插入图片描述
下面将遍历训练图片并生成对应的train_list.txt val_list.txt

In [2]
import os

遍历训练集

name = [name for name in os.listdir(‘work/train/IMAGES’) if name.endswith(‘.jpg’)]

train_name_list=[]
for i in name:
tmp = os.path.splitext(i)
train_name_list.append(tmp[0])

构造图片-xml的链接文件ori_train.txt

with open(“./work/train/ori_train.txt”,“w”) as f:
for i in range(len(train_name_list)):
if i!=0: f.write(‘\n’)
line=‘IMAGES/’+train_name_list[i]+‘.jpg’+" "+“ANNOTATIONS/”+train_name_list[i]+‘.xml’
f.write(line)

构造label.txt

labels=[‘crazing’,‘inclusion’,‘pitted_surface’,‘scratches’,‘patches’,‘rolled-in_scale’]
with open(“./work/train/labels.txt”,“w”) as f:
for i in range(len(labels)):
line=labels[i]+‘\n’
f.write(line)

将ori_train.txt随机按照eval_percent分为验证集文件和训练集文件

eval_percent 验证集所占的百分比

import random
eval_percent=0.2;

data=[]
with open(“work/train/ori_train.txt”, “r”) as f:
for line in f.readlines():
line = line.strip(‘\n’)
data.append(line)

index=list(range(len(data)))
random.shuffle(index)

构造验证集文件

cut_point=int(eval_percent*len(data))
with open(“./work/train/val_list.txt”,“w”) as f:
for i in range(cut_point):
if i!=0: f.write(‘\n’)
line=data[index[i]]
f.write(line)

构造训练集文件

with open(“./work/train/train_list.txt”,“w”) as f:
for i in range(cut_point,len(data)):
if i!=cut_point: f.write(‘\n’)
line=data[index[i]]
f.write(line)
正式进行训练工作
引入包并设为GPU训练,如果没有GPU则使用CPU训练
In [2]
import matplotlib
matplotlib.use(‘Agg’)
import os
os.environ[‘CUDA_VISIBLE_DEVICES’] = ‘0’
import paddlex as pdx
定义图像处理流程transforms
直接对https://aistudio.baidu.com/aistudio/projectdetail/442375进行一个完整的复刻和抄袭,主要是进行一些数据增强的操作

In [3]
from paddlex.det import transforms
train_transforms = transforms.Compose([
transforms.MixupImage(mixup_epoch=250),
transforms.RandomDistort(),
transforms.RandomExpand(),
transforms.RandomCrop(),
transforms.Resize(target_size=608, interp=‘RANDOM’),
transforms.RandomHorizontalFlip(),
transforms.Normalize(),
])

eval_transforms = transforms.Compose([
transforms.Resize(target_size=608, interp=‘CUBIC’),
transforms.Normalize(),
])
定义数据集Dataset
这里还是对参考代码的抄袭,但是要把训练集等的配置路径全部换成我们之前定义好的路径

In [4]
train_dataset = pdx.datasets.VOCDetection(
data_dir=‘work/train’,
file_list=‘work/train/train_list.txt’,
label_list=‘work/train/labels.txt’,
transforms=train_transforms,
shuffle=True)
eval_dataset = pdx.datasets.VOCDetection(
data_dir=‘work/train’,
file_list=‘work/train/val_list.txt’,
label_list=‘work/train/labels.txt’,
transforms=eval_transforms)
2021-08-29 12:24:32 [INFO] Starting to read file list from dataset…
2021-08-29 12:24:33 [INFO] 1120 samples in file work/train/train_list.txt
creating index…
index created!
2021-08-29 12:24:33 [INFO] Starting to read file list from dataset…
2021-08-29 12:24:34 [INFO] 280 samples in file work/train/val_list.txt
creating index…
index created!
正式训练
下面直接一键训练,在至尊版GPU上,我测试时使用epochs=300大约需要3h时间,下面为了快速看到效果,直接设置epoch=10

In [5]
num_classes = len(train_dataset.labels)
model = pdx.det.YOLOv3(num_classes=num_classes, backbone=‘DarkNet53’)
model.train(
num_epochs=10,
train_dataset=train_dataset,
train_batch_size=8,
eval_dataset=eval_dataset,
learning_rate=0.000125,
lr_decay_epochs=[210, 240],
save_interval_epochs=200,
save_dir=‘output/yolov3_darknet53’,
use_vdl=True)
进行预测
在这一步可以刷新内存,甚至重启了!因为刚刚的训练过程已经将模型保存了,之后直接读入就好。

遍历文件夹获得需要检测的图片列表
test数据是在之前和train数据一起解压的,这里就直接遍历文件夹即可~

如果有小伙伴为了保护存储器删除了数据,还请重新解压一次如果一路运行下来什么都没进行操作就直接运行就可以了

In [1]
import os
name = [name for name in os.listdir(‘work/test/IMAGES’) if name.endswith(‘.jpg’)]

test_name_list=[]
for i in name:
tmp = os.path.splitext(i)
test_name_list.append(tmp[0])
进行检测
有时候重启后会读入错误,可以等会儿或者刷新页面,因为之前训练的文件需要一段时间之后才能在notebook中同步成功。

模型预测结果为: [{‘category_id’: int64, ‘bbox’: float:[x,y,x_length,y_length], ‘score’: float, ‘category’: str}, {‘category_id’: int64, ‘bbox’: float:[x,y,x_length,y_length], ‘score’: float, ‘category’: str},…]

其中,category_id是编号,bbox是锚框,score是置信度,category是类别名称。需要注意bbox的格式和题目中格式不同,这里分别表明了框的左上角坐标,以及长宽长度,题目要求为左上角坐标和右下角坐标;这里的编号和题目中编号并不对应,所以需要根据类别信息进行转化。

In [4]
import paddlex as pdx

读取模型

model = pdx.load_model(‘output/yolov3_darknet53/best_model’)

建立一个标号和题目要求的id的映射

num2index={‘crazing’:0,‘inclusion’:1,‘pitted_surface’:2,‘scratches’:3,‘patches’:4,‘rolled-in_scale’:5}

result_list = []

将置信度较好的框写入result_list

for index in test_name_list:
image_name = ‘work/test/IMAGES/’+index+‘.jpg’
predicts = model.predict(image_name)
for predict in predicts:
if predict[‘score’]<0.5: continue;
# 将bbox转化为题目中要求的格式
tmp=predict[‘bbox’]
tmp[2]+=tmp[0]
tmp[3]+=tmp[1]
line=[index,tmp,num2index[predict[‘category’]],predict[‘score’]]
result_list.append(line)
2021-08-29 17:48:51 [INFO] Model[YOLOv3] loaded.
将结果写入目标文件
将上述list转化为csv就可以直接提交了!

In [5]
import numpy as np
result_array = np.array(result_list)

import pandas as pd
df = pd.DataFrame(result_array,columns=[‘image_id’,‘bbox’,‘category_id’,‘confidence’])

df.to_csv(‘submission.csv’,index=None)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/ipykernel_launcher.py:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify ‘dtype=object’ when creating the ndarray.

结果可视化
结果可视化并不是本题的需求,但是根据测试结果进行可视化观察是非常有意义的~

这里我保存了epoch=300的训练后模型,来看看模型的运行效果吧~

In [16]
!unzip -oq /home/aistudio/Trained300model.zip -d /home/aistudio/Trained300model

import paddlex as pdx
model = pdx.load_model(‘Trained300model/output/yolov3_darknet53/best_model’)
index = ‘1554’
image_name = ‘work/test/IMAGES/’+index+‘.jpg’
predicts = model.predict(image_name)
pdx.det.visualize(image_name, predicts, threshold=0.5, save_dir=‘./output/yolov3_darknet53/testImage/’)
2021-08-29 17:11:30 [INFO] Model[YOLOv3] loaded.
2021-08-29 17:11:32 [INFO] The visualized result is saved as ./output/yolov3_darknet53/testImage/visualize_1554.jpg
可以从./output/yolov3_darknet53/testImage/中找到对应的图片,已经看到1554号测试图片被定位了3个位置在这里插入图片描述
请点击此处查看本环境基本用法.
Please click here for more detailed instructions.

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐