Python3 generates a handwritten number, and python3 generates a handwritten number.
0. Introduction
Generally, verification codes are used for accessing the Internet, or in machine learning, you may have encountered issues such as Handwriting Recognition/verification code recognition. handwritten datasets are used;
I tried to write a python program to generate a handwritten image. Here is an implementation method for generating a 30*30 pixel handwritten number 1-9 image;
I used random to generate a random number of 1-9, then PIL was written to the image, and then rotated and distorted to get the "handwriting". Here there was no interference line or interference point;
The obtained handwritten Digital Image 1 is shown;
The implementation is relatively simple. With the PIL library, you do not need to install opencv. If you are interested, try it on your own.
Figure 1 generated handwritten number 1-9
Figure 2 Use generate_pngs.py to write the number 3 image to folder 3
If you want to generate a handwritten letter/Chinese character, you can:
Figure 3 generate_single_png.py
Source code uploaded to my GitHub: https://github.com/coneypo/Generate_handwritten_number
1. Design Process
Figure 4 Overall Design Process
Figure 5 process the generated image
1.1 create a blank image img_50 with a size of 50*50
img_50_blank = Image.new('RGB', (50, 50), (255, 255, 255))
Why do I need a 50*50 blank image here?
Because the image background (50*50 pixel canvas) is set to white (color array (255,255,255) during initialization, the background color is actually black;
After that, the image needs to be rotated. If a 30*30 pixel canvas is created, black borders will appear on the side after the image is rotated, as shown in figure 6;
So I created a 50*50 image, and then rotated it to produce a 30*30 image from the center;
Figure 6 rotate a canvas with 30*30 pixels (black edges may appear)
1.2 use PIL to write text on Images
Use PIL's ImageDraw to create a paint brush and use draw. text to write at a specified position;
Xy = () is the coordinate starting from the upper left corner of the image. The value can be adjusted as needed;
# Create a paint brush draw = ImageDraw. draw (img_50_blank) # generate a random number 1-9num = str (random. randint (1, 9) # Set the font. Select 25 font = ImageFont. truetype ('simsun. ttc ', 20) # xy is the coordinate draw at the beginning of the upper left corner. text (xy = (18, 11), font = font, text = num, fill = (0, 0, 0 ))
1.3 rotate images at random to a certain angle
Use rotate (angel) to rotate the image. angel takes the degree. Here, Let it rotate randomly-10 to + 10 degrees:
# Random rotation-10-10 angle random_angle = random. randint (-10, 10) img_50_rotated = img_50_blank.rotate (random_angle)
1.4 image distortion
Here is the core step for generating "handwritten" numbers. After a normal image is distorted, you can get the desired verification code:
# Image distortion parameter 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] # create img_50_transformed = img_50_rotated.transform (50, 50), Image. PERSPECTIVE, params)
2. py source code Introduction
2.1 generate_folders_1to9.py
Because we want to add the specified image category to the specified folder, we need to create nine folders under the project directory:
(You can also create a new folder by yourself. It is not enough to create nine folders, but if the verification code to be generated contains letters, it will be much more, uppercase A-Z total 24 + lowercase a-z total 24 + numbers 1-9 Total 9 = 57 subfolders)
#2011-1-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/# generate_folders_1to9.py # in the directory generated to store numbers 1-9 9 9 folders, respectively with 1-9 name import ospath_folders = "F: /***/P_generate_handwritten_number/data_pngs/"# 1-9for I in range (49,58): if (OS. path. isdir (path_folders + chr (I): pass else: # print (I, ":", path_1 + chr (I) # generate the directory OS. mkdir (path_folders + chr (I ))
Figure 7 automatically generated folder for storing the specified Image
2.2 generate_pngs.py
Generate samples handwritten numbers 1-9 based on the given random number of samples, and store them in the local folder 1-9 to generate a dataset;
You can modify the size of the generated image in the 49 rows. Here, the image size is 30*30 pixels;
# By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/# generate_pngs.py # generate handwritten numbers import randomfrom PIL import Image, ImageDraw, ImageFilter, ImageFontrandom. seed (3) # generate a single distorted digital Image def generate_single (): # first draw a 50*50 empty Image img_50_blank = Image. new ('rgb ', (50, 50), (255,255,255) # create paint brush draw = ImageDraw. draw (img_50_blank) # generate random number 1-9 num = str (random. randint (1, 9) # Set the font. Select 25 font = ImageFont. truetype ('simsun. ttc ', 20) # xy is the coordinate draw at the beginning of the upper left corner. text (xy = (18, 11), font = font, text = num, fill = (0, 0, 0) # random rotation-10-10 angle random_angle = random. randint (-10, 10) img_50_rotated = img_50_blank.rotate (random_angle) # graphic distortion parameter 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] # create img_50_transformed = img_50_rotated.transform (50, 50), Image. PERSPECTIVE, params) # generate a new 30*30 blank image (here you can change the size of the generated image) img_30 = img_50_transformed.crop ([10, 10, 40, 40]) return img_30, numpath_pic = "F: /***/P_generate_handwritten_number/data_pngs/"# generate handwritten numbers 1-9 and save them to the specified folder 1-9 # Use cnt_num [1]-cnt_num [9] to count the numbers generated from 1-9, after convenience, name cnt_num = [] for I in range (10): cnt_num.append (0) # Number of times samples = 200for m in range (1, samples + 1 ): # Call the image file generation function img, generate_num = generate_single () # obtain the gray imgray = img. convert ('1') # count the number of generated numbers 1-9, used to name the image file for j in range (1, 10): if (generate_num = str (j )): cnt_num [j] = cnt_num [j] + 1 # path, for example, "F: /code/***/P_generate_handwritten_number/data_pngs/1/415231.png "# print Output display path (path_pic + str (j) +"/"+ str (j) + "_" + str (cnt_num [j]) + ". png ") # Save the image in the specified folder imgray. save (path_pic + str (j) + "/" + str (j) + "_" + str (cnt_num [j]) + ". png ") # output displays the distribution of 1-9 (" \ n "," generated distribution of 1-9: ") for k in range (9): print (k + 1, ":", cnt_num [k + 1], "Zhang ")
Output
D: \ *** \ anaconda \ python.exe F:/***/P_generate_handwritten_number/generate_pngs.py
F:/***/P_generate_handwritten_number/data_pngs/4/4_1.png
F:/***/P_generate_handwritten_number/data_pngs/1/20.1.png
F:/***/P_generate_handwritten_number/data_pngs/8/8_1.png
F:/***/P_generate_handwritten_number/data_pngs/3/3_1.png
F:/***/P_generate_handwritten_number/data_pngs/1/4102.png
...
Distribution of the generated values from 1 to 9:
: 25 sheets
: 17 sheets
: 21 sheets
: 19 sheets
: 20 sheets
: 22
: 25 sheets
: 24 sheets
: 27
Modify samples in generate_pngs.py to generate a dataset of the specified size;
2.3 generate_single_png.py
Change 27 rows of char = "" (which can be numbers, letters, or Chinese characters) to generate a single handwritten distorted image:
# By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/# generate_single_png.py # generate handwritten numbers/Letters/Chinese characters import randomfrom PIL import Image, ImageDraw, ImageFilter, ImageFontrandom. seed (3) # generate a single distorted digital Image def generate_single (): # first draw a 50*50 empty Image img_50_blank = Image. new ('rgb ', (50, 50), (255,255,255) # create paint brush draw = ImageDraw. draw (img_50_blank) # Set the font. Select 25 font = ImageFont. truetype ('simsun. ttc ', 20) # xy is the coordinates at the beginning of the upper left corner # text is the content you want to display, numbers/Letters/Chinese characters char = "oh" draw. text (xy = (12, 11), font = font, text = char, fill = (0, 0, 0) # random rotation-10-10 angle random_angle = random. randint (-10, 10) img_50_rotated = img_50_blank.rotate (random_angle) # graphic distortion parameter 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] # create img_50_transformed = img_50_rotated.transform (50, 50), Image. PERSPECTIVE, params) # generate a new 30*30 blank image img_30 = img_50_transformed.crop ([10, 10, 40, 40]) return img_30, charpath_pic = "F: /code/python/P_generate_handwritten_number/"# Call the img function for generating image files, generated_char = generate_single () imgray = img. convert ('1') print (path_pic + "test.png") # Save the image in the specified folder imgray. save (path_pic + "test.png ")
2.4 del_pngs.py
Delete all images from subfolders 1-9 in the specified directory:
#2011-1-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/# del_pngs.py # Delete the image file generated under the path import ospath_pic = "F: /***/P_generate_handwritten_number/data_pngs/"# Delete the image def del_pic (): for I in range (1, 10) in the path ): # print (path_png + chr (I) namedir = OS. listdir (path_pic + str (I) for tmppng in namedir: if (tmppng in namedir): # print (tmppng) OS. remove (path_pic + str (I) + "/" + tmppng) del_pic ()
3. Summary
If you are interested, you can make a handwritten digital dataset. You can also make a slight modification to the dataset of letters and Chinese characters;
# GitHub: https://github.com/coneypo/Generate_handwritten_number