OCR系列之一:開坑介紹
開坑背景
近期即將進行一個新的工作,對儀表類示器數字進行識別。
樣圖如下:
這樣的:
當然還有很多類,這裡就不一一貼圖了,觀察發現,這是來自不同類的顯示器(儀表),那麼想要識別出上面的數字,想要一統天下的識別,這還是相當有挑戰的。初步思路很簡單:分兩個步驟,一是定位(ROI區域鎖定提取),傳統方法,無非是進行ROI區域定位,比如形態學處理或其他手段進行定位後再進行識別,但是有個困難是,類別不一樣的顯示器,沒有一個統一的方法進行定位的啊。問題就在這裡。一是識別,可採用ocr演算法進行識別。
拋開專案,我們可以將上述問題歸結為OCR識別問題。應用場景就很廣泛了,比如常見的專注於電子文件、證件、票據的漢字識別。由此,我覺得有必要要開一個坑來專門講述這個系列,文章將持續更新。
OCR簡介
既然入坑研究OCR,當然看了比較多關於OCR的資料,對OCR的前世今生也有了一個比較清晰的瞭解。這裡寫一篇關於OCR技術的綜述,對OCR相關的知識點都好好總結一遍,以加深個人理解。
什麼是OCR?
OCR英文全稱是Optical Character Recognition,中文叫做光學字元識別。它是利用光學技術和計算機技術把印在或寫在紙上的文字讀取出來,並轉換成一種計算機能夠接受、人又可以理解的格式。文字識別是計算機視覺研究領域的分支之一,而且這個課題已經是比較成熟了,並且在商業中已經有很多落地專案了。比如漢王OCR,百度OCR,阿里OCR等等,很多企業都有能力都是拿OCR技術開始掙錢了。其實我們自己也能感受到,OCR技術確實也在改變著我們的生活:比如一個手機APP就能幫忙掃描名片、身份證,並識別出裡面的資訊;汽車進入停車場、收費站都不需要人工登記了,都是用車牌識別技術;我們看書時看到不懂的題,拿個手機一掃,APP就能在網上幫你找到這題的答案。太多太多的應用了,OCR的應用在當今時代確實是百花齊放啊。
OCR的分類
如果要給OCR進行分類,大概可以分為兩類:手寫體識別和印刷體識別。這兩個可以認為是OCR領域兩個大主題了,當然印刷體識別較手寫體識別要簡單得多,我們也能從直觀上理解,印刷體大多都是規則的字型,因為這些字型都是計算機自己生成再通過列印技術印刷到紙上。在印刷體的識別上有其獨特的干擾:在印刷過程中字型很可能變得斷裂或者墨水粘連,使得OCR識別異常困難。當然這些都可以通過一些影象處理的技術幫他儘可能的還原,進而提高識別率。總的來說,單純的印刷體識別在業界已經能做到很不錯了,但說100%識別是肯定不可能的,但是說識別得不錯那是沒毛病。
印刷體已經識別得不錯了,那麼手寫體呢?手寫體識別一直是OCR界一直想攻克的難關,但是時至今天,感覺這個難關還沒攻破,還有很多學者和公司在研究。為什麼手寫體識別這麼難識別?因為人類手寫的字往往帶有個人特色,每個人寫字的風格基本不一樣,雖然人類可以讀懂你寫的文字,但是機器缺很難。那為什麼機器能讀懂印刷體?因為印刷體是機器造出來的啊,那機器當然能讀懂自己造的字型啦哈哈~其實上面也提到了,印刷體一般都比較規則,字型都基本就那幾十種,機器學習這幾十種字型並不是一件難事,但是手寫體,每個人都有一種字型的話,那機器該學習多少字型啊?這就是難度所在。
如果按識別的內容來分類,也就是按照識別的語言的分類的話,那麼要識別的內容將是人類的所有語言(漢語、英語、德語、法語等)。如果僅按照我們國人的需求,那識別的內容就包括:漢字、英文字母、阿拉伯數字、常用標點符號。根據要識別的內容不同,識別的難度也各不相同。簡單而言,識別數字是最簡單了,畢竟要識別的字元只有0~9,而英文字母識別要識別的字元有26個(如果算上大小寫的話那就52個),而中文識別,要識別的字元高達數千個(二級漢字一共6763個)!因為漢字的字形各不相同,結構非常複雜(比如帶偏旁的漢字)如果要將這些字元都比較準確地識別出來,是一件相當具有挑戰性的事情。但是,並不是所有應用都需要識別如此龐大的漢字集,比如車牌識別,我們的識別目標僅僅是數十個中國各省和直轄市的簡稱,難度就大大減少了。當然,在一些文件自動識別的應用是需要識別整個漢字集的,所以要保證識別的整體的識別還是很困難的。
OCR流程
為了方便描述,那就舉文件中的字元識別為例子來展開說明。
假如輸入系統的影象是一頁文字,那麼識別時的第一件事情是判斷頁面上的文字朝向,因為我們得到的這頁文件往往都不是很完美的,很可能帶有傾斜或者汙漬,那麼我們要做的第一件事就是進行影象預處理,做角度矯正和去噪。然後我們要對文件版面進行分析,進每一行進行行分割,把每一行的文字切割下來,最後再對每一行文字進行列分割,切割出每個字元,將該字元送入訓練好的OCR識別模型進行字元識別,得到結果。但是模型識別結果往往是不太準確的,我們需要對其進行識別結果的矯正和優化,比如我們可以設計一個語法檢測器,去檢測字元的組合邏輯是否合理。比如,考慮單詞Because,我們設計的識別模型把它識別為8ecause,那麼我們就可以用語法檢測器去糾正這種拼寫錯誤,並用B代替8並完成識別矯正。這樣子,整個OCR流程就走完了。從大的模組總結而言,一套OCR流程可以分為:
版面分析 -> 預處理-> 行列切割 -> 字元識別 -> 後處理識別矯正
從上面的流程圖可以看出,要做字元識別並不是單純一個OCR模組就能實現的(如果單純的OCR模組,識別率相當低),都要各個模組的組合來保證較高的識別率。上面的流程分的比較粗,每個模組下還是有很多更細節的操作,每個操作都關係著最終識別結果的準確性。做過OCR的童鞋都知道,送入OCR模組的影象越清晰(即預處理做的越好),識別效果往往就越好。那現在對這流程中最為重要的字元識別技術做一個總結。
識別方法
現在我們只想單純地想對字元進行識別,那方法會有哪些呢?我列了一下可以採取的策略:
- 使用谷歌開源OCR引擎Tesseract
- 使用大公司的OCR開放平臺(比如百度),使用他們的字元識別API
- 傳統方法做字元的特徵提取,輸入分類器,得出OCR模型
- 暴力的字元模板匹配法
- 大殺器:基於深度學習下的CNN字元識別
上面提到的OCR方法都有其有點和缺點,也正如此,他們也有各自特別適合的應用場景。
首先說開源OCR引擎Tesseract。搞字元識別的童鞋應該都聽說過Tesseract這個東西,這是谷歌維護的一個OCR引擎,它已經有一段相當悠久的歷史了。Tesseract現在的版本已經支援識別很多種語言了,當然也包括漢字的識別。畢竟Tesseract是外國人搞得一個東西,所以在漢字識別的精度上還是不能擺上檯面,不過還是自己去改善。但是Tesseract在阿拉伯數字和英文字母上的識別還是可以的,如果你要做的應用是要識別英文或者數字,不妨考慮一下使用Tesseract,畢竟拿來就能得到不錯的結果。當然啦,要做到你想要的識別率,後期微調或者優化肯定要多下功夫的。
接下來說一下借用OCR開放平臺做文字識別。現在很多大公司都開放了OCR的API供開發者呼叫,當然啦,小量呼叫是不收費的,但是大量呼叫就要收費了。最近我也在百度開放平臺上呼叫OCR的API做一些識別的工作,說實話,在漢字的識別上,我們中國公司的技術還是頂尖的,在漢字識別的準確率上已經讓人很滿意了。比如我要識別一些文字,自己寫個python指令碼,呼叫開放平臺的服務,返回的就是識別結果了。這種模式有啥不好的地方嗎?首先是需要錢(當然每天小批量識別一下是不用錢的),第二是自己的控制程度不足,我們想要提升識別精度,我們不可以從OCR識別上做改進(畢竟別人的東西,我們改不了),能做只是預處理和後期矯正,能做的還是比較有限的。但是,如果自己不想花大量時間做OCR模型並且手上有錢的話,這種識別方法還是OK的。
上面提到的都是用的是別人的東西,那我們想從頭自己做,咋辦?
那就自己做吧!先談一談字元模板那匹配法。暴力的字元模板匹配法看起來很蠢,但是在一些應用上可能卻很湊效。比如在對電錶數字進行識別時,考慮到電錶上的字型較少(可能就只有阿拉伯數字),而且字型很統一,清晰度也很高,所以識別難度不高。針對這種簡單的識別場景,我們首先考慮的識別策略當然是最為簡單和暴力的模板匹配法。我們首先定義出數字模板(0~9),然後用該模板滑動匹配電錶上的字元,這種策略雖然簡單但是相當有效。我們不需要左思右想去建模,訓練模型,只需要識別前做好模板庫就可以了。
模板匹配法只限於一些很簡單的場景,但對於稍微複雜的場景,那就不太實用了。那此時我們可以採取OCR的一般方法,即特徵設計、特徵提取、分類得出結果的計算機視覺通用的技巧。在深度學習大放異彩之前,OCR的方法基本都是這種方法,其效果嘛,並不算特別好。在這裡簡單說一下這裡常見的方法。第一步是特徵設計和提取,特徵設計是一件很煩人的事情,做過模式識別相關專案的童鞋也深有體會,我們現在識別的目標是字元,所以我們要為字元設計它獨有的的特徵,來為後面的特徵分類做好準備。字元有啥特徵呢?有結構特徵,即字元的端點、交叉點、圈的個數、橫線豎線條數等等,都是可以利用的字元特徵。比如“品”字,它的特徵就是它有3個圈,6條橫線,6條豎線。除了結構特徵,還有大量人工專門設計的字元特徵,據說都能得到不錯的效果。最後再將這些特徵送入分類器(SVM)做分類,得出識別結果。這種方式最大的缺點就是,人們需要花費大量時間做特徵的設計,這是一件相當費工夫的事情。通過人工設計的特徵(例如HOG)來訓練字元識別模型,此類單一的特徵在字型變化,模糊或背景干擾時泛化能力迅速下降。而且過度依賴字元切分的結果,在字元扭曲、粘連、噪聲干擾的情況下,切分的錯誤傳播尤其突出。針對傳統OCR解決方案的不足,學界業界紛紛擁抱基於深度學習的OCR。
這些年深度學習的出現,讓OCR技術煥發第二春。現在OCR基本都用卷積神經網路來做了,而且識別率也是驚人的好,人們也不再需要花大量時間去設計字元特徵了。
OCR的發展
在一些簡單環境下OCR的準確度已經比較高了(比如電子文件),但是在一些複雜環境下的字元識別,在當今還沒有人敢說自己能做的很好。現在大家都很少會把目光還放在如何對電子文件的文字識別該怎麼進一步提高準確率了,因為他們把目光放在更有挑戰性的領域。OCR傳統方法在應對複雜圖文場景的文字識別顯得力不從心,越來越多人把精力都放在研究如何把文字在複雜場景讀出來,並且讀得準確作為研究課題,用學界術語來說,就是場景文字識別(文字檢測+文字識別)。
從上圖可以看出,自然場景下的文字識別比簡單場景的文字識別實在困難太多了,現在雖然出了很多成果,但是離理想結果還是差很遠。
當然啦,除上面的場景文字識別外,歷史悠久的手寫體的識別到現在還是一件具有挑戰的課題,在深度學習的浪潮下,手寫體的識別已經前進了一大步,但是尚且沒達到印刷體識別那種可以商用的地步,所以啊,OCR的研究還得不斷地進行下去。
專案分析
OCR介紹完畢後,相信對這塊有個大概瞭解了,那麼回到專案中,我們要對儀表類數字進行識別,相對上述複雜場景來講,應該算是簡單的了。
我的一個思路如下:
這裡主要用的方法發是機器學習中的檢測+傳統方法的顏色分割。流程如下:
1)儀表檢測
2)數字區域分割(定位)
3)數字識別(檢測)
儀表檢測
目前開源的物體檢測方法很多,對於上面場景來說,很多方法都可以達到理想的效果,比方說SSD,yolo,haar + adaboost等,傳統方法,深度學習方法均可,建議採用多標籤輸出的方法,這樣就可以一張圖輸入,多張標輸出。
數字區域分割
如果直接檢測數字,干擾很多,效果很差,最好的方法是特殊場景,特殊對待,對於其他類別的,比如車票,身份證,車牌識別等,需要採用相應模板特定的定位演算法來定位感興趣區域,再去識別。
如下表,可以檢測黑色區域,得到如下的結果:
顏色檢測後進行最小外接矩形計算就可以得到。需要注意的是得到檢測框後要往內部padding一定比例的畫素
數字識別
數字檢測可以按照儀表檢測的方法來進行。很多人會用tesseract來實現識別,往往是不得其法的,據說tesseract內部的演算法是跟比劃相關,led的顯示是斷的,所以兩者是相悖的,所以用檢測方法會很好的解決這個問題,檢測分類包含數字,字母及小數點,為了效果好,標註的時候要用同樣大小的框進行標註,比如小數點的標註框要比其面積大很多。
不過我不打算採用第三方的識別介面來實現,原因前面已經講述了,一是效果一是不便修改和擴充套件。接下來打算使用深度學習的演算法來實現識別這塊。
好了,本篇先到這裡,後面細化。