Try   HackMD

Tesseract-OCR LSTM模型訓練指南

前言

技術歷史

Tesseract-OCR在第3版以前用的是傳統的辨識引擎(legacy engine),從第4版開始,Tesseract-OCR引入LSTM這種以深度學習為基礎的辨識引擎(LSTM engine),使得辨識的準確度能進一步獲得提升,因此本指南將針對LSTM訓練相關的知識與技巧進行說明。

模型訓練成本、辨識速度與準確度間的權衡

中文屬於表意文字,因此中文系統中有著數以萬計的中文字用以表意,從模型訓練的角度來看這意味著一件事,若要建構「全中文字通用的OCR辨識模型」,將會有數萬個類別(label值),從手寫數字數據集-MNIST類別與訓練資料的比例為10:60000來看,這表示訓練通用模型至少需要上千萬筆的訓練資料,因此不可能也不需要訓練這樣一個全中文字通用的模型,即便有這樣一個模型,辨識速度也可能因為模型過於龐大而變慢。

實務操作

從實務上來講,官方已有提供相對較通用且準確的辨識模型,只要以該辨識模型做為基礎,接著對模型進行微調(Fine tune)的動作,就能針對特定辨識錯誤的字詞加強訓練,切記,只需對關鍵字進行訓練,訓練過多的冗餘字,只會造成模型肥大效能下降,官方目前已經針對不同應用情境訓練對應的模型,如下表所示:

模型名稱 類型 應用情境 準確度 速度 專案連結
tessdata Both legacy & LSTM engine 訴求辨識準確率註1 較佳 點此
tessdata_best Only LSTM engine 用於模型的微調 點此
tessdata_fast Only LSTM engine 訴求辨識速度快 點此
註1. 以雙引擎模式(legacy+LSTM engine)進行辨識最準,缺點是最耗時。

OCR辨識實務

說明

官方其實已經提供了很好的辨識模型,所以如果辨識關鍵字的辨識效果還堪用,那就就直接用就好,因為訓練的成本偏高,但如果關鍵字的辨識能力不足,那麼再繼續往下參閱說明。

辨識模型

我們選用的是上表所呈現的tessdata專案,該專案能啟動雙引擎辨識模式,較耗時但較準確。

模型位置

下載完後將模型傳到下列路徑的目錄中。

C:\Program Files\Tesseract-OCR\tessdata

指令格式:

tesseract [pic to be tested] [output file name] -l [lang] --psm [num] --oem [num]

指令說明

  • 圖片辨識支援格式:包含bmp、pnm、png、jfif、jpeg、tiff,建議png或tif。
  • --psm [num] 表示Page segmentation modes(分頁模式)註2,實務上設6為佳。
  • --oem [num] 表示OCR Engine modes(OCR 引擎)模式註3

指令範例

tesseract test.png result -l chi_tra --psm 6 --oem 2
註2 psm的代碼意義
代碼 意義
0 Orientation and script detection (OSD) only.
1 Automatic page segmentation with OSD.
2 Automatic page segmentation, but no OSD, or OCR. (not implemented)
3 Fully automatic page segmentation, but no OSD. (Default)
4 Assume a single column of text of variable sizes.
5 Assume a single uniform block of vertically aligned text.
6 Assume a single uniform block of text.
7 Treat the image as a single text line.
8 Treat the image as a single word.
9 Treat the image as a single word in a circle.
10 Treat the image as a single character.
11 Sparse text. Find as much text as possible in no particular order.
12 Sparse text with OSD.
13 Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.
註3 oem的代碼意義
代碼 意義
0 Legacy engine only.
1 Neural nets LSTM engine only.
2 Legacy + LSTM engines.(雙引擎辨識模式)
3 Default, based on what is available.

先備條件

運行環境

  • Windows 10
  • Tesseract OCR v 5.0 alpha(下載)

