★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>
生成常用验证码识别,基于PaddleOCR训练识别
零.背景
在一些传统网站或者App中登录需要验证码,验证码的形态各异,有数字,英文,中文,图形,问答。本项目通过PaddleOCR实现验证码的生成,数据预处理,训练,评估和模型导出
PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力开发者训练出更好的模型,并应用落地。
一.环境安装
# 安装 PaddleOCR
%cd /home/aistudio/work
!git clone https://gitee.com/paddlepaddle/PaddleOCR.git
!pip install -r PaddleOCR/requirements.txt --user
%cd PaddleOCR/
# 下载英文PP-OCRv3的预训练模型
!wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/english/en_PP-OCRv3_rec_train.tar
# 解压模型参数
%cd pretrain_models
!tar -xf en_PP-OCRv3_rec_train.tar && rm -rf en_PP-OCRv3_rec_train.tar
二.生成数据集
分别生成训练集,验证码集和测试集,放在 /work/datas/目录下
txt文件中默认请将图片路径和图片标签用 \t 分割,如用其他方式分割将造成训练报错。
图像文件名 图像标注信息
train_data/rec/train/word_001.jpg 简单可依赖
train_data/rec/train/word_002.jpg 用科技让复杂的世界更简单
...
import random
from PIL import Image, ImageDraw, ImageFont
class Datas(object):
def __init__(self):
self.dataPath = '/home/aistudio/work/datas/'
def run(self):
trainNums = 800
vaildNums = 200
testNums = 100
self.trains(trainNums)
self.vailds(vaildNums)
self.tests(testNums)
def trains(self, nums):
filename = self.dataPath+'/train.txt'
f = open(filename, 'w')
for i in range(nums):
text = self.text(4)
self.create(text, 'train')
f.write(self.dataPath+"train/"+text+".png\t"+text)
f.write("\n")
def vailds(self, nums):
filename = self.dataPath+'/vaild.txt'
f = open(filename, 'w')
for i in range(nums):
text = self.text(4)
self.create(text, 'vaild')
f.write(self.dataPath+"vaild/"+text+".png\t"+text)
f.write("\n")
def tests(self, nums):
filename = self.dataPath+'/test.txt'
f = open(filename, 'w')
for i in range(nums):
text = self.text(4)
self.create(text, 'test')
f.write(self.dataPath+"test/"+text+".png\t"+text)
f.write("\n")
def text(self, length):
strs = 'abcdefghijklmnopqrstuvwxyz0123456789'
res = ""
for i in range(length):
w = strs[random.randint(0, len(strs)-1)]
w = w.upper() if random.randint(0,1) == 0 else w
res += str(w)
return res
def create(self, text, mode):
bg_color = (random.randrange(20, 120), random.randrange(20, 120), random.randrange(150, 255))
width = 400
height = 100
im = Image.new('RGB',(width,height),bg_color)
# 创建画笔对象
draw = ImageDraw.Draw(im)
# 构造字体对象
font = ImageFont.truetype('font.ttf', 80)
#font = ImageFont.load_default().font
# 构造字体颜色
fontcolor = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
draw.text((random.randint(10, 30), (random.randint(0, 10))), text[0], font=font, fill=fontcolor)
draw.text((random.randint(90, 130), (random.randint(0, 10))), text[1], font=font, fill=fontcolor)
draw.text((random.randint(180, 230), (random.randint(0, 10))), text[2], font=font, fill=fontcolor)
draw.text((random.randint(270, 330), (random.randint(0, 10))), text[3], font=font, fill=fontcolor)
#调用画笔的point()函数绘制噪点
for i in range(0, 10000):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
draw.point(xy, fill=fill)
#释放画笔
del draw
# im.show()
im.save(f'./datas/{mode}/{text}.png','png')
# 创建验证码图片
%cd /home/aistudio/work
!python datas.py
三.训练
这里使用英文PP-OCRv3模型进行训练,其配置文件在 PaddleOCR/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml
# 替换当前配置文件
%cd /home/aistudio/work
!cp -r en_PP-OCRv3_rec.yml PaddleOCR/configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml
/home/aistudio/work
需要设置训练接和验证集的路径:data_dir字段和label_file_list字段
如需要可视化,可以设置use_visualdl 为true
设置预训练模型路径字段 pretrained_model
Global:
debug: false
use_gpu: true
epoch_num: 500
log_smooth_window: 20
print_batch_step: 10
save_model_dir: ./output/v3_en_mobile # 设置模型保存路径
save_epoch_step: 3
eval_batch_step: [0, 2000]
cal_metric_during_train: true
pretrained_model: /home/aistudio/work/PaddleOCR/pretrain_models/en_PP-OCRv3_rec_train/best_accuracy # 设置预训练模型路径
checkpoints:
save_inference_dir: ./output/inference
use_visualdl: true # 设置可视化
infer_img: doc/imgs_words/ch/word_1.jpg
character_dict_path: ppocr/utils/en_dict.txt
max_text_length: &max_text_length 25
infer_mode: false
use_space_char: true
distributed: true
save_res_path: ./output/rec/predicts_ppocrv3_en.txt
Optimizer:
name: Adam
beta1: 0.9
beta2: 0.999
lr:
name: Cosine
learning_rate: 0.001
warmup_epoch: 5
regularizer:
name: L2
factor: 3.0e-05
Architecture:
model_type: rec
algorithm: SVTR
Transform:
Backbone:
name: MobileNetV1Enhance
scale: 0.5
last_conv_stride: [1, 2]
last_pool_type: avg
Head:
name: MultiHead
head_list:
- CTCHead:
Neck:
name: svtr
dims: 64
depth: 2
hidden_dims: 120
use_guide: True
Head:
fc_decay: 0.00001
- SARHead:
enc_dim: 512
max_text_length: *max_text_length
Loss:
name: MultiLoss
loss_config_list:
- CTCLoss:
- SARLoss:
PostProcess:
name: CTCLabelDecode
Metric:
name: RecMetric
main_indicator: acc
ignore_space: False
Train:
dataset:
name: SimpleDataSet
data_dir: /home/aistudio/work/datas/train # 设置数据集路径
ext_op_transform_idx: 1
label_file_list:
- /home/aistudio/work/datas/train.txt # 设置标签路径
transforms:
- DecodeImage:
img_mode: BGR
channel_first: false
- RecConAug:
prob: 0.5
ext_data_num: 2
image_shape: [48, 320, 3]
max_text_length: *max_text_length
- RecAug:
- MultiLabelEncode:
- RecResizeImg:
image_shape: [3, 48, 320]
- KeepKeys:
keep_keys:
- image
- label_ctc
- label_sar
- length
- valid_ratio
loader:
shuffle: true
batch_size_per_card: 128
drop_last: true
num_workers: 4
Eval:
dataset:
name: SimpleDataSet
data_dir: /home/aistudio/work/datas/vaild # 设置数据集路径
label_file_list:
- /home/aistudio/work/datas/vaild.txt # 设置标签路径
transforms:
- DecodeImage:
img_mode: BGR
channel_first: false
- MultiLabelEncode:
- RecResizeImg:
image_shape: [3, 48, 320]
- KeepKeys:
keep_keys:
- image
- label_ctc
- label_sar
- length
- valid_ratio
loader:
shuffle: false
drop_last: false
batch_size_per_card: 128
num_workers: 4
# 开始训练
%cd /home/aistudio/work/PaddleOCR/
!python3 tools/train.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml
# 断点训练
%cd /home/aistudio/work/PaddleOCR/
!python3 tools/train.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.checkpoints=./output/v3_en_mobile/iter_epoch_100
数据模型可视化结果
四.评估
训练中模型参数默认保存在Global.save_model_dir目录下。在评估指标时,需要设置Global.checkpoints指向保存的参数文件。评估数据集可以通过 configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml 修改Eval中的 data_dir 和 label_file_list 设置
# GPU 评估, Global.checkpoints 为待测权重
%cd /home/aistudio/work/PaddleOCR/
!python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.checkpoints=./output/v3_en_mobile/best_accuracy
五.预测
Global.pretrained_model:使用的权重
Global.infer_img:待预测的图片路径
# 预测图片
%cd /home/aistudio/work/PaddleOCR/
!python3 tools/infer_rec.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.pretrained_model=output/v3_en_mobile/best_accuracy Global.infer_img=/home/aistudio/work/datas/test/3zE8.png
六. 模型导出+预测
# 模型导出
# -c 后面设置训练算法的yml配置文件
# -o 配置可选参数
# Global.pretrained_model 参数设置待转换的训练模型地址,不用添加文件后缀 .pdmodel,.pdopt或.pdparams。
# Global.save_inference_dir参数设置转换的模型将保存的地址。
%cd /home/aistudio/work/PaddleOCR/
!python3 tools/export_model.py -c configs/rec/PP-OCRv3/en_PP-OCRv3_rec.yml -o Global.pretrained_model=./pretrain_models/en_PP-OCRv3_rec_train/best_accuracy Global.save_inference_dir=./inference/en_PP-OCRv3_rec/
# 使用导出模型进行预测
# image_dir 图片路径
# rec_model_dir 导出模型路径
# rec_char_dict_path 字段路径,当前项目选用的是
# rec_image_shape 图片信息shape 同配置文件 image_shape 保持一致
# rec_char_dict_path 字段路径,当前使用英文字典,根据实际情况选择
!python3 tools/infer/predict_rec.py --image_dir="/home/aistudio/work/datas/test/3zE8.png" --rec_model_dir="./inference/en_PP-OCRv3_rec/" --rec_image_shape="3, 48, 320" --rec_char_dict_path="./ppocr/utils/en_dict.txt"
PaddleOCR内置了一部分字典,可以按需使用。
ppocr/utils/ppocr_keys_v1.txt 是一个包含6623个字符的中文字典
ppocr/utils/ic15_dict.txt 是一个包含36个字符的英文字典
ppocr/utils/dict/french_dict.txt 是一个包含118个字符的法文字典
ppocr/utils/dict/japan_dict.txt 是一个包含4399个字符的日文字典
ppocr/utils/dict/korean_dict.txt 是一个包含3636个字符的韩文字典
ppocr/utils/dict/german_dict.txt 是一个包含131个字符的德文字典
ppocr/utils/en_dict.txt 是一个包含96个字符的英文字典
七. 总结
通过PaddleOCR 可以快速搭建训练,评估,导出,预测模型,完成验证码的识别工程。通过更换不同的预训练模型,可以二次训练出不同的验证码识别模型,支持中英文和其他多语种。