tesseract-ocr 第四課 如何訓練新語言

tesseract 3.0x是完全可訓練的。該頁描述了訓練過程,提供了一些指南來應用到各語言中。

版權所有,轉載請註明出處,並標明鏈接
作者:jolly wang

介紹

tesseract 3.0x是完全可訓練的。該頁描述了訓練過程,提供了一些指南來應用到各語言中。


背景和權限

tesseract原先只爲English文本而設計。後來經過努力,可以處理其它語言,以及 utf8字符。tesseract 3.0可以處理任何unicode字符,但只限於已經成功的字符集。

tesseract 3.01 新增了 從上到下 閱讀順序的語言, tesseract 3.02 添加了希伯來語 Hebrew (從右到左)。tesseract當前只有一個輔助引擎cube來處理阿拉伯語(Arabic)。(在3.0+中新增)

tesseract在一些大語種語言中進展緩慢,比如中文,但是目前可以運行。

任何語言都有不同的標點和數字,很難被只認ASCII標點和數字的 硬編碼算法識別 。該問題將在3.0x中解決。x>=2

4.1:需要的數據

爲了訓練另一種語言,你可以在tessdata子目錄下創建一些數據文件,接着使用combine_tessdata將它們融合進一個文件,命名規範爲: languagecode.file_name。語言碼可以遵從ISO 639-3標準。3.00使用的English文件有:
  • tessdata/eng.config
  • tessdata/eng.unicharset
  • tessdata/eng.unicharambigs
  • tessdata/eng.inttemp
  • tessdata/eng.pffmtable
  • tessdata/eng.normproto
  • tessdata/eng.punc-dawg
  • tessdata/eng.word-dawg
  • tessdata/eng.number-dawg
  • tessdata/eng.freq-dawg
接着融合成一個文件:
tessdata/eng.traineddata

然後提供另一個獨立文件:

tessdata/eng.user-words

traineddata文件通常是一個輸入文件的連接,帶有目錄表,幷包含了已知文件類型的偏移。在源代碼中見ccutil/tessdatamanager.h,可以看到當前接受的文件名列表。注意, traineddata 文件不同於3.00版本以上的列表,並且很可能在以後版本中變動。

4.2 準備文本輸入文件

