概述
如何生成类似下面的验证码?不同旋转角度,不同大小,不同字符间隙
之前找到过一个单个字符的旋转方案,这里给出的多字符的验证码旋转方案也是基于单字符的旋转cv2.getRotationMatrix2D。
以上面7个字符的验证码为例,我们需要在7张画布上的不同位置生成旋转好的字符,最后再将7张图片叠加起来,就是我们想要的了。
代码
代码生成图片演示案例:
代码demo如下:
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2
import random
string = 'PCCOXU'
char_location = [0, 6]
font_size = 35
tff_file = 'captcha.ttf' # 替换为自己的字体文件
font_style = ImageFont.truetype(tff_file, font_size, encoding="utf-8")
img_wh = (150, 50)
font_color = (32, 64, 160)
img_result = np.zeros((img_wh[1], img_wh[0], 3), dtype='uint8')
for index, char in enumerate(string):
# 创建画板,画上单个字符
img_data = Image.new("RGB", img_wh, (255,255,255))
draw = ImageDraw.Draw(img_data)
draw.text(char_location, char, font_color, font=font_style)
char_data = np.array(img_data)
# 使用cv2进行缩放旋转
char_box = font_style.getbbox(char)
x_center = char_location[0] + (char_box[2] / 2)
y_center = char_location[1] + (char_box[3] / 2)
center = (x_center, y_center)
angle = random.randint(-10, 10)
scale = random.uniform(0.8, 1.2)
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(char_data, M, img_wh, flags=cv2.INTER_AREA, borderMode=cv2.BORDER_REPLICATE)
# 提取字体部分,背景白色
chars_area = 255 * np.ones_like(rotated) - rotated
# 第一种合并方式,按最大值合并,避免字符重叠变色
char_last = np.expand_dims(img_result, axis=0)
char_next = np.expand_dims(chars_area, axis=0)
concat_data = np.concatenate([char_last, char_next], axis=0)
img_result = np.max(concat_data, axis=0)
# 第二种,按先后顺序,后添加的字符叠在之前的上面
# mask = chars_area > 0
# img_result[mask] = 0
# img_result += chars_area
# print('img_result.shape', img_result.shape)
# 更新下一个字符的起始坐标,这里默认y轴不变,这里可以调整字符间隙
word_space = random.randint(-5, 2)
char_location[0] += char_box[2] + word_space
# 还原为白色背景:
out_put = 255 * np.ones_like(img_result) - img_result
# save
captcha_img = Image.fromarray(out_put)
captcha_img.save(f'{string}.png')
验证码识别
举例的这个验证码的识别模型,训练流程已公开在aistudio上,使用的对抗训练的方式,欢迎大家交流参考:https://aistudio.baidu.com/aistudio/projectdetail/5755343