# 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 | 訴求辨識準確率<sup>註1</sup> | 較佳 | 慢 | [點此](https://github.com/tesseract-ocr/tessdata) | | tessdata_best | Only LSTM engine | 用於模型的微調 | 佳 | 中 | [點此](https://github.com/tesseract-ocr/tessdata_best) | | tessdata_fast | Only LSTM engine | 訴求辨識速度快 | 中 | 快 | [點此](https://github.com/tesseract-ocr/tessdata_fast) | ###### 註1. 以雙引擎模式(legacy+LSTM engine)進行辨識最準,缺點是最耗時。 ## OCR辨識實務 ### 說明 官方其實已經提供了很好的辨識模型,所以如果辨識關鍵字的辨識效果還堪用,那就就直接用就好,因為訓練的成本偏高,但如果關鍵字的辨識能力不足,那麼再繼續往下參閱說明。 ### 辨識模型 我們選用的是上表所呈現的[tessdata](https://github.com/tesseract-ocr/tessdata)專案,該專案能啟動雙引擎辨識模式,較耗時但較準確。 ### 模型位置 下載完後將模型傳到下列路徑的目錄中。 ``` C:\Program Files\Tesseract-OCR\tessdata ``` ### 指令格式: ```bash 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(分頁模式)<sup>註2</sup>,實務上設6為佳。 * `--oem [num]` 表示OCR Engine modes(OCR 引擎)模式<sup>註3</sup>。 ### 指令範例 ``` 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([下載](https://github.com/UB-Mannheim/tesseract/wiki)) ### 預備檔案 - 訓練文本 - 已訓練模型(tessedata_best-[下載](https://github.com/tesseract-ocr/tessdata_best/blob/master/chi_tra.traineddata)) - 字型檔<sup>註4</sup> ###### 註4. 字型檔若系統有內建就不用特別準備 ## 訓練步驟 ### Step1. 文字轉圖像 **目的:** 將字型套用在給定的字集生成圖檔 **產出:** * `[lang].[fontname].exp[num].tif` 文件 * `[lang].[fontname].exp[num].box` 文件 **指令格式:** ```bash 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"` 字型名稱(不見得是檔名,通常要特別去查)<sup>註5註6</sup>。 * `--fonts_dir="C:\Windows\Fonts"` 原則上是填系統字型文件的路徑,也可以自訂路徑。 若想進一步瞭解各種參數選項的功能與用法,可直接在terminal輸入`text2image`參閱。 **指令範例:** ```bash 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` 文件 **指令格式:** ```bash 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`參閱。 **指令範例:** ```bash 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` 文件 **指令格式:** ```bash tesseract [lang].[fontname].exp[num].tif -l [lang] --psm [lang] lstm.train ``` **指令說明:** 以下針對`tesseract`用於「構建.lstmf文件」的參數選項功能進行說明: * `lstm.train` 表示欲構建.lstmf文件。 **指令範例:** ```bash 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`文件<sup>註7</sup>。 **產出:** * `[lang].lstm` 文件 **指令格式:** ```bash combine_tessdata -e [target .traineddata file] [target file to extract] ``` **指令說明:** 以下針對`combine_tessdata`的常用參數選項功能進行說明: * `-e` 可從`.traineddata`中擷取出特定的文件 * `-u` 可從`.traineddata`中擷取出所有文件至特定資料夾。 * `-o` 可將某文件覆寫進`.traineddata`的文件。 **指令範例:** ```bash 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` 文件 **文件內容<sup>註8</sup>:** ``` chi_tra.MicrosoftJhengHei.exp0.lstmf ``` ###### 註8. 文件中只能有一個`.lstmf`檔的路徑,超過會報錯,請務必留意。 ### Step6. 模型訓練 **目的:** 將所有前置作業所準備好的文件用來進行訓練。 **產出:** * `[name]_checkpoint` 文件 * `[name]_[error_rate]_[iterations].checkpoint` 文件 **指令格式:** ```bash 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`參閱。 **指令範例:** ```bash 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` 文件 **指令格式:** ```bash 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`參閱。 **指令範例:** ```bash lstmtraining --stop_training --continue_from="dist_checkpoint" --traineddata="chi_tra.traineddata" --model_output="dist" ``` ### Step8. 模型測試 將`[lang].traineddata`放入系統的`~\Tesseract-OCR\tessdata`後,接著將terminal的目錄切換到要測試的圖片目錄底下,即可開始進行測試。 **指令範例:** ```bash tesseract test.png result -l chi_tra --psm 6 ``` ## Trobule shooting ### Case1:Compute CTC targets failed! #### 原因: Tesseract OCR發現`.box`文件格式錯誤,通常發生在訓練LSTM模型時,因為LSTM訓練一次只接受一整排框,而不是一格格的文字框,而在行末需要一行\t表示該行結束。 #### 相關討論:[討論1](https://github.com/tesseract-ocr/tesseract/issues/591) 、 [討論2](https://github.com/tesseract-ocr/tesseract/issues/2357#issuecomment-477239316) #### 解決方式: 確保有Step2與Step3有確實完成,並直接跳到Step.6。 ### Case2:Encoding of string failed! #### 原因: 在`[lang].traineddata`文件中有包含許多模型相關的文件,其中一個是`unicharset`文件,裡面記錄著該辨識模型所能辨識的字,相當於LSTM模型能夠分類圖像的類別數量,因此當訓練資料中出現`unicharset`文件沒紀錄的字元時,就相當於模型輸入未知的類別(label),所以就會報出這個錯誤。 #### 相關討論:[討論1](https://github.com/tesseract-ocr/tesseract/issues/2695) 、 [討論2](https://github.com/tesseract-ocr/tesseract/issues/1012) #### 解決方式: 針對`unicharset`文件中「沒有被紀錄的字」新建一個`unicharset`文件,並包裝成一個新的`[lang].traineddata`文件對於舊的(欲訓練的)`[lang].traineddata`文件進行訓練,使得原有LSTM模型能夠「支援新類別」也能夠「正確辨識新類別」,因此,也需要針對「欲新增的類別(字)」準備一份訓練文本讓模型訓練。 #### 注意事項: 此步驟相當費工,要擴充的新字除非很關鍵,否則千萬不要貪心的認為反正都要做了,那就連同一些罕用字或特殊符號都一起擴充,這可能會造成樣本蒐集不足,導致模型無法收斂,也可能造成模型訓練成本(時間、精力)過高,甚至使模型過於龐大而造成效能不足。 #### 步驟流程: **Step1. `unicharset`文件中「沒有被紀錄的字」獲取** * **想法流程:** 展開`[lang].traineddata`文件,並從中找到`unicharset`文件,接著可以透過自行撰寫程式,進而過濾訓練文本中有哪些未被`unicharset`文件所記錄到的文字而保留下來。 * **目標產出:** 未被`unicharset`文件所記錄到的文字。 * **指令格式:** ```bash combine_tessdata -u [path of target file] ``` * **指令範例:** ```bash combine_tessdata -u dist/chi_tra.traineddata ``` **Step.2 `.box`文件獲取** * **想法流程:** 透過`text2image`指令能將文字轉為`.tif`與`.box`。 * **目標產出:** `.box`文件。 * **指令格式:** ```bash text2image --text="[path to text file]" --outputbase="[lang].[fontname].exp[num]" --fontconfig_tmpdir="[directory of temp]" --font="[fontname]" --fonts_dir="[directory of fontname]" ``` * **指令範例:** ```bash 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`文件。 * **指令格式:** ```bash unicharset_extractor --output_unicharset [path to unicharset] --norm_mode 1 [path to .box file] ``` * **指令範例:** ```bash unicharset_extractor --output_unicharset chi_tra.unicharset --norm_mode 1 chi_tra.MicrosoftJhengHei.exp0.box ``` **Step.4 `unicharset`文件的字元屬性設定** * **想法流程:** 透過`set_unicharset_properties`指令,將讀取官方所提供langdata<sup>註9</sup>內的資訊,寫入`unicharset`文件的字元屬性中。 * **目標產出:** 已修改字元屬性的`unicharset`文件。 * **指令格式:** ```bash set_unicharset_properties -U [path to unicharset] -O chi_tra.unicharset --script_dir [directory of langdata] ``` * **指令範例:** ```bash set_unicharset_properties -U chi_tra.unicharset -O chi_tra.unicharset --script_dir dist\langdata-master ``` ###### 註9:請將官方提供的[langdata](https://github.com/tesseract-ocr/langdata)整個專案都clone下來。 **Step.5 新建`.traineddata`文件打包** * **想法流程:** 將新產生的`unicharset`文件重新打包成`.traineddata`文件,以備後續訓練進行使用。 * **目標產出:** `.traineddata`文件 * **指令格式:** ```bash combine_lang_model --input_unicharset [path to unicharset] --lang [lang] --script_dir [directory of langdata] --output_dir [directory of output] ``` * **指令範例:** ```bash 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` 文件 * **指令範例:** ```bash # 文字轉圖像 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`文件 * **指令範例:** ```bash 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`文件 * **指令範例:** ```bash 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 #### 官方說明:[連結](https://tesseract-ocr.github.io/tessdoc/TrainingTesseract-4.00.html#error-messages-from-training) #### 官方論壇:[連結](https://groups.google.com/g/tesseract-ocr) ## 參考資料 * [官方文件](https:/https://tesseract-ocr.github.io/tessdoc/TrainingTesseract-4.00.html) * [中譯版-官方文件](https://ivanzz1001.github.io/records/post/ocr/2017/09/18/tesseract-training) * [Tesseract-OCR 4.0LSTM訓練流程 (Windows環境下)](https://www.twblogs.net/a/5d744adbbd9eee541c3423a2) * [Tesseract 4.0 LSTM训练超详细教程](https://zhuanlan.zhihu.com/p/58366201) * [Tesseract OCR tips — custom dictionary to improve OCR](https://vovaprivalov.medium.com/tesseract-ocr-tips-custom-dictionary-to-improve-ocr-d2b9cd17850b) * [WORDLIST2DAWG(1) Manual Page](https://github.com/tesseract-ocr/tesseract/blob/master/doc/wordlist2dawg.1.asc) ###### tags: `日月光`
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.