您好,登錄后才能下訂單哦!
平時上網干啥的基本上都會接觸驗證碼,或者在機器學習學習過程中,大家或許會接觸過手寫體識別/驗證碼識別之類問題,會用到手寫體的數據集;
自己嘗試寫了一個生成手寫體圖片的python程序,在此分享下生成單張 30*30像素的手寫體數字1-9圖像 的一種實現方法;
我是利用random生成隨機數1-9,然后PIL寫到圖像上,然后經過旋轉、扭曲處理,得到“手寫體”,這里沒有加干擾線和干擾點;
得到的手寫體數字圖像如圖1所示;
實現比較簡單,用了PIL庫,不需要額外安裝opencv啥的,有興趣可以自己試試。
圖1 生成的手寫體數字1-9
圖2 利用generate_pngs.py寫入到文件夾3的數字3圖像
如果你想生成手寫體的字母/漢字也可以:
圖3 利用generate_single_png.py生成漢字的手寫體
源碼上傳到了我的GitHub: https://github.com/coneypo/Generate_handwritten_number
圖4 整體設計流程
圖5 生成的圖像經過的處理
1.1 新建一個空白圖像img_50,尺寸大小為50*50
img_50_blank = Image.new('RGB', (50, 50), (255, 255, 255))
為什么我這里要先生成50*50的空白圖像?
因為圖像背景(50*50像素的畫布)初始化的時候設置為白色(顏色數組(255, 255, 255)),而背景色之外的其實是黑色;
之后需要進行旋轉處理,如果直接新建30*30像素的畫布,旋轉之后邊上會出現黑邊,如圖6所示;
所以我新建了一個50*50,然后旋轉之后從中間裁出來一個30*30的圖像出來;
圖6 直接用30*30像素的畫布寫字旋轉(會出現黑邊)
1.2 利用PIL在圖像上寫文字
利用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.1 generate_folders_1to9.py
因為我們要將指定的圖像分類放入指定文件夾,所以我們需要先在項目目錄下面新建9個文件夾:
(當然你也可以自己新建,新建9個文件夾工作量還不大,但是如果要生成的驗證碼包含英文字母那就比較多了,大寫A-Z共24個+小寫a-z共24個+數字1-9共9個=57個子文件夾)
# 2018-01-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/ # generate_folders_1to9.py # 在目錄下生成用來存放數字1-9的9個文件夾,分別用1-9命名 import os path_folders = "F:/***/P_generate_handwritten_number/data_pngs/" # 1-9 for i in range(49,58): if (os.path.isdir(path_folders + chr(i))): pass else: # print(i,": ",path_1+chr(i)) # 生成目錄 os.mkdir(path_folders+chr(i))
圖7 自動生成的用來存放指定圖像的文件夾
2.2 generate_pngs.py
根據給定隨機次數samples, 生成samples個手寫體數字1-9,然后存放到本地文件夾1-9生成數據集;
在49行可以修改生成圖像的大小,我這里取的是30*30像素;
# 2018-01-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/ # generate_pngs.py # 生成手寫體數字 import random from PIL import Image, ImageDraw, ImageFilter, ImageFont random.seed(3) # 生成單張扭曲的數字圖像 def generate_single(): # 先繪制一個50*50的空圖像 img_50_blank = Image.new('RGB', (50, 50), (255, 255, 255)) # 創建畫筆 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)) # 隨機旋轉-10-10角度 random_angle = random.randint(-10, 10) img_50_rotated = img_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] # 創建扭曲 img_50_transformed = img_50_rotated.transform((50, 50), Image.PERSPECTIVE, params) # 生成新的30*30空白圖像,(在此處可以更改生成的圖像大小) img_30 = img_50_transformed.crop([10, 10, 40, 40]) return img_30, num path_pic = "F:/***/P_generate_handwritten_number/data_pngs/" # 生成手寫體數字1-9存入指定文件夾1-9 # 用cnt_num[1]-cnt_num[9]來計數數字1-9生成的個數,方便之后進行命名 cnt_num = [] for i in range(10): cnt_num.append(0) # 生成次數 samples = 200 for m in range(1, samples+1): # 調用生成圖像文件函數 img, generate_num = generate_single() # 取灰度 imgray = img.convert('1') # 計數生成的數字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(path_pic + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png") # 將圖像保存在指定文件夾中 imgray.save(path_pic + str(j) + "/" + str(j) + "_" + str(cnt_num[j]) + ".png") # 輸出顯示1-9的分布 print("\n", "生成的1-9的分布:") for k in range(9): print(k+1, ":", cnt_num[k+1], "張")
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/1_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/1_2.png
...生成的1-9的分布:
: 25 張
: 17 張
: 21 張
: 19 張
: 20 張
: 22 張
: 25 張
: 24 張
: 27 張
修改 generate_pngs.py中的samples, 你就可以生成指定大小的數據集;
2.3 generate_single_png.py
更改27行的char=" "(可以是數字/字母/漢字),生成單張手寫體扭曲圖像:
# 2018-01-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/ # generate_single_png.py # 生成手寫體數字/字母/漢字 import random from PIL import Image, ImageDraw, ImageFilter, ImageFont random.seed(3) # 生成單張扭曲的數字圖像 def generate_single(): # 先繪制一個50*50的空圖像 img_50_blank = Image.new('RGB', (50, 50), (255, 255, 255)) # 創建畫筆 draw = ImageDraw.Draw(img_50_blank) # 設置字體,這里選取字體大小25 font = ImageFont.truetype('simsun.ttc', 20) # xy是左上角開始的位置坐標 # text是你想要顯示的內容,數字/字母/漢字 char ="呵" draw.text(xy=(12, 11), font=font, text=char, fill=(0, 0, 0)) # 隨機旋轉-10-10角度 random_angle = random.randint(-10, 10) img_50_rotated = img_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] # 創建扭曲 img_50_transformed = img_50_rotated.transform((50, 50), Image.PERSPECTIVE, params) # 生成新的30*30空白圖像 img_30 = img_50_transformed.crop([10, 10, 40, 40]) return img_30, char path_pic = "F:/code/python/P_generate_handwritten_number/" # 調用生成圖像文件函數 img, generated_char = generate_single() imgray = img.convert('1') print(path_pic + "test.png") # 將圖像保存在指定文件夾中 imgray.save(path_pic + "test.png")
2.4 del_pngs.py
刪除指定目錄下子文件夾1-9中的所有圖片:
# 2018-01-9 # By TimeStamp # cnblogs: http://www.cnblogs.com/AdaminXie/ # del_pngs.py # 刪除路徑下生成的圖像文件 import os path_pic = "F:/***/P_generate_handwritten_number/data_pngs/" #刪除路徑下的圖片 def del_pic(): for i in range(1, 10): # 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()
自己動手豐衣足食,有興趣可以自己做手寫體數字數據集,字母和漢字的數據集稍加修改也可以做;
# GitHub: https://github.com/coneypo/Generate_handwritten_number
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。