python绘制数字23_Python 3 生成手写体数字数据集

0.引言

平时经常会接触到验证码,或者在机器学习学习过程中,大家或许会接触过手写体识别/验证码识别之类问题,会用到手写体的数据集;

自己尝试写了一个生成手写体图片的 Python 程序,可以批量生成手写体数字数据集,在此分享下生成 30*30像素 的手写体数字 1-9 图片的一种实现方法;

大概流程:新建空白图像 >>> 生成随机数 1-9 >>> 将数字写到空白图像上 >>> 旋转、扭曲处理 >>> 得到 “手写体数字”;

得到的手写体数字图像如 图1 所示,实现比较简单,有兴趣可以自己试;

图1 生成的手写体数字 1-9

图 2 利用 generate_imgs.py 得到数字 3 图像

1. 设计流程

图 4 整体设计流程

图 5 生成的图像经过的处理

1.1 新建一个空白图像 img_50,尺寸大小为 50*50

1 img_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 #创建画笔

2 draw =ImageDraw.Draw(img_50_blank)3

4 #生成随机数1-9

5 num = str(random.randint(1, 9))6

7 #设置字体,这里选取字体大小25

8 font = ImageFont.truetype('simsun.ttc', 20)9

10 #xy是左上角开始的位置坐标

11 draw.text(xy=(18, 11), font=font, text=num, fill=(0, 0, 0))

1.3 将图像随机旋转一定角度

利用 rotate(angel) 进行旋转图像,angel 取的是度数,这里让它随机旋转 -10 到 +10 度:

1 #随机旋转-10-10角度

2 random_angle = random.randint(-10, 10)3 img_50_rotated = img_50_blank.rotate(random_angle)

1.4 图像扭曲

这里是生成“手写体”数字的 核心步骤,一个正常的图像经过扭曲之后就可以得到想要的验证码了:

1 #图形扭曲参数

2 params = [1 - float(random.randint(1, 2)) / 100,3 0,4 0,5 0,6 1 - float(random.randint(1, 10)) / 100,7 float(random.randint(1, 2)) / 500,8 0.001,9 float(random.randint(1, 2)) / 500]10

11 #创建扭曲

12 img_50_transformed = img_50_rotated.transform((50, 50), Image.PERSPECTIVE, params)

2. Source Code 介绍

2.1 函数 mkdir_for_imgs()

因为我们要将指定的图像分类放入指定文件夹,所以我们需要先在项目目录下面新建 9 个文件夹:

(当然你也可以自己新建,新建 9 个文件夹工作量还不大,但是如果要生成的验证码包含英文字母那就比较多了,大写 A-Z 共 24 个 + 小写 a-z 共 24 个+ 数字 1-9 共 9 个= 57个子文件夹)

1 #在目录下生成用来存放数字 1-9 的 9个文件夹,分别用 1-9 命名

2 defmkdir_for_imgs():3 for i in range(49, 58):4 if os.path.isdir(path_img + "Num_" +chr(i)):5 pass

6 else:7 print(path_img + "Num_" +chr(i))8 os.mkdir(path_img + "Num_" + chr(i))

图 7 mkdir_for_imgs() 生成的用来存放指定图像的文件夹

2.2 函数 del_imgs()

删除子文件夹 Num_1-9 中的所有图片:

1 #删除路径下的图片

2 defdel_imgs():3 for i in range(1, 10):4 dir_nums = os.listdir(path_img+ "Num_" +str(i))5 for tmp_img indir_nums:6 if tmp_img indir_nums:7 #print("delete: ", tmp_img)

8 os.remove(path_img + "Num_" + str(i) + "/" +tmp_img)9 print("Delete finish", "\n")

2.3 完整的代码generate_imgs.py

mkdir_for_imgs() >>> del_imgs() >>> generate_1to9(n)

根据给定随机次数生成手写体数字 1-9,然后存放到本地文件夹 Num_1-9 ;

Line 67 修改生成图像的大小,我这里取的是 30*30 像素;

79 # 生成新的30*30空白图像

80 im_30 = im_50_transformed.crop([10, 10, 40, 40])

