相信大家在開發一些程序會有識別圖片上文字(即所謂的OCR)的需求,比如識別車牌、識別圖片格式的商品價格、識別圖片格式的郵箱地址等等,當然需求最多的還是識別驗證碼。如果要完成這些OCR的工作,需要你掌握圖像處理、圖像識別的知識,需要用到圖形形態學、傅里葉變換、矩陣變換、貝葉斯決策等很多復雜的理論,這讓絕大部分人都會望而卻步。
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的源代碼進行編譯。
-
采用第二步同樣的方法對待識別的圖片進行預處理,然后執行下面的代碼對預處理過后的圖片對象進行識別:


