端到端的OCR:基於CNN的實現
阿新 • • 發佈:2019-01-08
OCR是一個古老的問題。這裡我們考慮一類特殊的OCR問題,就是驗證碼的識別。傳統做驗證碼的識別,需要經過如下步驟:
1. 二值化
2. 字元分割
3. 字元識別
這裡最難的就是分割。如果字元之間有粘連,那分割起來就無比痛苦了。
最近研究深度學習,發現有人做端到端的OCR。於是準備嘗試一下。一般來說目前做基於深度學習的OCR大概有如下套路:
1. 把OCR的問題當做一個多標籤學習的問題。4個數字組成的驗證碼就相當於有4個標籤的圖片識別問題(這裡的標籤還是有序的),用CNN來解決。
2. 把OCR的問題當做一個語音識別的問題,語音識別是把連續的音訊轉化為文字,驗證碼識別就是把連續的圖片轉化為文字,用CNN+LSTM+CTC來解決。
目前第1種方法可以做到90%多的準確率(4個都猜對了才算對),第二種方法我目前的實驗還只能到20%多,還在研究中。所以這篇文章先介紹第一種方法。
下圖是一些這個驗證碼的例子:
可以看到這裡面有粘連,也有形變,噪音。所以我們可以看看用CNN識別這個驗證碼的效果。
首先,我們定義一個迭代器來輸入資料,這裡我們每次都直接呼叫python-captcha這個庫來根據隨機生成的label來生成相應的驗證碼圖片。這樣我們的訓練集相當於是無窮大的。
class OCRIter(mx.io.DataIter):
def __init__(self, count, batch_size, num_label, height, width):
super(OCRIter, self).__init__()
self.captcha = ImageCaptcha(fonts=['./data/OpenSans-Regular.ttf'])
self.batch_size = batch_size
self.count = count
self.height = height
self.width = width
self.provide_data = [('data', (batch_size, 3, height, width))]
self.provide_label = [('softmax_label', (self.batch_size, num_label))]
def __iter__(self):
for k in range(self.count / self.batch_size):
data = []
label = []
for i in range(self.batch_size):
# 生成一個四位數字的隨機字串
num = gen_rand()
# 生成隨機字串對應的驗證碼圖片
img = self.captcha.generate(num)
img = np.fromstring(img.getvalue(), dtype='uint8')
img = cv2.imdecode(img, cv2.IMREAD_COLOR)
img = cv2.resize(img, (self.width, self.height))
cv2.imwrite("./tmp" + str(i % 10) + ".png", img)
img = np.multiply(img, 1/255.0)
img = img