Tesseract5 fine tune Chinese character
Tesseract5 fine tune Chinese character如何实现?
在Train Tesseract LSTM with tesstrain.sh on Windows中,有网友提到在Github/Tesseract中下载的chi_sim.traineddata无法识别”垤,箐,勐”等较为生僻的文字,我们是否能自行对chi_sim.traineddata进行Fine Tune呢?网友提出这个问题时,我用自己编译的Tesseract4版本尝试Fine tune失败,最近用Tesseract5和tesstrain的makefile训练上述文字成功,本文记录训练过程以及训练过程中的疑问。
Fine Tune Chinese character
先假定我们的新字库的名称为chi_simFT,tesstrain下载后约定其解压路径为tesstrain-main。
tessdata
ground-truth
先用我们下载的chi_sim.traineddata进行验证测试图片,下图红色矩形划出的字是原字库无法正常识别的。
1 2 3 4 5 6 7 |
E:\>tesseract ChText.png stdout -l chi_sim Detected 30 diacritics 10KV 西门开闭所 110KV 东峨变 110KV 澧江变 220KV 元江变 35KV 贫河变 35KV 大龙潭 35KV 旬中变 35KV 高平变 35KV 江东变 35KV 那塘变 35KV 洼坏变 35KV 温泉变 35KV 羊街变 35KV 动仰变 35KV 咪哩变帮庄稍电站峨山县调滑石板电站 漫沙田电站南溪河电站清水河电站小河底二级站小河底一级站伊萨河二级水电 站伊萨河一级水电站玉溪地调玉溪市调元江县调 10.0.2.下 |
在进行LSTM的Fine Tune时,我们应该让该文字多次出现在不同的词组或文本中进行训练。在准备训练文件时,针对上述无法正确识别的文字分别准备两个词语或两行文本图片,如下图所示。本文主要为测试,故准备的图片比较少,个人认为正式训练时应该需要更多的数据样本。
同时每张图片都有其对应的.gt.txt文件,该文件中存储的时图片中的文字,以UTF-8的格式存储,例如yongmeng.gt.txt对应的内容为:
1 |
勐,勇猛也 |
所有的.png和gt.txt文件的路径均为tesstrain-main\data\chi_simFT-ground-truth,本文准备的.png和.gt.txt如下图所示。
.numbers/.punc/.wordlist/radical-stroke/Latin.unicharset
Han.unicharset
MakeFile
1 |
TESSDATA = $(LOCAL)/share/tessdata |
1 |
TESSDATA=data/tessdata |
1 |
MODEL_NAME = chi_simFT |
4. 修改shell find
cygwin中无法执行shell find,有两种方式处理该问题点。
处理方式1: 将makefile中的两处shell find进行如下修改:
1 |
shell /usr/bin/find |
处理方式2: 参考tesstrain-win中makefile的代码进行修改,也是有两处:
在makefile中搜索 $(GROUND_TRUTH_DIR) -name ‘*.gt.txt’ , 找到如下代码:
1 2 3 |
$(ALL_GT): $(shell /usr/bin/find -L $(GROUND_TRUTH_DIR) -name '*.gt.txt') @mkdir -p $(OUTPUT_DIR) find -L $(GROUND_TRUTH_DIR) -name '*.gt.txt' | xargs paste -s > "$@" |
将其修改为:
1 2 3 |
$(ALL_GT): $(wildcard $(GROUND_TRUTH_DIR)/*.gt.txt) @mkdir -p $(OUTPUT_DIR) find $(GROUND_TRUTH_DIR) -name '*.gt.txt' | xargs cat | sort | uniq > "$@" |
在makefile中再次搜索 $(GROUND_TRUTH_DIR) -name ‘*.gt.txt’ , 找到如下代码:
1 2 3 |
$(ALL_LSTMF): $(patsubst %.gt.txt,%.lstmf,$(shell find -L $(GROUND_TRUTH_DIR) -name '*.gt.txt')) @mkdir -p $(OUTPUT_DIR) find -L $(GROUND_TRUTH_DIR) -name '*.lstmf' | python3 shuffle.py $(RANDOM_SEED) > "$@" |
将其修改为:
1 2 3 |
$(ALL_LSTMF): $(patsubst %.gt.txt,%.lstmf,$(wildcard $(GROUND_TRUTH_DIR)/*.gt.txt)) @mkdir -p $(OUTPUT_DIR) find $(GROUND_TRUTH_DIR) -name '*.lstmf' -exec echo {} \; | sort -R -o "$@" |
做完上述修改后,打开命令提示符,进入tesstrain-main所在路径,运行如下命令:
1 |
make training --trace |
在以上两种处理方式中,处理方式1在执行到lstmtraining命令时,会出现如下错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
lstmtraining \ --debug_interval 0 \ --traineddata data/chi_simFT/chi_simFT.traineddata \ --old_traineddata data/tessdata/chi_sim.traineddata \ --continue_from data/chi_sim/chi_simFT.lstm \ --learning_rate 0.0001 \ --model_output data/chi_simFT/checkpoints/chi_simFT \ --train_listfile data/chi_simFT/list.train \ --eval_listfile data/chi_simFT/list.eval \ --max_iterations 10000 \ --target_error_rate 0.01 Loaded file data/chi_sim/chi_simFT.lstm, unpacking... Warning: LSTMTrainer deserialized an LSTMRecognizer! Code range changed from 224 to 226! Num (Extended) outputs,weights in Series: 1,48,0,1:1, 0 Num (Extended) outputs,weights in Series: C3,3:9, 0 Ft16:16, 160 Total weights = 160 [C3,3Ft16]:16, 160 Mp3,3:16, 0 TxyLfys64:64, 20736 Lfx96:96, 61824 RxLrx96:96, 74112 Lfx512:512, 1247232 Fc226:226, 115938 Total weights = 1520002 Previous null char=223 mapped to 225 Continuing from data/chi_sim/chi_simFT.lstm Deserialize header failed: data/chi_simFT-ground-truth/chalukou.lstmf Deserialize header failed: data/chi_simFT-ground-truth/eshan.lstmf Deserialize header failed: data/chi_simFT-ground-truth/meng.lstmf Deserialize header failed: data/chi_simFT-ground-truth/gui.lstmf Deserialize header failed: data/chi_simFT-ground-truth/yongmeng.lstmf Deserialize header failed: data/chi_simFT-ground-truth/chahe.lstmf Load of page 0 failed! Load of images failed!! make: *** [Makefile:287: data/chi_simFT/checkpoints/chi_simFT_checkpoint] Error 1 |
此时需要手动将tesstrain-main/data/foo/list.train, tesstrain-main/data/foo/all-lstmf,tesstrain-main/data/foo/list.eval换行符转换为LF,再次运行make training,即可顺利完成。
而处理方式2则可以顺利完成训练,不需要手动修改换行符。
正常训练完成的信息如下:
1 2 3 4 5 6 7 8 |
Finished! Selected model with minimal training error rate (BCER) = 0 Makefile:299: update target 'data/chi_simFT.traineddata' due to: data/chi_simFT/checkpoints/chi_simFT_checkpoint lstmtraining --stop_training --continue_from data/chi_simFT/checkpoints/chi_simFT_checkpoint --traineddata data/chi_simFT/chi_simFT.traineddata --model_output data/chi_simFT.traineddata Loaded file data/chi_simFT/checkpoints/chi_simFT_checkpoint, unpacking... |
训练得到的traineddata文件位于路径tesstrain-main\data下,将其拷贝至tesseract5的安装路径的tessdata文件夹中,我电脑的安装路径为D:\Program Files\Tesseract-OCR\tessdata,对同一张图片的测试结果如下:
1 2 3 4 5 6 7 8 |
E:\>tesseract ChText.png stdout -l chi_simFT Detected 30 diacritics 10KV 西 门 开 闭 所 110KV 东 峨 变 110KV 澧 江 变 220KV 元 江 变 35KV 岔 河 变 35KV 大 龙 潭 35KV 甸 中 变 35KV 高 平 变 35KV 江 东 变 35KV 那 塘 变 35KV 洼 垤 变 35KV 温 泉 变 35KV 羊 街 变 35KV 勐 仰 变 35KV 咪 哩 变 帮 庄 箐 电 站 峨 山 县 调 滑 石 板 电 站 漫 阔 田 电 站 南 溪 河 电 站 清 水 河 电 站 小 河 底 二 级 站 小 河 底 一 级 站 伊 河 二 级 水 电 站 伊 河 一 级 水 电 站 玉 溪 地 调 玉 溪 市 调 元 江 县 调 10.0.2. 玫 |
对比chi_sim.traineddata和chi_simFT.traineddata的测试结果,我们会发现有以下几点差异:
1. chi_sim无法识别的“岔,垤,箐,勐”等文字,通过fine tune之后,chi_simFT可以正确识别这些文字。
2. 但在chi_simFT中,原本可以识别的“漫沙田”被识别为“漫阔田”,“伊萨河”被识别为“伊河”。
3. chi_sim识别的结果中格式与空格基本与图片一致,但经过fine tune之后,chi_simFT的识别格式则与图片的格式相去甚远。
由以上对比结果可知,fine tune之后的字库虽然可以识别针对性训练的文字,但又很多缺陷,可能是训练过程中有一些细节问题未处理好,还需要继续学习。
感谢阅读,欢迎交流。