ocr中文,字元切分時如何保證切出整個漢字,例如知這個字?

另外,好像英文的i也存在這個問題。


居然被邀請,受寵若驚……

話說知乎上就沒有些專業做OCR的么?有的話也來回答一下嘛_(:3」∠)_

首先,講一下投影分割法——這應該是用於字元切分的最簡單直接的一種辦法了,也是我所知道的唯一方法……所謂投影分割法是根據圖像在水平和垂直兩個方向的投影密度來確定行切分和字元切分。一般是先進行行切分,然後對每一文本行進行垂直投影進行字元切分。以行切分為例,首先判斷圖片是否存在傾斜,若存在則先進行傾斜校正(計算傾斜角度然後進行坐標變換),保證文本行都是水平的後,逐行掃描圖像,記錄每一行的前景像素點(即組成文字的像素點)個數,得到一個圖像像素在水平方向上的統計結果,如下圖所示:

然後根據這個結果來決定每一個文本行的起始行和結束行,最一般的做法是閾值法,即設定一個閾值,根據每一行的前景像素個數決定該行是否屬於「文本行」的一部分。對於上圖,可以設定閾值為2。當然,閾值的設定可以依靠個人經驗,應該也有一些方法可以計算出一個合適的閾值。

之前說過,在文本行切分好後,就對每一個文本行行進行字元切分,這個原理和行切分是一樣的。即進行垂直投影,然後設定閾值進行分割。這裡應該就是題主關心的地方,那就是:對於一些包含左右結構的字,如何不將其分割為兩部分呢?對於這個問題,下面是我的解決方法:

1. 通過空白區域寬度判斷當前空白區域是字與字之間的空隙,還是同一個字內結構與結構之間的空隙。比如和前一個空白區域、後一個空白區域的寬度進行比較,或者與空白區域寬度的均值進行比較,一般來說,同一個字內部結構之間的空隙寬度是要比字與字之間的空隙小的,當然,這也不是絕對的。

2. 通過字的寬度/寬高比來判斷當前切割出來的「字」是一個完整的字還是一個完整的字的一部分。不同的字體,會有不同的字體寬高比,所以利用字寬可能是個更好的方法,原理與通過空白區域寬度進行判斷的方法類似。

當然,結合以上兩種方法也許會更好。

除此以外,是否有其他更好更魯棒的做法,我相信是有的,但是實在慚愧,我所知道的,也就這麼一點,希望能有幫助。


有些字是怎麼分割都不能分到一起,投影這種方法太粗放,還有兩種方法可以補救。

先進行垂直投影,分割字元的條件就是投影值是否為0,這樣的結果會有三種,正確的分割了字元---一個字元被分割開----幾個粘連字元被分在一起,補救的方法就是要解決後面兩種情況;

方法一:解決幾個粘連字元被分在一起的情況

對於幾個粘連字元被分在一起的部分,採用簡單的分類器比如淺層ANN對圖片迭代識別,保留識別情況最好的分割方法

方法二:解決一個字元被分割開的情況

如果一個字元,比如 知,被分成了兩部分,在後續分割中先不管,下一步該識別了,通過對識別結果進行檢查,對於分割太窄的前後相鄰兩部分合併重新識別。

具體操作過程涉及比較多,不再贅述,僅提供思路。


英文有等寬和不等寬。中文幾乎是方塊字。統計多數字體寬度和高度。進行二次處理。左右結構的初次識別成兩個字也沒關係。但是保留元信息。二次處理時根據元信息以及初步識別出的字元,符合左右結構的就合併成類似的字。


方塊字有字元寬度的先驗知識,手寫體的話一般採用過分割+語言模型+路徑搜索的方法


看到題目想到大學的時候做一個項目,汽車牌照OCR。這個比普通的OCR簡單很多,因為牌照上能出現的漢字字母數字範圍很小,而且字形是標準的。

一開始是用投影分割法,對於左右結構的字當然很容易斷在錯誤的位置上。於是想了一下,從後往前識別吧:車牌照後6位都是字母,這6部分都是整體結構的,肯定錯不了。剩下的整體當成一個字識別好了。

然後發現這樣依然有問題,必須得判斷出漢字的左邊界,才能把字型切出來,縮放成標準大小,否則左邊一塊空白的話跟模板是匹配不上的。於是又用上了寬高比,考慮到照片本身的寬高比可能不是非常標準,會根據後6位切分結果(字母/數字的大小)自動計算出漢字可能的寬高比範圍,根據這個可變的寬高比來切分。

這樣對於大部分圖片都能有比較好的結果,但是有的時候還是沒法正確識別「豫」,怎麼辦?給模板里加一個「象」的形狀,對應的識別結果是「豫」,問題解決。


第一步可以投影法粗暴分割,第二步根據統計分析,對異常數據進行合併或者切割操作等二次處理,當然可以直接上mser+swt方法,也是要結合一定的策略才能達到很好的效果,話說現在比較火的lstm搞整行文字識別,不知道誰搞過吖?


自然場景ocr只要找到到大體位置就可以識別,如果是書上這種整塊的文本,其實根本可以不用分割直接整體識別


推薦閱讀:

如何從0學習opencv,完成類似人臉檢測的畢設?

TAG:Python | 演算法 | 圖形圖像 | OCR光學字元識別 | OpenCV |