預備檔案

  • 訓練文本
  • 已訓練模型(tessedata_best-下載)
  • 字型檔註4
註4. 字型檔若系統有內建就不用特別準備

訓練步驟

Step1. 文字轉圖像

目的: 將字型套用在給定的字集生成圖檔
產出:

  • [lang].[fontname].exp[num].tif 文件
  • [lang].[fontname].exp[num].box 文件

指令格式:

text2image --text="[text file path]" --outputbase="[lang].[fontname].exp[num]" --fontconfig_tmpdir="[temp directory]" --font="[fontname]" --fonts_dir="[fontname directory]"

指令說明:
以下針對text2image的常用參數選項功能進行說明:

  • --text="all_chi_new.txt" 是要進行訓練的樣本文件路徑。
  • --outputbase="chi_tra.MicrosoftJhengHei.exp0" 欲生成.tif.box文件的路徑與名稱。
  • --fontconfig_tmpdir="%temp%" 字型組態檔的暫存位置(填環境變數即可),不填會報錯。
  • --font="Microsoft JhengHei" 字型名稱(不見得是檔名,通常要特別去查)註5註6
  • --fonts_dir="C:\Windows\Fonts" 原則上是填系統字型文件的路徑,也可以自訂路徑。

若想進一步瞭解各種參數選項的功能與用法,可直接在terminal輸入text2image參閱。

指令範例:

text2image --text="all_chi_new.txt" --outputbase="chi_tra.MicrosoftJhengHei.exp0" --fontconfig_tmpdir="%temp%" --font="Microsoft JhengHei" --fonts_dir="C:\Windows\Fonts"
註5. 常見字型對應名稱
中文名稱 樣式 對應英文名稱
微軟正黑體 Regular Microsoft JhengHei
微軟正黑體 Bold Microsoft JhengHei Bold
微軟正黑體 Light Microsoft JhengHei weight=290
新細明體 Regular mingliub
標楷體 Regular DFKai-SB
蘋方體 Ultralight PingFang TC Ultralight
蘋方體 Light PingFang TC Light
蘋方體 Thin PingFang TC Thin
蘋方體 Regular PingFang TC Regular
蘋方體 Medium PingFang TC Medium
蘋方體 Semibold PingFang TC Semibold
註6. 命名注意事項

填入字型名稱時,--font須填入正確的fontname,該空格就要空格,但是--outputbase出現空格則會報錯,正確範例如下:

  • --font="Microsoft JhengHei weight=290"
  • --outputbase="chi_tra.MicrosoftJhengHeiLight.exp0"

Step2. .box文件重建

目的: 由於LSTM訓練一次只接受一整排框,而不是一格格的文字框,而在行末還需要一行\t表示該行結束,因此需透過tesseract指令中的wordstrbox參數重建.box文件,在訓練的資料量較大時,此步驟相當耗時,若不做可能會報錯,但即便沒報錯,訓練時的錯誤率(loss)也會極高。

格式:

# .box file with wordstrbox format
1 148 127 268 151 0
2 148 127 268 151 0
3 148 127 268 151 0
4 148 127 268 151 0
5 148 127 268 151 0
6 148 127 268 151 0
7 148 127 268 151 0
8 148 127 268 151 0
     148 127 268 151 0

產出:

  • [lang].[fontname].exp[num].box 文件

指令格式:

tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] -l [lang] --psm [num] wordstrbox

指令說明:
以下針對tesseract用於「構建wordstrbox格式的.box文件」的參數選項功能進行說明:

  • -l [lang] 指定欲使用的辨識語言e.g. chi_tra。
  • wordstrbox 表示欲構建wordstrbox格式的.box文件。

若想進一步瞭解各參數選項的功能與用法,可在terminal輸入tesseract --help-extra參閱。

指令範例:

tesseract chi_tra.MicrosoftJhengHei.exp0.tif chi_tra.MicrosoftJhengHei.exp0 -l chi_tra --psm 6 wordstrbox

Step3. 模型訓練檔構建

目的: 透過.box.tif檔產生.lstmf檔,用於模型訓練。
產出:

  • [lang].[fontname].exp[num].lstmf 文件

指令格式:

tesseract [lang].[fontname].exp[num].tif  -l [lang] --psm [lang] lstm.train

指令說明:
以下針對tesseract用於「構建.lstmf文件」的參數選項功能進行說明:

  • lstm.train 表示欲構建.lstmf文件。

指令範例:

tesseract chi_tra.MicrosoftJhengHei.exp0.tif chi_tra.MicrosoftJhengHei.exp0 -l chi_tra --psm 6 lstm.train

Step4. 已訓練的LSTM模型擷取

目的:tessedata_best所下載的chi_tra.traineddata中擷取chi_tra.lstm文件註7
產出:

  • [lang].lstm 文件

指令格式:

combine_tessdata -e [target .traineddata file] [target file to extract]

指令說明:
以下針對combine_tessdata的常用參數選項功能進行說明:

  • -e 可從.traineddata中擷取出特定的文件
  • -u 可從.traineddata中擷取出所有文件至特定資料夾。
  • -o 可將某文件覆寫進.traineddata的文件。

指令範例:

combine_tessdata -e chi_tra.traineddata chi_tra.lstm

若想進一步瞭解各參數選項的功能與用法,可直接在terminal輸入combine_tessdata參閱。

註7. 模型的微調並非一定要以tessedata_best.lstm文件為基礎,而是要確定.traineddata需為基於LSTM模型所訓練,但由於tessedata_best是官方所提供訓練較全面且準確的模型,因此通常以tessedata_best為基礎。

Step5. 訓練資料清單建立

目的: 建立一個文件檔,提供訓練檔的路徑。
產出:

  • [lang].training_files.txt 文件

文件內容註8

chi_tra.MicrosoftJhengHei.exp0.lstmf
註8. 文件中只能有一個.lstmf檔的路徑,超過會報錯,請務必留意。

Step6. 模型訓練

目的: 將所有前置作業所準備好的文件用來進行訓練。
產出:

  • [name]_checkpoint 文件
  • [name]_[error_rate]_[iterations].checkpoint 文件

指令格式:

lstmtraining --model_output="[directory of output]" --continue_from="[path to lstm]" --traineddata="[path to .traineddata file]" --train_listfile="[path to train_listfile]" --target_error_rate=[float]

指令說明:
以下針對lstmtraining用以「訓練模型」的參數選項功能進行說明:

  • --model_output 指定模型訓練完所輸出的路徑。
  • --continue_from 指定LSTM模型的路徑,以該模型繼續訓練。
  • --train_listfile 指定存放欲被訓練之.lstmf檔的文件路徑。
  • --traineddata 指定.traineddata文件路徑。
  • --target_error_rate 指定模型準確度收斂的標準(停止標準)。
  • --debug_interval (optional)預設為0,每100個迭代輸出進度報告,若為-1則改為每次迭代輸出進度。

若想進一步瞭解各參數選項的功能與用法,可直接在terminal輸入lstmtraining參閱。

指令範例:

lstmtraining --model_output="dist" --continue_from="chi_tra.lstm" --traineddata="chi_tra.traineddata" --train_listfile="chi_tra.training_files.txt" --target_error_rate=0.01

Step7. 模型輸出

目的: 模型訓練完產生的[name]_checkpoint文件表示模型參數,將其寫入模型。
產出:

  • [lang].traineddata 文件

指令格式:

lstmtraining --stop_training --continue_from="[path to [name]_checkpoint file]" --traineddata="[path to .traineddata file]" --model_output="[directory of output]"

