Tesseract 4.x 新字体微调训练

前言

首先,就个人而言,Tesseract 的 Wiki 关于训练的教程,写得真的混淆,对于英语不是特别好的人来说看得是云里雾里的。
我是看了一两天的文档,硬是理清楚是个什么样的流程,网上搜的教程基本上都是官方Wiki的翻译,并且翻译得也不是很好,最终 youtube 上看了一个老外关于微调的完整例子,终于理清流程。
说到Tesseract的训练,关于百度上搜到的那些结果真的是让人很失望,大多都是Tesseract 3.x的方法,Tesseract 3.x还没有引入LSTM,因此那些文章关于Tesseract的训练都是手动添加训练文字图片进行校正,这种识别其实就是利用庞大的字库文字特征码来识别的,算不上什么人工智能。这种方式的文字识别需要大量的添加中文字库,其实在看这种文章的时候大家就会发现一个问题:如何大量的进行训练呢?一张一张添加图片生成box文件并校正?对于个人来说这真的是非人类操作!
所以实际上Tesseract4.x版本新增了LSTM训练,与此同时3.x版本的训练模式依旧可用,并且有专门工具批量根据字体生成.tif训练图片样本,哪里还需要我们自己来手动添加,下面就来一步一步讲解LSTM训练,如果不想进行LSTM训练,完全可以只生成.box等文件后手动合并训练结果。

训练流程

准备工作:

  • 若不是从头训练,我认为只需要安装需要训练的字体即可,Linux字体安装自行百度。
  • 不管你安没安装好Tesseract,训练必须要克隆整个项目到本地:https://github.com/tesseract-ocr/tesseract
  • langdata_lstm克隆到本地:https://github.com/tesseract-ocr/langdata_lstm,如果网速不好的话可以不用全部克隆(1G左右),自行找到`chi_sim`与`eng`下载即可,这些文件是必须的:
    1. wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/radical-stroke.txt
    2. wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/common.punc
    3. wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/font_properties
    4. wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/Latin.unicharset
    5. wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/Latin.xheights
    然后chi_simeng自行建好目录将github上对应目录下的文件全部下载下来即可。主要包含了语言包的一些配置,以及一些用来生成训练的文字及单词。
  • tessdata官方训练好的字库,这里我们训练的是中文,所以去下载chi_sim.traineddata以及eng.traineddata,eng.traineddata是必须的。这里我选择的是官方的fast版本,后面训练时的版本必须是best版本。tessdata目录在克隆的tesseract项目里,不必自建,因为里面还包含了一些其他文件,我们要做的就是将官方训练好的字库下载到该目录。

1、生成待训练数据(官方 langdata 中中文字库训练样本为 25MB 左右的文本,全部生成图片的话会过大,所以这里指定最多生成 50 页文字):

  1. ~/tesstutorial/tesseract/src/training/tesstrain.sh \
  2. --fonts_dir /usr/share/fonts \
  3. --lang chi_sim --linedata_only \
  4. --noextract_font_properties \
  5. --langdata_dir ~/tesstutorial/langdata \
  6. --tessdata_dir ~/tesstutorial/tesseract/tessdata \
  7. --save_box_tiff --maxpages 150 \
  8. --fontlist "SimHei" \
  9. --output_dir ~/tesstutorial/train

生成的训练文件都在~/tesstutorial/train目录下。
解释:这一步操作,实际上是利用 text2image 将要训练的样本文字转换为 tif 图片,生成的图片中的文字都是校正好的,可以自己打开看一下。这样一来,我们知道生成的图片对应的正确文字,我们就可以拿来与官方现有训练好的数据进行评估。即:用官方现有的训练字库来识别生成的图片,将识别结果,与我们生成时已知的文字进行对比,就能知道当前训练库对于当前字体的识别率了,当然,这不需要我们自己手动去识别比对计算识别率了,有专门的工具。

2、提取 chi_sim.lstm 文件:

combine_tessdata -e ~/tesstutorial/tesseract/tessdata/chi_sim.traineddata ~/tesstutorial/chi_sim.lstm

进行评估:
lstmeval —model ~/tesstutorial/chi_sim.lstm \
—traineddata ~/tesstutorial/train/chi_sim/chi_sim.traineddata \
—eval_listfile ~/tesstutorial/train/chi_sim.training_files.txt

实际上上面的评估过程可以省略,只是用来查看当前的识别精度而已,这点在官方文档根本没有说明,莫名地就在教程中使用该工具,让人以为它和训练有关。

