OCR文字識別用的是什麼演算法?

最好具體說一下OCR整個過程的步驟


根據近期的一些paper總結一下,說的不對請多指正。

General OCR一般包含兩步: 1. detection--&>找到包含文字的區域(proposal); 2. classification--&>識別區域中的文字。

先說detection models, 近兩年比較熱門的object detection model有 faster-rcnn(https://arxiv.org/pdf/1506.01497.pdf) 和 yolo(http://pjreddie.com/media/files/papers/yolo.pdf), 兩個模型都是基於CNN給出proposed regions 同時對object region進行分類。 其中yolo比faster-rcnn的速度更快,但是在accuracy上有些損失。

再說classification models, 比較著名的是Ian goodfellow在13年提出的multi-digit number classification([1312.6082] Multi-digit Number Recognition from Street View Imagery using Deep Convolutional Neural Networks), 同樣也是基於deep CNN. 該方法的不足在於要事先選定可預測的sequence的最大長度,較適用於門牌號碼或者車牌號碼(少量字元, 且每個字元之間可以看作是獨立); 另一類比較常用的方法是RNN/LSTM/GRU + CTC, 方法最早由Alex Graves在06年提出應用於語音識別。這個方法的好處在於可以產生任意長度的文字,並且模型的性質決定了它有能力學到文字於文字之間的聯繫(temporal relations/dependencies)。不足之處在於sequential natural決定了它的計算效率沒有CNN高,並且還有潛在的gradients exploding/vanishing的問題。

以上說的這兩類模型都不需要對文字預先分割(end-to-end)。

另一類不需要對文字預先分割的方法就是attention-mechanism,attention可以分為hard attention和soft attention. 其中hard attention能夠直接給出hard location,通常是bounding box的位置 (https://arxiv.org/pdf/1412.7755.pdf), 想法直觀,缺點是不能直接暴力bp。soft attention通常是rnn/lstm/gru encoder-decoder model (https://arxiv.org/abs/1603.03101), 可以暴力bp。還有一種比較特別的gradient-based attention(http://www.ics.uci.edu/~yyang8/research/feedback/feedback-iccv2015.pdf) 也挺有意思。


文字檢測演算法近幾年發展迅速,可以分為水平文字檢測(四個自由度,類似物體檢測)和傾斜文字檢測(文字框是不規則四邊形,八個自由度),水平文字檢測個人認為比較好的演算法是2016 ECCV喬宇老師團隊的CTPN,傾斜文字檢測個人比較喜歡的方法是2017 CVPR的EAST和Seglink,感興趣可以看論文繼續了解。

文字識別近兩年沒有太大進展,有兩種方法,一種是CNN+RNN+CTC,白翔老師團隊的CRNN寫的比較清楚,還有一種是CNN+RNN基於Attention的方法。

最近比較火的方向是文字檢測和識別放到一個網路里joint train,沈春華老師團隊2017 ICCV的Towards End-to-end Text Spotting with Convolutional Recurrent Neural Networks這篇文章已經在水平文字上把檢測識別end to end做的比較work,感覺這可能是未來一兩年的一個熱點。


一般OCR套路是這樣的

1.先檢測和提取Text region.

2.接著利用radon hough變換 等方法 進行文本校正。

3.通過投影直方圖分割出單行的文本的圖片。

最後是對單行的OCR

對單行的OCR主要由兩種思想

第一種是需要分割字元的。

分割字元的方法也比較多,用的最多的是基於投影直方圖極值點作為候選分割點並使用分類器+beam search 搜索最佳分割點。

搜索到分割點之後對於單個字元,傳統的就是特徵工程+分類器。
一般流程是 灰度 -&> 二值化-&>矯正圖像 -&> 提取特徵(方法多種多樣例如pca lbp 等等) -&>分類器(分類器大致有SVM ANN KNN等等 )。

現在的 CNN(卷積神經網路)可以很大程度上免去特徵工程。

第二種是無需分割字元的

還有一點就是端到端(end to end)的識別,但前提是你需要大量的標註好的數據集。
這種方法可以不分割圖像直接以連續的輸出字元序列。

對於短長度的可以使用mutli-label classification 。比如像車牌,驗證碼。
這裡我試過一個車牌的多標籤分類。
車牌識別中的不分割字元的端到端(End-to-End)識別

google做街景門牌號識別就是用的這種方法。

如果字元序列長度較比如很長的手寫體 而且不固定的話。可以使用類似於語音識別中採用的方法,讓訓練好的單個字元分類器在序列圖像上滑動,輸出概率圖,接著用 lstm rnn 等序列模型+ ctc loss輸出字元序列。
像現在的tesseract 4.0 已經使用lstm來進行ocr了。


我來回答一下吧,畢竟我畢業設計做的這個(雖然爛尾了)。

首先OCR是模式識別的一個領域,所以整體過程也就是模式識別的過程。其過程整體來說可以分為以下幾個步驟:

  1. 預處理:對包含文字的圖像進行處理以便後續進行特徵提取、學習。這個過程的主要目的是減少圖像中的無用信息,以便方便後面的處理。在這個步驟通常有:灰度化(如果是彩色圖像)、降噪、二值化、字元切分以及歸一化這些子步驟。經過二值化後,圖像只剩下兩種顏色,即黑和白,其中一個是圖像背景,另一個顏色就是要識別的文字了。降噪在這個階段非常重要,降噪演算法的好壞對特徵提取的影響很大。字元切分則是將圖像中的文字分割成單個文字——識別的時候是一個字一個字識別的。如果文字行有傾斜的話往往還要進行傾斜校正。歸一化則是將單個的文字圖像規整到同樣的尺寸,在同一個規格下,才能應用統一的演算法。
  2. 特徵提取和降維:特徵是用來識別文字的關鍵信息,每個不同的文字都能通過特徵來和其他文字進行區分。對於數字和英文字母來說,這個特徵提取是比較容易的,因為數字只有10個,英文字母只有52個,都是小字符集。對於漢字來說,特徵提取比較困難,因為首先漢字是大字符集,國標中光是最常用的第一級漢字就有3755個;第二個漢字結構複雜,形近字多。在確定了使用何種特徵後,視情況而定,還有可能要進行特徵降維,這種情況就是如果特徵的維數太高(特徵一般用一個向量表示,維數即該向量的分量數),分類器的效率會受到很大的影響,為了提高識別速率,往往就要進行降維,這個過程也很重要,既要降低維數吧,又得使得減少維數後的特徵向量還保留了足夠的信息量(以區分不同的文字)。
  3. 分類器設計、訓練和實際識別:分類器是用來進行識別的,就是對於第二步,你對一個文字圖像,提取出特徵給,丟給分類器,分類器就對其進行分類,告訴你這個特徵該識別成哪個文字。在進行實際識別前,往往還要對分類器進行訓練,這是一個監督學習的案例。成熟的分類器也很多,什麼svm,kn,神經網路etc。我當時不知天高地厚用經典bp神經網路去學習,結果……呵呵……
  4. 後處理:後處理是用來對分類結果進行優化的,第一個,分類器的分類有時候不一定是完全正確的(實際上也做不到完全正確),比如對漢字的識別,由於漢字中形近字的存在,很容易將一個字識別成其形近字。後處理中可以去解決這個問題,比如通過語言模型來進行校正——如果分類器將「在哪裡」識別成「存哪裡」,通過語言模型會發現「存哪裡」是錯誤的,然後進行校正。第二個,OCR的識別圖像往往是有大量文字的,而且這些文字存在排版、字體大小等複雜情況,後處理中可以嘗試去對識別結果進行格式化,比如按照圖像中的排版排列什麼的,舉個栗子,一張圖像,其左半部分的文字和右半部分的文字毫無關係,而在字元切分過程中,往往是按行切分的,那麼識別結果中左半部分的第一行後面會跟著右半部分的第一行諸如此類。

OCR的大致內容差不多就是這樣。由於我對模式識別尚處於入門階段,如果有什麼地方說錯了,還請指出(並多多包涵)。

以上。


說一下自己做了兩年的topic吧(單指識別)。

自己剛剛開始上手的framework是: CNN + LSTM + CTC。這個framework加上residue network + stn可以把通用的數據集刷的非常高。

之後開始研究attention based的框架,這個框架比較靈活,可挖的坑也比較多,目前遇到的主要問題是數據集。現有的數據集的不夠支撐更加複雜的模型。


我做過一個驗證碼的實現,見基於卷積神經網路實現驗證碼識別(一)和基於卷積神經網路實現驗證碼識別(二)。

不足之處只能識別定長的字元串,也就是用來搞搞驗證碼,車牌號。不過代碼比較簡單,可以當作入門。過幾天寫個基於Fast-RCNN的實現出來


主要是圖像的處理,包括灰度處理、二值化、去噪、旋轉、水平切割、垂直切割

然後再用特徵提取+識別

效果如下(這裡現在只做了英文的演算法):

=======================================

Three months after [he government stopped issulng (%) or renewing permits for In[ernet cafes because of security (%#) concerns, some cafe owners are having flnanclal (ff%%) concerns of their own.

=======================================詳細的可以看看:

拍照怎麼搜題?(上)

拍照怎麼搜題?(下)


我花了一年的時間做了一個蒙古文的OCR識別率在95%以上。且是用Python寫的所以源碼200+行。

上面的朋友們都大體說的差不多了只是我個人覺得OCR的最費時間的地方是訓練樣本!我在這個地方(由於我的筆記本性能不是太好)花了很長的時間去弄的到現在我的識別率提不上去就是因為我的樣本不夠多的問題而樣本多了電腦會受不了的。而且從幾十萬個小圖片中找到識別錯誤的圖片可不是一件簡單的事情啊。需要很大的耐心和毅力而且這是一個長期的任務。希望你加油。


預處理(傾斜校正 去噪等)版面分析 字元切分 特徵提取(確定特徵 降維等) 分類(比如最近鄰 神經網路 svm等等) 後處理(自然語言理解範疇)


利益相關,OCR類app開發者;目前識別印刷體中文已經穩定在95%以上。

OCR一般分為幾個步驟:

1 版面分析 2 行拆分為字元 3 識別字元 4 識別後矯正

如果要進行商業應用,一般來講使用C++和opencv的組合是最好的

如果僅僅學術研究,直接使用matlab即可;但是注意:matlab很多內置演算法的效果不如opencv對應演算法的效果

下面展開來講——

1 版面分析

版面分析也就是把一整張圖像拆分為行;便於後面一行一行地處理。

在圖像沒有明顯傾斜扭曲時,可以先使用筆畫等寬演算法(swt演算法)把非筆跡的像素過濾掉,再使用投影直方圖進行分行;以下是一個分行樣例。

2 行拆分為字元

拆分,就是把每一行拆分到獨立的字;最簡單的辦法就是使用連通域分析或者直方圖投影進行拆分

3 識別字元

識別字元就在於生成樣本+選擇識別演算法

入門可以參考這篇文章OpenCV 2.4+ C++ SVM文字識別

裡面採用了最簡單的辦法進行建模(定位字元區域後縮放到8x8方塊),並且使用了一種很常見的方法(SVM)進行訓練和識別。

實踐中,要注意幾點:

(1)大樣本+簡單識別方法優於小樣本+複雜識別演算法。所以不需要選擇太複雜的建模和分類方法,盡量通過縮放平移等方法把原始樣本展開即可。

(2)字體數量要跟建模方法適應。字體不能太少;否則樣本不足;字體也不能太多,以免樣本互相覆蓋——多個相似的樣本指向不同的標籤。

(3)要考慮單個字元被不當分割和不同字元粘連的情況。這個時候就需要識別演算法能提供置信度的計算,並且嘗試不同識別組合,找到總的置信度最高的一種情況。可以先進行過切分,再使用圖相關演算法找出最佳組合——找到最佳切分組合就相當於在圖裡找到一條最短路徑(這裡的「圖」說的是演算法導論中的圖)。

4 識別後矯正

再好的演算法,也難免會有識別錯誤的時候。比如「了」和「T」, 「1」和「|」,等等。可以考慮使用馬爾可夫模型或者其它類似演算法進行識別結果矯正。

最後安利一下自己的iOS app:深度識別

拍照就可以識別多種語言文字 目前總體五星評價哦 -_- 歡迎大家來捧場


勉強答一個。前面的回答已經比較全面,這裡說一點自己的感覺和總結。最近遇到一個識別各種儀器儀錶示數與文本的任務,考慮到不同於傳統的OCR問題,更接近於自然場景的文本識別問題,看了些關於這方面的研究。從整體上可以分為Detection和Recognition兩個部分;與文檔類的OCR問題不同的是,自然場景中的文字檢測本身是一件十分困難的事情,許多學者進行了很多的嘗試。

在深度學習方法出現之前,基於傳統的手工設計特徵(Handcraft Features),包括基於連通區域,以及基於HOG的檢測框描述的方法是比較主流的;如通過最大穩定極值區域(MSER-Maximally Stable Extremal Regions)得到字元的候選,並將這些字元候選看作連通圖(graph)的頂點,此時就可以將文本行的尋找過程視為聚類(clustering)的過程,因為來自相同文本行的文本通常具有相同的方向、顏色、字體以及形狀。OPENCV3.3中實現了MSER的場景文字檢測和識別的演算法。

在基於深度學習的辦法中,目前看到的大多數解決辦法還是Detection和Recognition分開來研究,並沒有真正的看Detection+Recognition的端到端完成識別的成果。

Detection部分大多數也是基於proposal的,一般先藉助Faster R-CNN或者SSD得到許多個proposal,然後訓練分類器對proposal進行分類,最後再做細緻處理得到精細的文本區域;這個過程中學者們也解決了文字的方向,大小等的問題。同時,也有基於圖像分割來做的,但是看到的不是很多,具體可見參考文獻。

如果已經檢測到了穩定的文本區域,Recognition部分可以採用比較通用的做法;可以對字元進行分割後單獨識別,也可以進行序列識別,容易想見的是,序列識別才是真正有意義的。如前面的答主所說CNN+RNN+CTC的辦法是論文中常看到的;這個辦法也常用在驗證碼的自動識別上面。

在Detection方面,喬宇老師團隊的:Detecting Text in Natural Image with Connectionist Text Proposal Network, ECCV, 2016. 這篇文章在github上有多個實現(CPTN);在Recognition方面白翔老師的CRNN也有不錯的表現。有人在github上將CPTN和CRNN結合了起來,前者採用Caffe實現,後者採用PyTorch實現,但是這並不是真正意義上的端到端。

如何實現自然場景圖片到正確有意義的文本輸出是還需一些努力的。

參考文獻和鏈接:

(1) 文字的檢測與識別資源 - dllTimes - CSDN博客

(2)白翔:趣談「捕文捉字」-- 場景文字檢測 | VALSE2017之十

(3) bgshih/crnn

(4) tianzhi0549/CTPN

(5) Scene Text Detection


傳統的ocr都是二值化,字元分割識別吧。速度比較快,但是只能適應簡單背景。

深度學習檢測,end-to-end識別適應性好,但是cpu速度不行,手機端更別說了。

百度,阿里的demo都不錯,應該也是深度學習檢測,序列識別的。

電腦GPU還行的話,可以自己去訓練一個

https://github.com/bear63/sceneReco

http://blog.csdn.net/u013293750/article/details/73188934

訓練的模型樣本只有100多玩,模型還不穩定,標點符號錯得比較多,因為沒有專門對標點符號進行訓練,都識別成中文了。有硬體支持的話樣本增加到幾千萬,上億,應該會有更好的結果.


剛好現在在公司做OCR和STR, 現在主流的方法是CNN(基於featuremap的文字檢測)+lstm(任意序列的文字行識別),ICDAR2015文字競賽上top的成績基本都是這種方法了,另外題主如果想實現end to end的訓練和預測可以直接考慮簡單暴力的fasterrcnn,出來的結果用cnn過濾下可以達到ICDAR幾個challenge的top3.


切分,歸一化,特徵提取,和資料庫中對比,結果輸出。注意這個資料庫是從標準字體中提取出來的特徵,其實就是模式識別的問題。

模式識別問題:待識別的文字,標準的文字,對標準文字提取特徵,然後對待識別文字進行提取特徵,運用分類器進行分類,然後將結果輸出。


直接 CNN,簡單粗暴有效,老的特徵過程不用學了,馬上淘汰。

http://llcao.net/cu-deeplearning15/pdf/8OCR.pdf


在搜狗做過一點類似的事情,一般就是先拆分出單字,再預處理,然後CNN,訓練一段時間,最後出結果。


第一個答主已經說得很詳細了,補充一點分類器方面的材料,漢字識別以前主要採用最近鄰分類器(KNN)和修正二次判別函數(MQDF),主要是針對掃描文檔OCR和手寫漢字OCR。當然現在深度學習發展迅猛,卷積神經網路(CNN)已經開始大行其道,具體可以看看百度深度學習研究院的技術報告。


單字元用CNN,整行或者單詞用CNN+LSTM+CTC,都有開源實現


給你提供一個現成的框架,也是分那幾步走了,效果不錯

LEADTOOLS Professional OCR Module


我就想知道那些用端到端方法做識別的,最後發現識別不好的時候,怎麼回去調參?改變訓練樣本呢還是怎麼的,感覺抓瞎

在線等,挺急的


推薦閱讀:

怎麼描述一個人的興趣呢,如何數學建模?

TAG:演算法 | 圖形圖像 | 模式識別 | OCR光學字元識別 | 推薦演算法 | 圖像識別 |