今天來說說文字識別
說到文字識別先給大家介紹一個工具吧。圖像預處理,或者生成訓練數據集的工具。
傳送門:https://github.com/tmbdev/ocropy
但是!圖片處理比較慢。本人根據需求用opencv重新了寫了下,速度提升10倍不止。要是用了umat可能會更快!要代碼的留言 最近會發到github上
說到工具,在給大家介紹一個做OCR必須要知道wiki:
傳送門:https://github.com/wanghaisheng/awesome-ocr/wiki
37個pages希望可以幫到你!
前言書講過,OCR主要分兩個步驟,1文字檢測2文字識別
那麼文字檢測通過以上幾片文章,然後根據自己的需求稍微制定化一下,應該可以解決95%的問題。
那麼現在說說OCR 第二部 那就是文字識別。
文字識別呢 在下大概試過兩種形式。
一種呢,先參考OCR系列第一篇的檢測。文字分割後 形成每個單一的文字框,這樣利用一個相對淺層的cnn,來做分類。經驗告訴我,對於這樣的文字框來說,網絡層並不是越深越好。
另一種呢,是接著第二遍第三篇的檢測來說的。就是文本行作為輸入進行檢測。文本行。文字個數 不固定。今天就主要講講這類的算法的框架:CRNN!
CRNN整體來看其實很容易理解。顧名思義:cnn+rnn
最好的學習其實就是看paper 我所做的也是跟大家更快的讀一篇paper 然後突出重點,在說一說自己遇到的坑,與解決的過程
好吧 先來給大家「科普」:crnn!
呦呦切克鬧,網絡結構來一套,卷積循環我都要,CTC層最重要!
那些介紹cnn是vgg16啊 去除全連接層啊,我就不多說了。重點是Before being fed into the network, all the images need to be scaled to the same height.所有的圖像都需要縮放到相同高度!
更細緻看一看cnn rnn的參數。。你會發現不同
後面兩個MaxPooling的kennel是1*2的 ,這樣會有比較寬的特徵圖,更長的特徵序列,另外加了bn層訓練會快很多 更好train。
然後接下來看Transcription
這一層解決什麼問題呢?
大家都知道lstm出來之後是很多個序列的。但是這麼多個序列我怎麼和原始圖片的字符對應呢?這就用到了ctc的思想了。整如下面一句話
We adopt the conditional probability defined in the Connectionist Temporal Classification (CTC) layer proposed by Graves et al. [15]
那好吧!我們來看看ctc
首先推薦大家看看我們的老朋友 HMM隱馬爾可夫。前向計算什麼的都是一樣。
舉個例子 比如做驗證碼識別:原始圖片的驗證碼是:1234 四個數字
在數字中加blank
那麼有兩個trick可以用
一:_1_2_3_4_
二:11223444
反過來想:其實就是找到所有輸出的序列中,找到那些可以通過某些規則可以轉換成原先數字的序列!
看這圖是不是眼熟?是的跟第一篇傳統ocr文章中的思路差不多的。都是找路徑問題。
然後用了前向計算反向計算
現在看看loss
L(S)=−ln∏(x,z)∈Sp(z|x)=−∑(x,z)∈Slnp(z|x)
其中
p(z|x) 代表給定輸入x,輸出序列 z 的概率,S為訓練集。損失函數可以解釋為:給定樣本後輸出正確label的概率的乘積。在看這句話 在看這個loss 是不是有些思路了呢?
遇到的問題:
1,文本訓練的時候,由於大部分數據生成的,造成與真實分割的圖片 前後空白不一樣。造成左右(前後)空白比較大的地方會識別出莫名其妙的東西。可以通過檢測後處理 或者擴充數據集。
2,當批量預測的時候,需要統一圖片的寬度。以最長的為基準,短的都用空白填充。這樣又出現了上面的問題,而且會浪費大量算力和顯存!
效果: 對於轉移領域比如掃描件 可以達到98%以上 但是對於相對通用的環境只有94%左右