最近項目中有個需求,就是讓識別手機號。其實按照產品的思路就是外購,並且確實已經開始採購。因爲採購過程其實也是漫長的,因而乎本人就準備本身研究一下實現手機號識別。linux
若是用一些第三方的話,好比百度OCR識別是有限制的,並且就是集成SDK而已,沒什麼可研究的。最終通過尋尋覓覓,找到了咱們今天的主角--Tesseract。Tesseract
是一款由HP實驗室開發由Google維護的開源OCR(Optical Character Recognition , 光學字符識別)引擎。git
Tesseract
工程引入過程真可謂是一波三折,在本身工程引入的時候遇到了挺多的問題。github
首先咱們經過Github上的開源代碼下載Tesseract
主工程,在主工程中咱們能夠看到Tesseract
會被單獨編譯成一個動態庫bash
TesseractOCR.framework
導入到工程中tessdata
文件夾拖到本身的工程中G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"eng"];
tesseract.engineMode = G8OCREngineModeTesseractOnly;
tesseract.pageSegmentationMode = G8PageSegmentationModeAutoOSD;
tesseract.image = [UIImage imageNamed:@"image_sample.jpg"];;
[tesseract recognize];
NSString *recognizedText = tesseract.recognizedText;
NSLog(@"%@",recognizedText);
複製代碼
其實經過最簡單的三部咱們已經完成了TesseractOCR
集成。是否是很簡單啊?其實否則,經過以上簡單三步咱們可能會遇到如下問題。app
dyld: Library not loaded: @rpath/TesseractOCR.framework/TesseractOCR
Referenced from: /var/containers/Bundle/Application/.../testocr.app/testocr
Reason: image not found
複製代碼
這個問題解決方案就是在Xcode->General->Embedded Binaries 點擊+,選擇TesseractOCR.framework
便可解決測試
Error opening data file /var/containers/Bundle/Application/.../testocr.app/tessdata/chi_sim.traineddata
Please make sure the TESSDATA_PREFIX environment variable is set to the parent directory of your "tessdata" directory.
複製代碼
這個問題就是我在在引入tessdata
文件夾的方式的時候致使的。 優化
Create folder references
就能夠了。
一般經過以上步驟,此時個人demo可以正常運行起來了,並且可以識別出原來工程中的圖片ui
咱們項目中的需求就是經過視頻流截取一張圖片,而後再經過TesseractOCR
識別。效果圖以下:spa
經過以上代碼集成到咱們本身的工程發現一個問題就是手機號識別率很低。由於咱們用的是eng
訓練庫,因此就考慮是否是水土不服,將他換成中文的訓練庫。命令行
說幹就幹咱們就去官方下載最新的4.0.0中文訓練庫chi_sim.traineddata
。
tessdata
文件夾中eng
改爲chi_sim
G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"chi_sim"];
複製代碼
本覺得會大功告成,反而這裏就是重頭戲!
allow_blob_division
複製代碼
在chi_sim.traineddata文件目錄下,使用命令行執行:
combine_tessdata -e chi_sim.traineddata chi_sim.config
複製代碼
執行完後,在目錄下出現chi_sim.config的文件,打開該文件; 在allow_blob_division F這一行的前面加#,註釋掉
即:# allow_blob_division F
複製代碼
而後,在執行命令行: combine_tessdata -o chi_sim.traineddata chi_sim.config
到此在使用 chi_sim.traineddata文件就不會報read_params_file: parameter not found: allow_blob_division
actual_tessdata_num_entries_ <= TESSDATA_NUM_ENTRIES:Error:Assert failed:in file ../../ccutil/tessdatamanager.cpp, line 53
複製代碼
這個問題我集合Google和Github上的Issues得出統一結論:chi_sim.traineddata
版本庫不對應,由於咱們下載的是4.0.0最新版,因此按照結論咱們就換成一個較低的版本,並且確實能夠啦!
不過綜合對比下來感受識別率還不是很好,畢竟最新的訓練庫表明着識別率最高,因此內心隱隱仍是不甘心。
經過問題3不知你們有沒有感受到chi_sim.traineddata
能夠進行分解,而後再次合成呢?
經過結合combine_tessdata有關介紹此命令的文章,我有了一個大膽的想法,將老版本和新版本的的chi_sim.traineddata
分別解包。而後將兩個集合起來從新合成。
咱們經過如下兩行便可實現
合成
combine_tessdata -o chi_sim.traineddata chi_sim.
複製代碼
解壓
combine_tessdata -e chi_sim.traineddata chi_sim.
複製代碼
chi_sim.traineddata
經過解壓出來的文件,咱們對比發現其實新版比舊版少了幾個文件。這時候我有個更大膽的想法,我只要我需求的文件,我只要數字識別庫就行了,經過這種方式能夠極大的減小包的大小,不過經過嘗試以失敗了結。由於只要咱們須要的庫的話,數量與代碼中的數量又不匹配了
chi_sim.traineddata
將咱們合成的chi_sim.traineddata
放到工程中就不會再報問題4了。並且識別率很高。(我本身合成的已經分享出來了在文章末尾)
結合上步合成的最新訓練庫,經過屢次嘗試,如下代碼是識別率最高的了。
G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"chi_sim"];
tesseract.engineMode = G8OCREngineModeTesseractOnly;//必需要設置此模式
tesseract.pageSegmentationMode = G8PageSegmentationModeSparseText;//此模式識別率最高
tesseract.charWhitelist = @"0123456789";//白名單
tesseract.charBlacklist = @"abcdefghigklmnopqrstuvwxyz-_";//黑名單
tesseract.image = newImage;
tesseract.rect = CGRectMake((KSCREEN_WIDTH-210-16)/2, 62-2, 210, 20+4);
tesseract.maximumRecognitionTime = 5;
[tesseract recognize];
複製代碼
是不斷的使用中,發現一個問題,用戶手機與紙的距離是個問題,若是用戶離着太遠識別率很是低,只有在一個適當的距離能基本很快就能識別出來,並且正確率很是高。
個人解決方案就是經過在掃描界面上增長一個框,這裏可以有效控制用戶的距離
最終實現了手機號的識別,不過這個識別速度要2到3秒,稍微慢了點,並且那個距離的解決也不是最好的。各位若是有什麼好的解決方案能夠與我聯繫