基於LeNet網絡的中文驗證碼識別
由於公司需要進行了中文驗證碼的圖片識別開發,最近一段時間剛忙完上線,好不容易閑下來就繼上篇《基於Windows10 x64+visual Studio2013+Python2.7.12環境下的Caffe配置學習 》文章,記錄下利用caffe進行中文驗證碼圖片識別的開發過程。由於這里主要介紹開發和實現過程,CNN理論性的東西這里不作為介紹的重點,遇到相關的概念和術語請自行研究。目前從我們訓練出來的模型來看,單字識別率接近96%,所以一個四字驗證碼的准確率大概80%,效果還不錯,完全能滿足使用,如果每張圖片的樣本繼續加大應該能取得更高的准確率,當然隨着樣本的加大,訓練時間也隨之增大,對硬件設備要求也越高,還有就是優化LeNet網絡結構,目前這里只使用了三層卷積。
(一)開發准備
(1)開發環境
軟件環境:visual Studio2013+Python2.7.12+caffe
硬件環境:Intel Core i7-4790+GTX1080+RAM32G
(2)訓練圖片
可以用於驗證碼的中文常用字大概3666個,每個字的訓練大於等於50個,所以總共訓練樣本大概20萬,其中80%用於訓練集,20%用於測試集。樣本收集是一個非常麻煩和耗時的過程,需要手工標注結果,我這里利用手工打碼平台收集,最便宜一個驗證碼要4分錢,可以大概算一下,光為了收集這么多樣本就將近花費1萬RMB,還有配置一個GTX1080的顯卡大概6千RMB,這點成本對一個公司還好,如果是對於個人投入還是不少,所以對於實驗室的學生黨玩深度學習成本還是蠻高的!
訓練集:26萬樣本圖片
測試集:13萬樣本圖片
(二)圖片樣本處理
目前驗證碼種類無極繁多,有數字、字母、中文、圖片等等,不過本文主要介紹中文驗證碼的識別。中文驗證碼設計干擾的方式主要圍繞:
(1)背景色干擾
(2)文字傾斜扭曲
(3)干擾線
(4)中文拼音並存(百度九宮格)
(5)疊字
針對不同類型的驗證碼需要分別處理,這些處理過程統稱圖片預處理,目前並沒有統一的預處理方式,需要針對不同的驗證碼做特殊處理,但是大體過程無外乎:灰度化、二值化、去干擾線、分割切圖、標准化,這些過程用python實現都非常的簡單,這里就不詳細介紹了,直接上代碼,需要import cv2:

調用預處理方法的代碼:

處理前的圖片:
預處理后的圖片:
(三)caffe模型配置
模型配置階段,需要進行caffe所需數據格式准備、訓練集和測試集准備、Lenet網絡結構配置等三步
(1)訓練集和測試集准備
預處理階段將驗證碼切割成四個圖片后,需要將每個圖片進行標准化為32*32像素大小的圖片,不然caffe模型無法訓練。標准化完成以后就需要把每個字的圖片分拆到訓練集和測試集中去,這里代碼就不貼了,根據個人喜好我設置一個字的訓練集占80%,測試集占20%,然后把所有字用一個字典進行映射為數字編號,方便模型給出結果時我們能找到對應的漢字。
(2)caffe格式數據
為了生成caffe所需數據格式需要用到convert_imageset項目,在第一篇配置中已經編譯好了這個項目,可以直接拿過來用,python調用代碼如下:

生成成功過后可以分別在訓練集和測試集文件夾看到如下兩個文件:data.mdb和lock.mdb,都是caffe標准mdb格式的數據
(3)Lenet網絡模型
目前Lenet模型已經非常成熟,最常用的是Lenet-5(5層),對於層數不需要太多的CNN網絡用它完全足夠了,當然現在更強大的模型還有:Alexnet、googlenet,VGG,resnet。resnet是今年剛出的,據benchmark的測試,對於人臉識別它可以完爆其他網絡,層數更是可以多達200,有興趣的可以看看:GitHub測評項目。對於Lenet有一個可視化的配置網站:http://ethereon.github.io/netscope/#/editor,這里配置的三層結構如下:
模型總共包含三個卷積層,兩個池化層,模型中最重要的幾個設置參數:num_output、kernel_size、stride需要分別配置,模型的好壞除了層數結構的設計外,就看這幾個參數是否配置的合理,具體的配置這里不詳細講解,相關講解文章非常的多,也有很多優秀的論文可以借鑒,模型的結構代碼如下:

(四)訓練模型
到目前為止,准備工作都做完了,現在就可以利用python import caffe進行模型訓練了,模型訓練速度快慢主要看你GPU的配置如何,我開始用的GTX650,訓練5000輪下來,就得消耗半天時間,實在無法忍受這個速度,就向公司申請買了一個GTX1080,那速度簡直沒法比,訓練5000輪半個小時就能完成。調用模型的代碼如下:
cmd='caffe.exe train -solver=./caffe-master/caffe-master/windows/CaptchaTest/dpsample/solver/lenet_solver.prototxt'#訓練語句 os.system(cmd) os.chdir(path)
模型訓練中主要的輸出參數有:loss,accuracy,如果你看到loss一直在收斂,每500輪輸出一次的准確率也在提高,那么說明你的模型設計沒什么問題,不然就得重新設計。訓練完成后就能得到如下模型:
(五)使用模型
模型訓練完成后,我們就可以簡單的用測試圖片進行測試,測試代碼如下:
#調用模型 deploy='.\dpsample\solver\lenet_deploy.prototxt' #deploy文件 caffe_model='.\dpsample\iterate_iter_5000.caffemodel' #訓練好的 caffemodel imgtest='./dpsample/data/val/685_363.png' #隨機找的一張待測圖片 net = caffe.Net(deploy, caffe_model, caffe.TEST) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) #設定圖片的shape格式(1,3,32,32) transformer.set_transpose('data', (2,0,1)) #改變維度的順序,由原始圖片(28,28,3)變為(3,28,28) #transformer.set_mean('data', np.load(mean_file).mean(1).mean(1)) #減去均值,前面訓練模型時沒有減均值,這兒就不用 #transformer.set_raw_scale('data', 1) # 縮放到【0,1】之間 已經在網絡里設置scale,這里可以不用 transformer.set_channel_swap('data', (2,1,0)) #交換通道,將圖片由RGB變為BGR im=caffe.io.load_image(imgtest) #加載圖片 net.blobs['data'].data[...] = transformer.preprocess('data',im) #執行上面設置的圖片預處理操作,並將圖片載入到blob中 out = net.forward() prob= net.blobs['prob'].data[0].flatten() #取出最后一層(Softmax)屬於某個類別的概率值,並打印 print prob order=prob.argsort()[-1] print(order)
最后輸出的order就是模型預測出最有可能文字的序號,再到文字和序號對應的字典中去查看就知道這里的識別對不對了!
#寫在最后# 我是一個忠實的VS用戶,所有代碼都在VS編輯器實現的,它要能用python需要安裝一個PTVS插件,在這里編輯python代碼需要非常注意中文編碼的處理,否則你會吃大苦頭,不過相信我,其他編輯器能搞定的VS也一定沒問題,只是你要有足夠的耐心,遇到問題的時候多思考多搜搜問題的本質所在。
原創性聲明:
本人在cnblogs上的ID為marso,博客地址為http://www.cnblogs.com/marso/,所有包含原創聲明的博客均為本人原創作品。博客的內容除已注明的引用文獻外均為本人獨立研究成果。除特殊注明外均采用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議進行許可。
作品及其衍生品不得未經許可而用於商業用途。個人使用無需許可,但必須在引用部分(代碼,基本思想或實現方案等)標示出原作者信息,發布時需附帶本聲明。(對於GPLv3下發布的作品,引用本人作品不需要許可,也不需要標示出引用部分或附帶聲明。)
關於“原創”的說明:文章發布前我會進行初步的相關搜索,如未發現有別人發表過類似內容的作品我才會發表。但是因為可能有遺漏,所以不能保證我的博客內容一定為“首創”,但一定可以保證“原創”。
歡迎轉載,並請注明以下內容:
轉載自博客園marso的Blog, 博客地址為http://%博客URL%,采用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議 進行許可。其中“%博客URL%”替換為被轉載博客的實際URL。