3、开始训练:

  1. OMP_THREAD_LIMIT=8 lstmtraining --model_output ~/tesstutorial/output/simhei \
  2. --continue_from ~/tesstutorial/chi_sim.lstm \
  3. --traineddata ~/tesstutorial/tesseract/tessdata/chi_sim.traineddata \
  4. --train_listfile ~/tesstutorial/train/chi_sim.training_files.txt \
  5. --max_iterations 10000

注意continue_from参数,该参数指定了从前面提取出来的神经网络,也就是在现有的训练字库基础上进行训练,不仅仅可以是.lstm文件,也可以是chexbox文件,chexbox是训练生成的文件,比如上面的命令,训练输出文件夹~/tesstutorial/output/simhei就会生成chexbox文件。
如果训练指定次数后结果还不满意,可以继续训练,这时可以重复执行上面命令,如果chi_sim.lstm不小心删除了,可以指定--continue_from改成~/tesstutorial/output/simhei中的checkbox文件,需要注意的是,-max_iterations需要比上一次大,因为它是接着之前的训练结果开始训练的。

4、合并训练结果:

  1. lstmtraining --stop_training \
  2. --continue_from ~/tesstutorial/output/simhei_checkpoint \
  3. --traineddata ~/tesstutorial/tesseract/tessdata/chi_sim.traineddata \
  4. --model_output ~/tesstutorial/output/chi_sim_simhei.traineddata

最终生成我们训练好的chi_sim_simhei.traineddata文件,如果想像官方那样生成fast版本,可用如下命令将chi_sim_simhei.traineddata转成fast版本:

combine_tessdata -c chi_sim_simhei.traineddata

总结

填坑:
训练时大量打印类似image too large错误,这是因为生成训练数据时,tif 图片宽度过宽导致的,解决办法:
修改tesseract/src/training/tesstrain_utils.sh文件中的X_SIZE=3600X_SIZE=2550

训练完后用来识别中文时,文字之间多了空格,解决办法,直接在识别时加上自定义配置文件,比如新建my_config文件,内容:preserve_interword_spaces 1,调用识别命令:

tesseract -l chi_sim+eng test.jpg stdout my_config

前者我没试,请自行尝试。
最终测试新字体效果非常不错,官方训练库识别率很差,经过自己微调添加新字体训练后识别率大大提升。

标签: tesseract train

精彩评论
  1. 作者你好,我正在按照你的步骤来训练自己的字体模型,我现在有一个疑问,是不是当目标图片中有多少字体,那么训练更多的字体模型就更加准确?

    1. 是的,微调训练使用的都是官方提供的样本汉字生成的图片,实际上发现很多常用的文字没有包含,可以采用官方提供的教程进行新增字符训练(不过我在微调训练的基础上测试不是很顺利,存在一些问题没有成功)

  2. kim kim

    老哥,利害!還有在研究嗎?
    我看其它教程fine tune是要指定字符集的( chi_sim.unicharset ), 這個字符集到有甚麼用途,為何這邊訓練新字形不用?

    1. 如果我没记错的话,如果你下载官方(https://github.com/tesseract-ocr/langdata_lstm)的语言包,里面每种语言都有默认包含.unicharset文件的,这些文件实际上是汉字在图片中的位置信息,训练新字体也是需要的,在上面文章中生成待训练数据时会生成,只不过它是全自动的(过程就是读取语言包中对应语言的样本汉字,然后汉字生成图片,汉字在图片中的位置信息就保存在.unicharset文件,实际上就和其他网上文章手动操作一样,只不过脚本帮我们做了),最后在进行训练的时候会用到这个文件的。

  3. Lulu Lulu

    checkbox还是checkpoint文件... 同感官方教程演示例子的时候加了很多别的东西进去, 知乎那篇什么超详细也是在各个case之间跳跃还不加序号...

  4. nano nano

    我训练时出现“!int_mode_:Error:Assert failed:in file weightmatrix.cpp, line 244 !int_mode_:Error:Assert failed:in file weightmatrix.cpp, line 244 段错误 (核心已转储)”错误,请问是什么问题?

  5. asna asna

    博主能否放一些训练生成的字形看看。

    1. 很久没搞了,东西都删掉了。生成的字形没什么好看的,什么字体训练生成的时候就是什么字形。

发表评论:

icon_mrgreen.gificon_neutral.gificon_twisted.gificon_arrow.gificon_eek.gificon_smile.gificon_confused.gificon_cool.gificon_evil.gificon_biggrin.gificon_idea.gificon_redface.gificon_razz.gificon_rolleyes.gificon_wink.gificon_cry.gificon_surprised.gificon_lol.gificon_mad.gificon_sad.gificon_exclaim.gificon_question.gif