Python 3 生成手写体数字数据集
0.引言
平时经常会接触到验证码,或者在机器学习学习过程中,大家或许会接触过手写体识别/验证码识别之类问题,会用到手写体的数据集;
自己尝试写了一个生成手写体图片的 Python 程序,可以批量生成手写体数字数据集,在此分享下生成 30*30像素 的手写体数字 1-9 图片 的一种实现方法;
大概流程:新建空白图像 >>> 生成随机数 1-9 >>> 将数字写到空白图像上 >>> 旋转、扭曲 处理 >>> 得到 “手写体数字”;
得到的手写体数字图像如 图1 所示,实现比较简单,有兴趣可以自己试;
源码上传到了我的 GitHub,如果对您有帮助欢迎 star 支持下: https://github.com/coneypo/Generate_handwritten_number ;

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

图 2 利用 generate_imgs.py 得到数字 3 图像
1. 设计流程

图 4 整体设计流程

图 5 生成的图像经过的处理
1.1 新建一个空白图像 img_50,尺寸大小为 50*50
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) 是从图像左上角开始的坐标,取值自己根据需求调整;
# 创建画笔
draw = ImageDraw.Draw(img_50_blank) # 生成随机数1-9
num = str(random.randint(1, 9)) # 设置字体,这里选取字体大小25
font = ImageFont.truetype('simsun.ttc', 20) # xy是左上角开始的位置坐标
draw.text(xy=(18, 11), font=font, text=num, fill=(0, 0, 0))
1.3 将图像随机旋转一定角度
利用 rotate(angel) 进行旋转图像,angel 取的是度数,这里让它随机旋转 -10 到 +10 度:
# 随机旋转-10-10角度
random_angle = random.randint(-10, 10)
img_50_rotated = img_50_blank.rotate(random_angle)
1.4 图像扭曲
这里是生成“手写体”数字的 核心 步骤,一个正常的图像经过扭曲之后就可以得到想要的验证码了:
# 图形扭曲参数
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500] # 创建扭曲
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-9 的 9个文件夹,分别用 1-9 命名
def mkdir_for_imgs():
for i in range(49, 58):
if os.path.isdir(path_img + "Num_" + chr(i)):
pass
else:
print(path_img + "Num_" + chr(i))
os.mkdir(path_img + "Num_" + chr(i))