指令說明:
以下針對lstmtraining用以「模型輸出」的參數選項功能進行說明:

  • --stop_training 表示將training model轉換為runtime model。
  • --continue_from 指定[name]_checkpoint文件的路徑,以轉換為runtime model。
  • --traineddata 指定將被更新model的.traineddata文件路徑。
  • --model_output 指定模型訓練完所輸出的路徑。

若想進一步瞭解各參數選項的功能與用法,可直接在terminal輸入lstmtraining參閱。
指令範例:

lstmtraining --stop_training --continue_from="dist_checkpoint" --traineddata="chi_tra.traineddata" --model_output="dist"

Step8. 模型測試

[lang].traineddata放入系統的~\Tesseract-OCR\tessdata後,接著將terminal的目錄切換到要測試的圖片目錄底下,即可開始進行測試。

指令範例:

tesseract test.png result -l chi_tra --psm 6

Trobule shooting

Case1:Compute CTC targets failed!

原因:

Tesseract OCR發現.box文件格式錯誤,通常發生在訓練LSTM模型時,因為LSTM訓練一次只接受一整排框,而不是一格格的文字框,而在行末需要一行\t表示該行結束。

相關討論:討論1討論2

解決方式:

確保有Step2與Step3有確實完成,並直接跳到Step.6。

Case2:Encoding of string failed!

原因:

[lang].traineddata文件中有包含許多模型相關的文件,其中一個是unicharset文件,裡面記錄著該辨識模型所能辨識的字,相當於LSTM模型能夠分類圖像的類別數量,因此當訓練資料中出現unicharset文件沒紀錄的字元時,就相當於模型輸入未知的類別(label),所以就會報出這個錯誤。

相關討論:討論1討論2

解決方式:

針對unicharset文件中「沒有被紀錄的字」新建一個unicharset文件,並包裝成一個新的[lang].traineddata文件對於舊的(欲訓練的)[lang].traineddata文件進行訓練,使得原有LSTM模型能夠「支援新類別」也能夠「正確辨識新類別」,因此,也需要針對「欲新增的類別(字)」準備一份訓練文本讓模型訓練。

注意事項:

此步驟相當費工,要擴充的新字除非很關鍵,否則千萬不要貪心的認為反正都要做了,那就連同一些罕用字或特殊符號都一起擴充,這可能會造成樣本蒐集不足,導致模型無法收斂,也可能造成模型訓練成本(時間、精力)過高,甚至使模型過於龐大而造成效能不足。

步驟流程:

Step1. unicharset文件中「沒有被紀錄的字」獲取

  • 想法流程: 展開[lang].traineddata文件,並從中找到unicharset文件,接著可以透過自行撰寫程式,進而過濾訓練文本中有哪些未被unicharset文件所記錄到的文字而保留下來。
  • 目標產出: 未被unicharset文件所記錄到的文字。
  • 指令格式:
combine_tessdata -u [path of target file]
  • 指令範例:
combine_tessdata -u dist/chi_tra.traineddata

Step.2 .box文件獲取

  • 想法流程: 透過text2image指令能將文字轉為.tif.box
  • 目標產出: .box文件。
  • 指令格式:
text2image --text="[path to text file]" --outputbase="[lang].[fontname].exp[num]" --fontconfig_tmpdir="[directory of temp]" --font="[fontname]" --fonts_dir="[directory of fontname]"
  • 指令範例:
text2image --text="all_chi_new.txt" --outputbase="chi_tra.MicrosoftJhengHei.exp0" --fontconfig_tmpdir="%temp%" --font="Microsoft JhengHei" --fonts_dir="C:\Windows\Fonts"

Step.3 unicharset文件構建

  • 想法流程: 透過unicharset_extractor指令能將.box文件轉為unicharset文件。
  • 目標產出: unicharset文件。
  • 指令格式:
unicharset_extractor --output_unicharset [path to unicharset] --norm_mode 1 [path to .box file]
  • 指令範例:
unicharset_extractor --output_unicharset  chi_tra.unicharset --norm_mode 1 chi_tra.MicrosoftJhengHei.exp0.box

