平时经常会接触到验证码,或者在机器学习学习过程中,大家或许会接触过手写体识别/验证码识别之类问题,会用到手写体的数据集;
大概流程:新建空白图像>>>生成随机数1-9>>>将数字写到空白图像上>>>旋转、扭曲处理>>>得到“手写体数字”;
得到的手写体数字图像如图1所示,实现比较简单,有兴趣可以自己试;
图1生成的手写体数字1-9
图2利用generate_imgs.py得到数字3图像
1.设计流程
图4整体设计流程
图5生成的图像经过的处理
1.1新建一个空白图像img_50,尺寸大小为50*50
1img_50_blank=Image.new('RGB',(50,50),(255,255,255))
想要的30*30的图像,为什么我这里要先生成50*50的空白图像?
因为图像背景(50*50像素的画布)初始化的时候设置为白色(颜色数组(255,255,255)),而背景色之外的其实是黑色;
之后需要进行旋转处理,如果直接新建30*30像素的画布,旋转之后边上会出现黑边,如图6所示;
所以我新建了一个50*50,然后旋转之后从中间裁出来一个30*30的图像出来;
图6直接用30*30像素的画布写字旋转(会出现黑边)
1.2利用PIL在图像上写文字text
利用PIL的ImageDraw,创建画笔,然后利用draw.text在指定位置写字;
xy=(18,11)是从图像左上角开始的坐标,取值自己根据需求调整;
1#创建画笔2draw=ImageDraw.Draw(img_50_blank)34#生成随机数1-95num=str(random.randint(1,9))67#设置字体,这里选取字体大小258font=ImageFont.truetype('simsun.ttc',20)910#xy是左上角开始的位置坐标11draw.text(xy=(18,11),font=font,text=num,fill=(0,0,0))
1.3将图像随机旋转一定角度
利用rotate(angel)进行旋转图像,angel取的是度数,这里让它随机旋转-10到+10度:
1#随机旋转-10-10角度2random_angle=random.randint(-10,10)3img_50_rotated=img_50_blank.rotate(random_angle)
1.4图像扭曲
这里是生成“手写体”数字的核心步骤,一个正常的图像经过扭曲之后就可以得到想要的验证码了:
1#图形扭曲参数2params=[1-float(random.randint(1,2))/100,30,40,50,61-float(random.randint(1,10))/100,7float(random.randint(1,2))/500,80.001,9float(random.randint(1,2))/500]1011#创建扭曲12img_50_transformed=img_50_rotated.transform((50,50),Image.PERSPECTIVE,params)
2.SourceCode介绍
2.1函数mkdir_for_imgs()
因为我们要将指定的图像分类放入指定文件夹,所以我们需要先在项目目录下面新建9个文件夹:
(当然你也可以自己新建,新建9个文件夹工作量还不大,但是如果要生成的验证码包含英文字母那就比较多了,大写A-Z共24个+小写a-z共24个+数字1-9共9个=57个子文件夹)
1#在目录下生成用来存放数字1-9的9个文件夹,分别用1-9命名2defmkdir_for_imgs():3foriinrange(49,58):4ifos.path.isdir(path_img+"Num_"+chr(i)):5pass6else:7print(path_img+"Num_"+chr(i))8os.mkdir(path_img+"Num_"+chr(i))
图7mkdir_for_imgs()生成的用来存放指定图像的文件夹
2.2函数del_imgs()
删除子文件夹Num_1-9中的所有图片:
1#删除路径下的图片2defdel_imgs():3foriinrange(1,10):4dir_nums=os.listdir(path_img+"Num_"+str(i))5fortmp_imgindir_nums:6iftmp_imgindir_nums:7#print("delete:",tmp_img)8os.remove(path_img+"Num_"+str(i)+"/"+tmp_img)9print("Deletefinish","\n")
2.3完整的代码generate_imgs.py
mkdir_for_imgs()>>>del_imgs()>>>generate_1to9(n)
根据给定随机次数生成手写体数字1-9,然后存放到本地文件夹Num_1-9;
Line67修改生成图像的大小,我这里取的是30*30像素;
79#生成新的30*30空白图像80im_30=im_50_transformed.crop([10,10,40,40])