图 7 mkdir_for_imgs() 生成的用来存放指定图像的文件夹
2.2 函数 del_imgs()
删除子文件夹 Num_1-9 中的所有图片:
# 删除路径下的图片
def del_imgs():
for i in range(1, 10):
dir_nums = os.listdir(path_img+ "Num_" + str(i))
for tmp_img in dir_nums:
if tmp_img in dir_nums:
# print("delete: ", tmp_img)
os.remove(path_img + "Num_" + str(i) + "/" + tmp_img)
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:
# Created on: 2018-01-09
# Updated on: 2018-09-03
# Author: coneypo
# Blog: http://www.cnblogs.com/AdaminXie/
# Github: https://github.com/coneypo/Generate_handwritten_number
# 生成手写体数字 import random
import os
from PIL import Image, ImageDraw, ImageFont random.seed(3)
path_img = "data_pngs/" # 在目录下生成用来存放数字 1-9 的 9个文件夹,分别用 1-9 命名
def mkdir_for_imgs():
for i in range(49, 58):
if os.path.isdir(path_img + "Num_" + chr(i)):
pass
else:
print(path_img + "Num_" + chr(i))
os.mkdir(path_img + "Num_" + chr(i)) # generate folders
# mkdir_for_imgs() # 删除路径下的图片
def del_imgs():
for i in range(1, 10):
dir_nums = os.listdir(path_img+ "Num_" + str(i))
for tmp_img in dir_nums:
if tmp_img in dir_nums:
# print("delete: ", tmp_img)
os.remove(path_img + "Num_" + str(i) + "/" + tmp_img)
print("Delete finish", "\n") del_imgs() # 生成单张扭曲的数字图像
def generate_single():
# 先绘制一个50*50的空图像
im_50_blank = Image.new('RGB', (50, 50), (255, 255, 255)) # 创建画笔
draw = ImageDraw.Draw(im_50_blank) # 生成随机数1-9
num = str(random.randint(1, 9)) # 设置字体,这里选取字体大小25
font = ImageFont.truetype('simsun.ttc', 20) # xy是左上角开始的位置坐标
draw.text(xy=(18, 11), font=font, text=num, fill=(0, 0, 0)) # 随机旋转-10-10角度
random_angle = random.randint(-10, 10)
im_50_rotated = im_50_blank.rotate(random_angle) # 图形扭曲参数
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500] # 创建扭曲
im_50_transformed = im_50_rotated.transform((50, 50), Image.PERSPECTIVE, params) # 生成新的30*30空白图像
im_30 = im_50_transformed.crop([10, 10, 40, 40]) return im_30, num # 生成手写体数字1-9存入指定文件夹1-9
def generate_1to9(n):
# 用cnt_num[1]-cnt_num[9]来计数数字1-9生成的个数,方便之后进行命名
cnt_num = []
for i in range(10):
cnt_num.append(0) for m in range(1, n + 1):
# 调用生成图像文件函数
im, generate_num = generate_single() # 取灰度
im_gray = im.convert('') # 计数生成的数字1-9的个数,用来命名图像文件
for j in range(1, 10):
if generate_num == str(j):
cnt_num[j] = cnt_num[j] + 1 # 路径如 "F:/code/***/P_generate_handwritten_number/data_pngs/1/1_231.png"
# 输出显示路径
print("Generate:", path_img + "Num_" + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png")
# 将图像保存在指定文件夹中
im_gray.save(path_img + "Num_" + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png") print("\n")
# 输出显示1-9的分布
print("生成的1-9的分布:")
for k in range(9):
print("Num", k + 1, ":", cnt_num[k + 1], "in all") # generate n times
generate_1to9(1000)

图 8 利用 generate_imgs.py 得到数字 1 图像
3.总结
有兴趣可以自己生成手写体数字数据集,感谢你的支持;
# 代码已上传到了我的GitHub,如果对您有帮助欢迎 Star下:https://github.com/coneypo/Generate_handwritten_number
# 请尊重他人劳动成果,转载或者使用源码请注明出处:http://www.cnblogs.com/AdaminXie
# 如有问题请留言或者联系邮箱 coneypo@foxmail.com
Python 3 生成手写体数字数据集的更多相关文章
- Python 3 利用机器学习模型 进行手写体数字识别
0.引言 介绍了如何生成数据,提取特征,利用sklearn的几种机器学习模型建模,进行手写体数字1-9识别. 用到的四种模型: 1. LR回归模型,Logistic Regression 2. SGD ...
- Python 3 利用机器学习模型 进行手写体数字检测
0.引言 介绍了如何生成手写体数字的数据,提取特征,借助 sklearn 机器学习模型建模,进行识别手写体数字 1-9 模型的建立和测试. 用到的几种模型: 1. LR,Logistic Regres ...
- caffe-windows之手写体数字识别例程mnist
caffe-windows之手写体数字识别例程mnist 一.训练测试网络模型 1.准备数据 Caffe不是直接处理原始数据的,而是由预处理程序将原始数据变换存储为LMDB格式,这种方式可以保持较高的 ...
- 利用Python自动生成暴力破解的字典
Python是一款非常强大的语言.用于测试时它非常有效,因此Python越来越受到欢迎. 因此,在此次教程中我将聊一聊如何在Python中生成字典,并将它用于任何你想要的用途. 前提要求 1,Pyth ...
- Python随机生成验证码的两种方法
Python随机生成验证码的方法有很多,今天给大家列举两种,大家也可以在这个基础上进行改造,设计出适合自己的验证码方法方法一:利用range Python随机生成验证码的方法有很多,今天给大家列举两种 ...
- 使用sphinx快速为你python注释生成API文档
sphinx简介sphinx是一种基于Python的文档工具,它可以令人轻松的撰写出清晰且优美的文档,由Georg Brandl在BSD许可证下开发.新版的Python3文档就是由sphinx生成的, ...
- Python小游戏——猜数字教程(random库教程)
今天来开发一个简单的数字逻辑游戏,猜数字(数字炸弹) 首先开发游戏第一件事,了解需求. 猜数字游戏规则: 计算机随机生成一个指定范围的数字,由玩家来猜测, 之后计算机会根据玩家提供数字来与自己生成的数 ...
- pyhton2 and python3 生成随机数字、字母、符号字典(用于撞库测试/验证码等)
本文介绍Python3中String模块ascii_letters和digits方法,其中ascii_letters是生成所有字母,从a-z和A-Z,digits是生成所有数字0-9.string.p ...
- Python自动生成代码工具
项目中有一个需求,对一个基类而言,拥有一个比较方法和拷贝方法,某些地方需要频繁地对这两个方法进行调用.对于所有子类而言,需要重写这两个方法,并在其中维护类内一些成员变量.例如有一个变量m_iMyVal ...
随机推荐
- TCP 建立连接:三次握手
转自:http://www.cnblogs.com/winner-0715/p/5032661.html 感谢! TCP 建立连接过程 TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是T ...
- Java的注释和Javadoc在eclipse生成的方法 – Break易站
本文内容来自:Java的注释和Javadoc在eclipse生成的方法 – Break易站 1. Java的注释 Java里有两种注释风格.下面这个写法是非常常见的 1 2 3 4 /*This i ...
- PyCharm/WebStorm遇到Cannot start internal HTTP server
在开始学习html.css的时候,使用PyCharm 的模拟链接到服务器的时候总是遇到 网上也没有遇到合适的解决方案,遂下载了WebStorm,希望能通过安装配置好一些设置,结果依然不行,只有从头分析 ...
- Java中的String类能否被继承?为什么?
不能被继承,因为String类有final修饰符,而final修饰的类是不能被继承的. Java对String类的定义: public final class String implements ja ...
- IIS 应用程序池自动停止
IIS7 .NET Runtime version 2.0.50727.5420 - 执行引擎错误(000007FEE77AAF0E) (80131506) 装完系统,配置完IIS,发现.NET程序报 ...
- python之list
1.python列表 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推 序列都可以进行的操作包括索引,切片,加,乘, ...
- 【转载】Linux cgroup资源隔离各个击破之 - cpu隔离1
Linux cgroup 有两个子系统支持CPU隔离.一个是cpu子系统,另一个是cpuset子系统. cpu子系统根据进程设置的调度属性,选择对应的CPU资源调度方法 .1. 完全公平调度 Comp ...
- C/C++知识点清单01
第一章 C/C++程序基础 一.一般赋值语句: 考察一般赋值语句的概念和方法. 1.程序: #include<stdio.h> int main(void) { ,y,z; x*=(y=z ...
- HDFS中namenode启动失败
1.环境配置: -1.core-site.xml文件 <configuration> <property> <name>fs.defaultFS</name& ...
- windows c++程序移植到linux的要点
这段时间得到一份源码,是Windows下的,调试了一把,可以正常运行,可是没有Linux版本,而实际的应用场景是要在Linux服务器上面运行 所以涉及到Windows下c++程序的移植,有同事竭力推荐 ...