Line 105 给定生成手写体数字的次数:

116 # generate n times

117 generate_1to9(1000)

generate_imgs.py:

1 #Created on: 2018-01-09

2 #Updated on: 2018-09-03

3 #Author: coneypo

4 #Blog: http://www.cnblogs.com/AdaminXie/

5 #Github: https://github.com/coneypo/Generate_handwritten_number

6 #生成手写体数字

7

8

9 importrandom10 importos11 from PIL importImage, ImageDraw, ImageFont12

13 random.seed(3)14 path_img = "data_pngs/"

15

16

17 #在目录下生成用来存放数字 1-9 的 9个文件夹,分别用 1-9 命名

18 defmkdir_for_imgs():19 for i in range(49, 58):20 if os.path.isdir(path_img + "Num_" +chr(i)):21 pass

22 else:23 print(path_img + "Num_" +chr(i))24 os.mkdir(path_img + "Num_" +chr(i))25

26

27 #generate folders

28 #mkdir_for_imgs()

29

30

31 #删除路径下的图片

32 defdel_imgs():33 for i in range(1, 10):34 dir_nums = os.listdir(path_img+ "Num_" +str(i))35 for tmp_img indir_nums:36 if tmp_img indir_nums:37 #print("delete: ", tmp_img)

38 os.remove(path_img + "Num_" + str(i) + "/" +tmp_img)39 print("Delete finish", "\n")40

41

42 del_imgs()43

44

45 #生成单张扭曲的数字图像

46 defgenerate_single():47 #先绘制一个50*50的空图像

48 im_50_blank = Image.new('RGB', (50, 50), (255, 255, 255))49

50 #创建画笔

51 draw =ImageDraw.Draw(im_50_blank)52

53 #生成随机数1-9

54 num = str(random.randint(1, 9))55

56 #设置字体,这里选取字体大小25

57 font = ImageFont.truetype('simsun.ttc', 20)58

59 #xy是左上角开始的位置坐标

60 draw.text(xy=(18, 11), font=font, text=num, fill=(0, 0, 0))61

62 #随机旋转-10-10角度

63 random_angle = random.randint(-10, 10)64 im_50_rotated =im_50_blank.rotate(random_angle)65

66 #图形扭曲参数

67 params = [1 - float(random.randint(1, 2)) / 100,68 0,69 0,70 0,71 1 - float(random.randint(1, 10)) / 100,72 float(random.randint(1, 2)) / 500,73 0.001,74 float(random.randint(1, 2)) / 500]75

76 #创建扭曲

77 im_50_transformed = im_50_rotated.transform((50, 50), Image.PERSPECTIVE, params)78

79 #生成新的30*30空白图像

80 im_30 = im_50_transformed.crop([10, 10, 40, 40])81

82 returnim_30, num83

84

85 #生成手写体数字1-9存入指定文件夹1-9

86 defgenerate_1to9(n):87 #用cnt_num[1]-cnt_num[9]来计数数字1-9生成的个数,方便之后进行命名

88 cnt_num =[]89 for i in range(10):90 cnt_num.append(0)91

92 for m in range(1, n + 1):93 #调用生成图像文件函数

94 im, generate_num =generate_single()95

96 #取灰度

97 im_gray = im.convert('1')98

99 #计数生成的数字1-9的个数,用来命名图像文件

100 for j in range(1, 10):101 if generate_num ==str(j):102 cnt_num[j] = cnt_num[j] + 1

103

104 #路径如 "F:/code/***/P_generate_handwritten_number/data_pngs/1/1_231.png"

105 #输出显示路径

106 print("Generate:", path_img + "Num_" + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png")107 #将图像保存在指定文件夹中

108 im_gray.save(path_img + "Num_" + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png")109

110 print("\n")111 #输出显示1-9的分布

112 print("生成的1-9的分布:")113 for k in range(9):114 print("Num", k + 1, ":", cnt_num[k + 1], "in all")115

116 #generate n times

117 generate_1to9(1000)

图 8 利用 generate_imgs.py 得到数字 1 图像

3.总结

有兴趣可以自己生成手写体数字数据集,感谢你的支持;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值