OCR是一個古老的問題。這里我們考慮一類特殊的OCR問題,就是驗證碼的識別。傳統做驗證碼的識別,需要經過如下步驟:
1. 二值化 2. 字符分割 3. 字符識別
這里最難的就是分割。如果字符之間有粘連,那分割起來就無比痛苦了。
最近研究深度學習,發現有人做端到端的OCR。於是准備嘗試一下。一般來說目前做基於深度學習的OCR大概有如下套路:
1. 把OCR的問題當做一個多標簽學習的問題。4個數字組成的驗證碼就相當於有4個標簽的圖片識別問題(這里的標簽還是有序的),用CNN來解決。 2. 把OCR的問題當做一個語音識別的問題,語音識別是把連續的音頻轉化為文本,驗證碼識別就是把連續的圖片轉化為文本,用CNN+LSTM+CTC來解決。
目前第1種方法可以做到90%多的准確率(4個都猜對了才算對),第二種方法我目前的實驗還只能到20%多,還在研究中。所以這篇文章先介紹第一種方法。
我們以python-captcha驗證碼的識別為例來做驗證碼識別。
下圖是一些這個驗證碼的例子:
可以看到這里面有粘連,也有形變,噪音。所以我們可以看看用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.transpose