Halcon的OCR字符識別算法技巧總結 Halcon自動化訓練OCR分類器舉例

 

一、重要算子

OCR分類器其實有很多,如下圖所示。但是通常mlp分類器效果較好,使用較多。

 

 

 主要算子如下:

① append_ocr_trainf(Character, Image : : Class, TrainingFile : )

四個參數分別是:字符Region、字符Image、字符文本、OCR訓練的.trf文件路徑

 

如果該路徑下不存在.trf文件,那麼它會自動生成該文件。

該算子作用是將單個字符區域、單個字符圖像和對應的字符文本寫入TrainingFile 文件。

 

② read_ocr_trainf_names( : : TrainingFile : CharacterNames, CharacterCount)

查詢.trf訓練文件中存儲有哪些字符,以及每個字符在訓練器中的數量。

 

③ create_ocr_class_mlp(42, 67, 'constant', 'default', CharacterNames, NumHidden, 'none', 10, 42, OCRHandle)

最前面的兩個參數分別指字符的寬度高度。NumHidden指隱藏層的層數,一般不宜過低。

 

④ trainf_ocr_class_mlp( : : OCRHandle, TrainingFile, MaxIterations, WeightTolerance, ErrorTolerance : Error, ErrorLog)

訓練神經網絡,通常參數用默認值即可。

 

⑤ write_ocr_class_mlp( : : OCRHandle, FileName : )

保存OCR的的.omc分類器到文件。

 

⑥ read_ocr_class_mlp( : : FileName : OCRHandle)

從文件中讀取OCR的.omc分類器。

 

一個典型的創建OCR分類器的過程通常是:

append_ocr_trainf → create_ocr_class_mlp → trainf_ocr_class_mlp → write_ocr_class_mlp 

 

具體創建OCR分類器的方法,可以看這個例子:Halcon自動化訓練OCR分類器舉例

 

 

二、關鍵問題

1、create_ocr_class_mlp算子中,如何確定字符的寬度和高度?

 

同一種字體不同字符的寬度、高度是不一樣的(例如字母A和I),如何確定這兩個值?

有兩種方式:一是直接測量字符中較寬字符的寬度和高度,把它們作爲 WidthCharacterHeightCharacter ;二是使用OCR助手(助手——打開新的OCR)來分析得出這兩個值(推薦這種方式)。

 

 

轉到“分割”頁面即可看到自動分析得出的“字符寬度”和“字符高度”等信息。

 

 

2、使用自己訓練的OCR分類器,還是使用Halcon自帶的分類器?

 

如果字體恰好合適的話,使用Halcon自帶的分類器,通常效果是極好的。但是缺點也很明顯:一是選擇有限,如果需要OCR的字體比較特殊,可能選不好合適的分類器;二是你很難對Halcon自帶的分類器進行優化,因爲它只提供.omc文件,而不提供訓練用的.trf文件

 

自己訓練的分類器也有優缺點。訓練和使用分類器主要使用下面幾個算子:

append_ocr_trainf、create_ocr_class_mlp、trainf_ocr_class_mlp、do_ocr_multi_class_mlp

 

缺點一是需要自己切割字符收集字庫,如下所示:

 

缺點二是可能自己訓練的分類器不如Halcon自帶的分類器效果好。(原因一方面因爲字庫不夠豐富,另一方面可能對OCR的理解不夠深刻,導致訓練分類器時有些細節考慮不周全)

不過自己訓練分類器也有優點,最大的的優點是訓練過程可控,而且自己可以添加字符圖片,豐富字庫,即分類器可以不斷得到優化。這一點是Halcon自帶的分類器所不具備的。

 

3、如果使用Halcon自帶的分類器,如何選擇合適的?

 

點擊OCR助手中的下圖中的紅框中的圖標即可。

 

 

先加載“訓練文件”(.trf),再加載“分類器”(.omc),即可看到識別結果及其把握度。當所有字符均識別正確,且把握度很高的時候,就說明這個分類器很合適。

 

 

