1、主要功能
①界面化的輸入方式,進行實時數字識别
②可以識别多位的數字,例如23,234
③CNN進行數字識别
2、運作環境
Windows10、python3.7+、tensorflow2.x
3、步驟介紹
神經網絡的模型可以自己訓練或調用./model下已經訓練好的模型,用tf2.x實作,對圖檔的預處理等是利用opencv和PIL實作的,界面使用PyQt5,該識别器可以實時識别從GUI中畫出的數字圖檔,利用截圖的方式存儲圖檔,并對圖檔進行預處理,進行字元分割成多個圖檔進行CNN識别,最終以一圖一數字的形式組合傳回至前端。
具體過程:
4、細節
具體的界面代碼在下方的連結中,這裡稍微說一下圖檔字元分割部分:
# 按行切割,此時grayscaleimg為 50x100 矩陣,50 行,100列,每個元素不是0就是255
row_nz = []
# 将每行展成一個list,即有50個list
for row in grayscaleimg.tolist():
row_nz.append(len(row) - row.count(0))
# row_nz裡存儲每行值和不為0的列數 eg.[0, 0, 0, 0, 0, 0, 7, 15, 16, 9, 10, 9, 9, 11, 14, 25, 32, 24, 20, 13, 7, 7,
# 7, 9, 10, 10, 9, 9, 9, 14, 19, 14, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 50
# 代表在第6行(0開始)有7列元素不為0
# 找到上界(即第一個開始出現筆畫的行号) 記為第upper_y列
upper_y = 0
for i, x in enumerate(row_nz):
if x >= 1: # 若一行中出現大于兩個地方有筆畫(255)
upper_y = i
break
# 找到下界(即最後一個出現筆畫的行号) 記為第lower_y列
lower_y = 0
for i, x in enumerate(row_nz[::-1]):
if x >= 1:
lower_y = len(row_nz) - i
break
# 按上下界進行切割,将沒有筆畫的上部分和下部分都丢棄,留下中間帶有筆畫的區域
sliced_y_img = grayscaleimg[upper_y: lower_y, :]
# 同理,按列切割,此時grayscaleimg為 (lower_y - upper_y)x100 矩陣
col_nz = []
# 将每行展成一個list,即有100個list
for col in sliced_y_img.T.tolist():
col_nz.append(len(col) - col.count(0))
# 尋找每個字元的左邊界和右邊界,column_boundary_list存儲每個字元的起始列号
column_boundary_list = []
# record = False
for i, x in enumerate(col_nz[:-1]):
# 如果第i列無筆畫(和為0),第i+1列有筆畫,可以認為i列是某個字元的左邊界
if col_nz[i] <= 1 and col_nz[i + 1] > 1:
column_boundary_list.append(i)
# 如果第i列有筆畫,第i+1列無筆畫,可以認為i列是某個字元的右邊界
elif col_nz[i] >= 1 and col_nz[i + 1] < 1:
column_boundary_list.append(i + 1)
# 此時若書寫32, column_boundary_list裡存儲的類似于[20, 31, 56, 89],即20-31列代表'3', 56-89列代表'2'
# 存儲分割後的圖檔
img_list = [] # img_list存儲每幅圖的矩陣
xl = [column_boundary_list[i:i + 2] for i in range(0, len(column_boundary_list), 2)]
for x in xl:
s = len(x)
if len(x) == 2 and x[1] - x[0] > 5:
s = fill(sliced_y_img[:, x[0]:x[1]]) # 從sliced_y_img截取每幅圖的列,進行背景填充
img_list.append(s) # 将填充後的矩陣存入img_list
img_list = [x for x in img_list if x.shape[1] > 5]
print("數字位數為: ", len(img_list)) # 輸出總的字元數,即圖檔數
最後再對img_list裡的圖檔調用識别函數進行識别,傳回單一數字加入list中。
5、樣例
完整代碼:https://github.com/GusionTan/HandwrittenDigitRecognitio
歡迎探讨,喜歡的話麻煩點個星,轉載請注明出處。