Step.4 unicharset文件的字元屬性設定

  • 想法流程: 透過set_unicharset_properties指令,將讀取官方所提供langdata註9內的資訊,寫入unicharset文件的字元屬性中。
  • 目標產出: 已修改字元屬性的unicharset文件。
  • 指令格式:
set_unicharset_properties -U [path to unicharset] -O chi_tra.unicharset --script_dir [directory of langdata]
  • 指令範例:
set_unicharset_properties -U chi_tra.unicharset -O chi_tra.unicharset --script_dir dist\langdata-master
註9:請將官方提供的langdata整個專案都clone下來。

Step.5 新建.traineddata文件打包

  • 想法流程: 將新產生的unicharset文件重新打包成.traineddata文件,以備後續訓練進行使用。
  • 目標產出: .traineddata文件
  • 指令格式:
combine_lang_model --input_unicharset [path to unicharset] --lang [lang] --script_dir [directory of langdata] --output_dir [directory of output]
  • 指令範例:
combine_lang_model --input_unicharset chi_tra.unicharset --lang chi_tra --script_dir dist\langdata-master --output_dir dist

Step.6 訓練資料準備

  • 想法流程: 將第一步所保留未被unicharset文件所記錄的文字用於建構訓練的語料,可用不同的字型、角度、雜訊等等方式產出圖片,並接續產出所有訓練所需的檔案。
  • 目標產出:
    • [lang].[fontname].exp[num].box 文件
    • [lang].[fontname].exp[num].tif 文件
    • [lang].[fontname].exp[num].lstmf 文件
    • [lang].training_files.txt 文件
  • 指令範例:
# 文字轉圖像
text2image --text="training_text.txt" --outputbase="chi_tra.MicrosoftJhengHei.exp0" --fontconfig_tmpdir="%temp%" --font="Microsoft JhengHei" --fonts_dir="C:\Windows\Fonts" --xsize=2000 --ysize=3000

# .box文件重建
tesseract chi_tra.MicrosoftJhengHei.exp0.tif chi_tra.MicrosoftJhengHei.exp0 -l chi_tra --psm 6 wordstrbox

# 模型訓練檔構建
tesseract chi_tra.MicrosoftJhengHei.exp0.tif chi_tra.MicrosoftJhengHei.exp0 -l chi_tra --psm 6 lstm.train

Step.7 寫入新unicharset文件並訓練模型

  • 想法流程: 準備好下列文件,並進行模型訓練。
    • 由新unicharset文件打包成的新traineddata文件
    • 由原traineddata文件擷取出來的lstm模型
    • traineddata文件
    • 存放欲被訓練之.lstmf檔的training_files文件。
  • 目標產出: .traineddata文件
  • 指令範例:
lstmtraining --model_output="dist" --continue_from="chi_tra.lstm" --traineddata="dist\chi_tra\chi_tra.traineddata" --old_traineddata="chi_tra.traineddata" --train_listfile="chi_tra.training_files.txt" --target_error_rate=0.05
  • 指令說明
    • --traineddata 指定新traineddata文件的路徑
    • --old_traineddata 指定原traineddata文件的路徑

Step.8 將訓練結果寫入新模型

  • 想法流程: 選定錯誤率最低的[name]_[error_rate]_[iterations].checkpoint 文件寫入模型,更新版的模型就會支援新字元並且具備辨識能力,後續就能以該模型為基礎,針對其它辨識效果不佳的字元加強訓練。
  • 目標產出: .traineddata文件
  • 指令範例:
lstmtraining --stop_training --continue_from="dist_0.012_360000_360000.checkpoint" --traineddata="dist\chi_tra\chi_tra.traineddata" --old_traineddata="chi_tra.traineddata" --model_output="dist\chi_tra.traineddata"

應變邏輯

More detail

官方說明:連結

官方論壇:連結

參考資料

tags: 日月光