4、如何準確分割出圖像中的字符區域?

 

OCR的過程實際是調用do_ocr_multi_class_mlp算子。

do_ocr_multi_class_mlp(Character, Image : : OCRHandle : Class, Confidence)

 

其中Character即是字符區域(Region),如下所示:

 

 

分割字符區域的思路有兩種:① 用形態學閾值分割;② 用find_text系列算子。

形態學分割算子大家比較熟悉,不需要多說,但是算子之間的組合比較靈活,思路比較重要。

 

find_text分割字符區域代碼舉例如下:(Characters即是字符區域Region)

 

注:如果自己訓練OCR分類器,create_text_model_reader就不需要傳入.omc文件路徑,例如:

create_text_model_reader ('manual', [], TextModel)

 

5、對於字符區域分割,形態學閾值分割和find_text方法,哪種更好?

 

通常來說,直接用find_text系列算子,很容易得到比較不錯的字符區域分割結果。因爲它可以通過set_text_model_param算子設置很多字體的信息參數,例如:

 

這種方法的優點很明顯:就是很容易做到標準化。只需要設置幾個參數,就可以得到很好的分割效果。

但是這種方法的缺點也很明顯,它的自由度有點差,效果不理想時,繼續優化的辦法有限。如果該設的參數都設置了,分割字符區域效果還是不理想,該怎麼辦呢?

 

因此,對於經驗豐富的視覺算法工程師,對於棘手的OCR項目,我仍然推薦使用形態學閾值分割來分割字符區域(Region),不過這個需要相當的技巧。

 

6、提高字符區域分割效果的技巧。

 

提高OCR準確率有兩條路子:① 訓練分類器時,儘量用豐富的字符圖片庫,訓練出良好的分類器;② 識別前,儘量分割出準確的字符區域,好利於識別。

 

訓練分類器的過程中,其實能玩出的花樣並不多。因此重點還是在分割字符區域這一步,建議如下:

 

(1)儘量把需要OCR的文字圖像轉正

(2)可以用reduce_domain算子把需要OCR的圖像區域挖出來,排除圖像其他區域的干擾。

(3)分割之前可以增強圖像的對比度,例如使用scale_image_max和emphasize算子。

(4)改變圖像中字符筆畫寬度的算子gray_erosion_rect可嘗試使用,但是如果字符本身比較小,這個算子就不建議使用了,因爲此時它對字符筆畫的寬度改變會很大。

(5)如果圖像光照情況基本一致,儘量使用threshold而不是binary_threshold這類自動閾值算子。因爲threshold的結果是可預測的,而自動閾值的分割結果通常較難預測

(6)閾值分割以後,可以使用select_shape算子限定一些篩選條件,篩選出真正的字符部分。

 

特別注意:訓練分類器的程序正式識別字符的程序中,圖像預處理和閾值分割方式必須一致,這樣才能得到最好的OCR效果。

 

7、對於識別錯的“相似”字符的補救措施。

 

有些字符是很相似的,例如字母“Q”和“O”,字母“I”和數字“1”。

 

對於上圖的Q和O,如果容易識別混淆,那麼如何判斷到底是Q還是O呢?

 

提供一種思路:可以求字母內部的空白區域,調用算子:convexity (CharRegion, Convexity)

這個算子可以獲得Q或者O內部區域的“凸度”,凸度極高的,說明這個字符是O,反之就是Q。

 

其他字符也可以用其他方法分別個性化判斷。

 

另外,對於OCR,可以觀察圖中字符的分佈,例如某一塊區域只可能出現數字,但是識別出了形如“058I”這樣的結果,那麼很可能就是把數字“1”錯判爲了字母“I”。這時可以人爲把字母“I”改成數字“1”作爲後續補救措施。

 

至於其他未提到的OCR技巧,歡迎留言補充。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章