文本輸入文件( lang.config, lang.unicharambigs, font_properties, box files, wordlists for dictionaries.. )需要滿足以下需求:

  • ASCII 或者 utf8 編碼,沒有BOM
  • uinx行結尾符('\n')
  • 文件尾空行(否則:將得到錯誤信息:last_char == '\n':Error:Assert failed..

4.2.1 How little can you get away with?

你必須使用下面的過程來創建 unicharset, inttemp, normproto, pfftable。如果你只嘗試識別一個受限範圍的字體(例如:單一字體),那麼一個簡單的訓練頁就足夠了。在你的應用程序中不再需要提供 另外的文件 ,但是必須更精確。老的DangAmbigs已經被替換成 unicharambigs。

4.3 訓練過程

一些過程不可避免是人工的。儘可能提供自動化幫助。在將來,會出來許多自動化工具,但需要更復雜的install/build過程。以下的工具是自帶的:

4.3.1 生成訓練圖像

第一步是決定使用完整的字符集,準備一個包含了許多樣本集的文本或詞處理文件。重點要注意的是,當創建一個訓練文件時:

  • 確保每個字符的最小數目的樣本。10很好,但5只對少數字符有效。
  • 常用字符的樣本應更多:至少20個。
  • 不要將所有非字母組合在一起。讓文件更實際化。例如,“The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&(),.{}<>/?”,這個就很糟糕。而這個則更好:“The (quick) brown {fox} jumps! over the $3,456.78<lazy> #90 dog & duck/goose, as 12.5% of E-mail from [email protected] is spam?” ,這個給出了文本行查找碼,來獲取特定字符的基標語義。
  • 當打印時,文本空格絕對安全。。。。。。
  • 訓練數據應該按字體分組。。。。。
  • 沒必要訓練多個size的文本。。。。。
  • 不要在一個image文件混合多種字體(確切的說:在單個.tr文件中),它將造成丟棄一些特徵,導致識別錯誤
  • 下載頁的boxtiff文件將幫助你如何格式化你的訓練數據。

接着,打印和掃描(使用一些電子渲染方法)來創建你的訓練頁的image。直到32個訓練文件都被使用。它交創建一個混合的字體和樣式,包含italic和bold。

注意:由於間距,訓練真實的image是相當困難的,這個將在未來改善。對於現在,更容易打印和掃描你自己的訓練文本。

你也可以保存你的文本成爲一個utf8文本文件,用來在下一步中,將代碼插入到另一個文件。

對於大量訓練數據的識別,對於多數字體, 限制 32個圖像。每個字體都應被放到單個 多頁tiff(只有你正使用libtiff),和boxfile中,可以通過修改指定頁數來爲每個字符做協調。。。。。

4.3.2 製作box file

接下來,tesseract需要一個‘box’文件來定位每個訓練圖像。box文件是一個文本文件,它在每行列出了訓練圖像的字符,以及圍繞 bounding box 的座標。tesseract 3.0有一個模式,可以用來輸出一個需要格式的文本文件,但是如果字符集不同於當前訓練,它將自然地具有不對的文本。因此,這裏的關鍵是,需要人工編輯正確的文本進去。

命令行下運行tesseract你的訓練圖片:
tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox

比如:

tesseract eng.timesitalic.exp0.tif eng.timesitalic.exp0 batch.nochop makebox

接下來是最困難的部分。你需要編輯文件  [lang].[fontname].exp[num].box ,併爲每個字符放至utf8編碼在文件是每行起始處。例如:發行版包含了一個圖像:eurotext.tif. 運行以上的命令來生成一個文本文件,可 以包含下面的行:
s 734 494 751 519 0 p 753 486 776 518 0 r 779 494 796 518 0 i 799 494 810 527 0 n 814 494 837 518 0 g 839 485 862 518 0 t 865 492 878 521 0 u 101 453 122 484 0 b 126 453 146 486 0 e 149 452 168 477 0 r 172 453 187 476 0 d 211 451 232 484 0 e 236 451 255 475 0 n 259 452 281 475 0

因爲 Tesseract  以英文模式運行 ,它不能正確識別元音(umlaut)。這種字符需要使用一個合適的編輯器來糾正。可以使用能識別utf8的編輯器。HTML 編輯器是個不錯的選擇。。。。

理論上,boxfile中的每行都表示了你訓練文件中的每個字符,如果你需要水平分隔字符,比如雙逗號 ,, 它將具有兩個box需要合併。

示例: lines 116-129:
D 101 504 131 535 0 e 135 502 154 528 0 r 158 503 173 526 0 , 197 498 206 510 0 , 206 497 214 509 0 s 220 501 236 526 0 c 239 501 258 525 0 h 262 502 284 534 0 n 288 501 310 525 0 e 313 500 332 524 0 l 336 501 347 534 0 l 352 500 363 532 0 e 367 499 386 524 0  389 520 407 532 0

你將看到, 最下面的雙引號字符被表達成兩個單一的逗號。bounding box必須按以下方式合成:
  • 第一個數(左)採用兩行中最小的(197)
  • 第二個數(下)採用兩行中最小的(496)
  • 第三個數(右)採用兩行中最大的(214)
  • 第四個數(上)採用兩行中最大的(508)

於是,給出:
D 101 504 131 535 0 e 135 502 154 528 0 r 158 503 173 526 0 ? 197 497 214 510 0 s 220 501 236 526 0 c 239 501 258 525 0 h 262 502 284 534 0 n 288 501 310 525 0 e 313 500 332 524 0 l 336 501 347 534 0 l 352 500 363 532 0 e 367 499 386 524 0  389 520 407 532 0
如果你不能成功地在訓練圖像中將字符分隔開,其中一些會被圈進另一個box中。在一些情況下,你可以使用更好的空格和起點,重新標註圖像。(比如:2.04,有24個字節來描述一個字符的限制,這將允許你 根據你的unicode字符集, 在6到24個unicode間來描述這個字符。如果達到該限制,請編寫一個issue描述你的情況)

注意:在box 文件中的座標系統,在左下邊有(0,0)。

如果你的編輯器支持utf8,該過程將更簡單,每個utf8字符都最高支持4字節來編寫它,使用dumb功能可以查看所有字節。

一些支持編輯box文件的可視化工具: AddOns wiki .

4.3.3 自引導一個新的字符集

如果你嘗試一個新的字符集,將它們使用單字體來獲取一個新的box文件會很合適,運行其餘的訓練過程,接着使用tesseract來生成其它的box文件:
tesseract fontfile.tif fontfile -l yournewlanguage batch.nochop makebox

這將使得第二個box文件更容易生成,一種較好的選擇是,tesseract將識別出大多數正確文本。你可以總是重複這個過程,來添加更多的字體到訓練集中(比如:命令行工具 mfTraining 和 cnTraining)來製作它們,但是注意,還沒有增量模式來允許你添加新的訓練數據到存在的字符集中。這意味着每次你運行mfTraining和cnTraing工具,你可以從tr文件中製作新的數據文件,這些工具不會將採用已經存在的intproto/pffmtable/normproto並將它們直接添加進去。

4.3.4 全新提供Tif/Box pair!!

Tif/Box 對在新的下載頁提供。(注意:tiff文件採用G4壓縮以便節省空間,因此,你必須首先具有libtiff或者未壓縮的數據)。你可以遵從以下過程,來爲你的語言生成更好的訓練數據或添加不同的字符形狀到已經存在的語言中:

  1. 過濾box文件,只保持你想要的字符。
  2. 運行tesseract來訓練。
  3. 對於每種字體,從多個語言中cat出.tr文件,來獲取你想要的字符休,並從你有的字體或字符中添加.tr文件
  4. 以相同的方式cat出已經過濾的box文件到.tr文件中,以便在unicharset_extractor中處理
  5. 運行訓練過程的其它步驟

注意!這聽起來並不簡單!cntraining和mftraining只能最多采用32個.tr文件,因此,對於相同的字體,你必須從多種語言中,以字體獨立的方式,將所有的文件 cat到一起來讓32種語言結合在一起。cntraining/mftraining以及unicharset_extractor命令行工具必須各自由給定的.tr和.box文件,以相同的順序,爲不同的字體進行不同的過濾。可以提供一個程序來完成以上的事情,並在字符集表中挑出相同字符集。這樣會將事情更簡單些。

4.3.5 運行 tesseract進行訓練

對於你的訓練圖像,box文件對,以訓練模式運行tesseract:
tesseract fontfile.tif junk nobatch box.train
或者
tesseract fontfile.tif junk nobatch box.train.stderr
在版本2.03及以下,第一種方式發送所有錯誤給 tesseract.log(在所有平臺上)。而使用box.train.stderr,將發送錯誤到stderr 上。

注意,box文件名必須匹配tif文件名,包含路徑,否則tesseract將找不到它。這一步的輸出是fontfile.tr,它包含了訓練頁的每個字符的特徵。注意,輸出名從輸入的圖像名中派生出來,而非正常的輸出名,這裏的junk. junk.txt將被使用單個不帶文本的新行來寫。

非常重要 在apply_box中確認輸出錯誤。如果報告了FATALITIES,沒必要繼續訓練過程, 直到你你修正box文件。新的box.train.stderr配置文件使得它很選擇輸出的位置。一個FATALITY通常標明這一步錯誤。如果該座標錯誤,那麼關注的特徵圖像也將錯誤。如果一個字符沒有工作樣本不能被識別,那麼生成的inttemp文件將不會茶杯unicharset文件,接着tesseract 將中止。

另一個錯誤:box file format error on line n.。。。。。。。

沒必要編輯fontfile.tr文件的內容。裏面的字體名不必設置。出於好奇,以下是該格式的信息:
Every character in the box file has a corresponding set of entries in the .tr file (in order) like this UnknownFont <utf8 code(s)> 2 mf <number of features> x y length dir 0 0 ... (there are a set of these determined by <number of features> above) cn 1 ypos length x2ndmoment y2ndmoment The mf features are polygon segments of the outline normalized to the 1st and 2nd moments. x= x position [-0.5.0.5] y = y position [-0.25, 0.75] length is the length of the polygon segment [0,1.0] dir is the direction of the segment [0,1.0] The cn feature is to correct for the moment normalization to distinguish position and size (eg c vs C and , vs ')

5 計算字符集

tesseract需要知道可能要輸出的字符集。爲了生成unicharset數據文件,在相同的頁bounding box文件上使用unicharset_extractor程序進行聚類:
unicharset_extractor fontfile_1.box fontfile_2.box ...
tesseract需要訪問字符屬性  ( isalpha, isdigit, isupper, islower. ).該數據而可以以unicharset的數據形式被編碼。每行都是一個字符。utf8的字符是按照十六進制數表達。每位表示一個屬性。如果相應位置1,它意味着屬性是真的。這些位(從最小位到最大位): isalpha, islower, isupper, isdigit。

示例:
  • ';' 爲非字母字符,小寫字符,大小字符,而非數字。它的屬性通過二進制數 10000表示(16進制的10表示 )
  • 'b'是一個字母字符,小寫字符。它的屬性通過二進制數00011表示(3)
  • 'W'是一個字母字符,大寫字符。它的屬性通過二進制數00101表示(5)
  • '7'只是一個數字。它的屬性通過二進制數01000表示(8)
  • ‘=’非數字或字母字符。它的屬性通過二進制數字00000表示(0)
; 10 Common 46 b 3 Latin 59 W 5 Latin 40 7 8 Common 66 = 0 Common 93

日文或中文字母字符屬性由二進制數00001表示(1)

如果你的系統支持wctype函數,這些值都將通過unicharset_extractor自動設置,並且沒必要通編輯unicharset文件。在一些老的系統中,unicharset文件必須通過手動添加屬性描述代碼。

注意  inttemp, normproto  和 pffmtable被生成時, unicharset文件必須重新生成 (比如:當box文件被更改時,它們必須被重新創建)。必須以正確的方式,隨着inttemp存儲成索引到unicharset中時,實際的字符將通過給定索引的unichaset分類器返回。

最後兩列表示腳本類型( Latin, Common, Greek, Cyrillic, Han, null ),以及相應語言的字符id。

5.1 字體屬性(3.01 中新)

3.01中的新需求是font_property文件。該文件的目的是提供字體形式信息,當字體被識別時,將出現在輸出中。font_properties 文件是一個文本文件,通過 -F filename 選項指定來進行mftraining.

每行的font_properties文件都以如下進行格式化:
<fontname> <italic> <bold> <fixed> <serif> <fraktur>
當<fontname>是一個字體的字符串名,並且<italic>, <bold>, <fixed>, <serif> and <fraktur>  是所有簡單的0 或 1標記,表示字體具有命名屬性。

當運行mftraining時,每個.tr文件名必須有相關entry在font_properties文件中,否則將中止mftraining。。。。。

例如:

font_properties文件如下:
timesitalic 1 0 0 1 0
shapeclustering -F font_properties -U unicharset eng.timesitalic.exp0.tr mftraining -F font_properties -U unicharset -O eng.unicharset eng.timesitalic.exp0.tr 

5.2 聚合

當所有訓練頁的字符特徵被抽取出來時,我們需要將它們聚集起來創建prototype文件。這些字符形狀特性可以通過使用shapeclustering(在3.02版本之後提供)、mftraining 和 cntraining 程序進行聚焦。

shapeclustering -F font_properties -U unicharset lang.fontname.exp0.tr lang.fontname.exp1.tr ...
shapeclustering通過形狀聚集創建了主形狀表,並將它寫到一個文件中:shapetable.
mftraining -F font_properties -U unicharset -O lang.unicharset lang.fontname.exp0.tr lang.fontname.exp1.tr ...
-U 文件表示unicharset,由上面的 unicharset_extractor  生成,   lang.unicharset是輸出unicharset,它將由combine_tessdata給出。Mftraining將輸出兩個其它的數據文件:inttemp(形狀原型)和pffmtable(每個字符所希望的特徵)。  
cntraining lang.fontname.exp0.tr lang.fontname.exp1.tr ...
它將輸出normproto 數據文件(character normalizati on sensitivity prototypes 


6.字典數據(可選)

tesseract爲每種語言使用三個字典文件。兩種文件被編碼成 有向非循環字圖. DAWG (   Directed Acyclic Word Graph ).其它是普通utf8文本文件:

Name Type Description
punc-dawg dawg A dawg made from punctuation patterns found around words. The "word" part is replaced by a single space.
word-dawg dawg A dawg made from dictionary words from the language.
number-dawg dawg A dawg made from tokens which originally contained digits. Each digit is replaced by a space character.
freq-dawg dawg A dawg made from the most frequent words which would have gone into word-dawg.
fixed-length-dawgs dawg Several dawgs of different fixed lengths —— useful for languages like Chinese.
bigram-dawg dawg A dawg of word bigrams where the words are separated by a space and each digit is replaced by a ?.
unambig-dawg dawg TODO: Describe.

爲了生成DAWG字典文件,你首先需要爲你的語言提供一個wordlist。你需要找到一個合適的字典文件,用來作爲一個spellcheckers  的 wordlist的基礎 (ispell aspell hunspell)== 注意lincense. wordlist格式化成一個utf8的文本文件,每行都有一個詞。將wordlist分割成需要的集合: 比如:常用詞,其它剩下的詞,接着使用worldlist2dawg來生成DAWG文件:
wordlist2dawg frequent_words_list lang.freq-dawg lang.unicharset wordlist2dawg words_list lang.word-dawg lang.unicharset
對於從右向左的語言(RTL)使用選項 "-r 1".  其它選項參照: wordlist2dawg Manual Page

注意:wordlist必須包含至少一個單詞!在合併的traineddata文件中不允許存在。

如果單詞總是具有標點在其中,比如:google.com , 那麼在字典中包含它們很合適。

最後的字典文件稱爲:user-words,通常爲空。

如果你需要字典wordlists的樣本文件,解合併(使用 combine_tessdata )已經存在的語言數據文件(比如:eng.traineddata),接着使用 dawg2wordlist 抽取wordlists.

7、最後的文件(unicharambigs

tesseract最後使用的數據文件稱爲: unicharambigs 。它表示了在字符或字符集間固有的模糊,這通常整個都是以人工方式生成。爲了理解文件格式,查看以下示例:
v1 3       I I 0   2       u o     3 3       I - I   1       H       2 2       ' '     1       "       1 2       ?? 6    1       ??     1 1       m       2       r n     0 3       i i i   1       m       0
第一行是一個版本標識符。剩下的行包含了5個以tab分隔的字段。第一個字段表示的是第二個字段的字符串數。第三個字段表示的是第四個字段的字符串數。第5個字段是一個類型標識符。第二和第四個字段表示了空格分隔的字符串。這可以是一個utf8格式的文件,因此,每個字符串是一個utf8字符串。每個這樣的字符串必須匹配unicharset文件中一些行的第一個字段,比如,它必須是一個可識別單元。

類型表示符的值如下:
Value Type Description
0 NOT_AMBIG the ngram pair is not ambiguous
1 REPLACE_AMBIG ocred ngram should always be substituted with correct
2 DEFINITE_AMBIG add correct ngram to the classifier results (1-1)
3 SIMILAR_AMBIG use pairwise classifier for ocred/correct pair (1-1)
4 CASE_AMBIG this is a case ambiguity (1-1)

替代規則是,
如果第5個字段爲1, 在第二字段中的 字符串集聯總會被第4字段中的字符串聯連替代。
如果第5個字段爲0,那麼沒必要替換。

它扮演着hint的角色,如果替換將一個非字典詞替換爲一個字典詞,那麼,這個詞就應該用來訓練該適配性分類器,分段搜索可以提高識別第4個字段的可能性。主要影響是,第5個字段爲0的主要影響是,減少錯誤適配,它不會使用更高的hint來替代。

當爲2時,第一行顯示了雙引號('')應該被替換單引號(')。(第5個字段標是是否標準替換)。第二行表示的是,pair 'rn'可能有時被識別成'm'。而第三行表示,字母‘m ’可能有時被識別成序列'iii'。第4行表示, 埃納德語符號“ ?? ”,常被誤識別,因爲符號“ ?? ”後面跟着的數字‘6’,接着的序列常常被替換。最後一行可以是空行('\n')。

注意, 兩邊的 字符應出現在 unicharset中。該文件不能用來從一種字符翻譯成另一種字符。

unicharambigs文件應該爲空,或者不存在。

8.將它們放在一起

所有都合在一起!你需要做的所有事情是將它們收集在一起(shapetable, normproto, inttemp, pffmtable),並且重命名爲一個lang.prefix,lang可以是3個字符的編碼(   http://en.wikipedia.org/wiki/List_of_ISO_639-2_codes  ),接着以如下方式運行:
combine_tessdata lang.
注意,不要忘記加句點。

接着將生成lang.traineddata。tesseract可以識別文本:
tesseract image.tif output -l lang
實際上,你可以使用語言碼中的任何字符串,但是,如果你想任何人能輕易理解,按ISO 639的方式命名。

關於 combine_tessdata 更多選項,在 Manual Page 或者源碼註釋中( source code )。

轉自:http://my.oschina.net/ywbrj042/blog/405992
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章