標籤:
相信大家在開發一些程式會有識別圖片上文字(即所謂的OCR)的需求,比如識別車牌、識別圖片格式的商品價格、識別圖片格式的郵箱地址等等,當然需求最多的還是識別驗證碼。如果要完成這些OCR的工作,需要你掌握影像處理、Image Recognition的知識,需要用到圖形形態學、傅裡葉變換、矩陣變換、貝葉斯決策等很多複雜的理論,這讓絕大部分人都會望而卻步。
Tesseract這個開源項目的出現讓我們普通人也可以涉足OCR的開發。Tesseract可以從圖片中識別出文字內容,但不要以為Tesseract可以智能的識別出各種奇形怪狀、複雜的圖片文字,Tesseract預設只能識別非常標準字型、清晰無幹擾的圖片文字,剛接觸Tesseract的人很多都會發出這樣的評價“Tesseract吹的挺厲害,但是識別率很低呀,不好用”。其實我們要識別的內容千奇百怪,Tesseract是需要去訓練才能比較高準確率的識別的,我們需要把一批樣本圖片讓Tesseract去嘗試識別,然後對他識別出的錯誤結果進行校正,告訴他“這個圖片你識別錯了,應該識別為某某某”,這樣Tesseract慢慢的就“學會了”怎麼樣進行識別。也就是如下一個訓練過程:
看到有一個“預先處理”,這是什麼意思呢?我們知道,很多驗證碼都是加了一些幹擾處理的,比如說有的驗證碼加了噪音點、有的驗證碼加了幹擾線、有的驗證碼加了幹擾背景、有的驗證碼做了文字扭曲。如:
這些圖片如果直接交給Tesseract去處理,識別的難度會非常大。開發人員應該在把圖片交給Tesseract之前對圖片進行比較的預先處理操作,比如去掉幹擾線、去掉背景噪點、字元矯正等等,有些複雜的預先處理操作可能會涉及到圖形形態學中比較深入的理論,這不是一篇文章能夠介紹的,下面只列出比較簡單的圖片預先處理的基本知識,深入學習請參考圖形學相關資料。
基礎講解:
1、.Net中圖片對象類是Image類,使用Image.FromFile(file)來載入一張圖片,一般的圖片都是位元影像,Bitmap類是Image類的子類,所以我們一般把Image. FromFile()傳回值轉換為Bitmap類型使用Bitmap bitmap = (Bitmap)Image.FromFile(file)
2、Bitmap. Save()用來把記憶體中的圖片對象儲存到輸出中去。第二個參數為圖片格式。
3、由於Bitmap關聯到GDI的非託管資源,實現了IDisposable介面,所以需要使用using進行對象的資源管理,以避免程式記憶體泄露的問題。
4、如果要進行高效的圖片操作,需要配合指標對Bitmap進行操作,當然為了避免對C#指標操作不熟悉的讀者,這篇文章中我將會使用效率略低但是比較易懂的GetPixel、 SetPixel方法來進行圖片操作。GetPixel、 SetPixel是Bitmap提供的兩個方法,分別可以用來對圖片進行指定座標像素點顏色的讀取和設定指定座標像素點的顏色。
接下來開始講解Tesseract的使用:
首先我們要採集多張有代表性的驗證碼樣本圖片,因為比較複雜的驗證碼的訓練過程會比較長,而這次傳智播客.Net學院舉辦的驗證碼識別免費公開課時間有限,因此我挑選了相對比較簡單的驗證碼進行識別。複雜驗證碼的識別過程也是大同小異的。我測試用的100張驗證碼圖片在文章最後的“公開課軟體、圖片庫和代碼.zip”壓縮包中。
這些圖片有一些明顯的噪音背景和幹擾線,但是噪音背景和幹擾線的顏色就是那幾個,因此我使用拾色器拾取了這些點的顏色,使用如下的代碼把那些顏色替換為白色,並且儲存為tif格式的圖片:
轉換後效果如下:
可以看到背景顏色和幹擾線全部被去掉了。
接下來運行jTessBoxEditor(jTessBoxEditor是使用java編寫的,因此先需要安裝配置java運行環境,對java運行環境安裝配置不熟悉的朋友請自行尋找資料),雙擊jTessBoxEditor.jar即可啟動運行。將第二步處理後的tiff使用主菜單 “Tool→Merge Tiff”圖片合并為一張圖片,比如儲存到F:\aa\下haijia.tif檔案中。
下載安裝tesseract-ocr-setup-3.01-1.exe(我使用3.02有問題,不知道是我的問題還是我不會用,總之還是推薦大家這裡先使用3.01版本),這個setup版本會自動把安裝目錄添加到Path環境變數中,推薦使用。如果下載portable版本則需要自己編輯環境把tesseract解壓路徑添加到Path環境變數中。
在下一步操作之前需要先給訓練結果取一個名字,比如我這裡就取haijia這個名字。如果你取了別的名字,只要把後面所有操作中的“haijia”改成你取的名字即可。
啟動windows命令列視窗,並且進入haijia.tif檔案所在的目錄,然後執行tesseract.exe haijia.tif haijia batch.nochop makebox。其中haijia.tif就是第三步產生的合并tiff檔案的檔案名稱,haijia則是咱們取的訓練名。這樣就會產生初始識別結果的haijia.box檔案
保證haijia.box檔案和haijia.tif檔案檔案名稱完全一樣並且放在同一個檔案夾下。使用jTessBoxEditor開啟haijia.tif檔案,逐個校本文字,後儲存。注意在jTessBoxEditor中每次修改完了字元都要斷行符號,注意及時儲存。如果發現多識別了、兩個字母被識別為一個字母、一個字母被識別為兩個字母等錯誤,需要使用Merge、split、delete之類的功能進行微調,還要通過修改X、Y、W、H修改自動識別的地區 。
所有的自動識別結果矯正完畢後命令列執行tesseract.exe haijia.tif haijia nobatch box.train
命令列執行unicharset_extractor.exe haijia.box
在目錄下建立一個名字為“font_properties”的檔案,並且輸入文本(其中haijia就是訓練的名字,儲存的時候使用EditPlus等進階文字編輯器去掉BOM頭或者儲存為ANSI格式): haijia 1 0 0 1 0
命令列執行cntraining.exe haijia.tr
命令列執行 mftraining.exe -F font_properties -U unicharset haijia.tr
第12步完成後,目錄下應該產生若干個檔案了,把unicharset, inttemp, normproto, pfftable這四個檔案加上訓練名字首碼“haijia.”。
命令列執行“combine_tessdata haijia.” 來合并產生的haijia.traineddata訓練檔案。執行完這步後,檔案夾下就應該產生一個haijia.traineddata檔案了,這個檔案就是識別用的訓練資料檔案,只需要這一個haijia.traineddata檔案即可,之前用的tif圖片檔案以及其他的中間檔案都不需要了。
接下來調用Tesseract的API就可以在程式中進行驗證碼識別了。Tesseract支援很多語言,C/C++、Java、.Net、PHP、Python都有相應的API封裝,只要尋找你使用語言的API庫即可。下面還是以.Net為例。
使用tesseractdotnet_v301_r590.zip中的tesseract.dll添加到相應的引用。注意tesseractdotnet預設只支援.Net 2.0,所以需要把項目的Target修改為.Net 2.0,如果你需要在2.0以上的版本中使用,則需要自己下載tesseractdotnet的原始碼進行編譯。
採用第二步同樣的方法對待識別的圖片進行預先處理,然後執行下面的代碼對預先處理過後的圖片對象進行識別:
C#識別驗證碼技術-Tesseract