Tesseract5.4.0自定义LSTM训练
准备jTessBoxEditor,然后配置环境变量。
1、将图片转换成tif格式的,这里需要用画图工具另存为;
2、生成box文件
执行命令:
tesseract agv.normal.exp1.tif agv.normal.exp1 -l eng --psm 6 batch.nochop makebox
关于box文件的生成,对于Tesseract3可以使用makebox,但是对于Tesseract的lstm训练,需要使用lstmbox。否则再后面会报如下的错误。
生成lstmbox的命令如下:
D:\agvtest2>tesseract agv.normal.exp1.tif agv.normal.exp1 -l eng lstmbox
关于PSM的说明
0 = 仅方向和脚本检测 (OSD)。
1 = 自动页面分割,带 OSD。
2 = 自动页面分割,但无 OSD 或 OCR。(未执行)
3 = 完全自动页面分割,但无 OSD。(默认值)
4 = 假设一列文字大小可变。
5 = 假定垂直对齐的单个统一文本块。
6 = 假定单个统一的文本块。
7 = 将图像视为单一文本行。
8 = 将图像视为单个单词。
9 = 将图像视为圆圈中的单个单词。
10 = 将图像视为单个字符。
11 = 文本稀疏。不按特定顺序查找尽可能多的文本。
12 = 带 OSD 的稀疏文本。
13 = 原始行。将图像视为单行文本、
3、校正box文件中的信息
使用jTessBoxEditor打开tif文件。执行train.bat,打开jTexxBoxEditor.jar
校正完成后,一定要点保存。如下
关于box文件的内容,这里需要注意。它与tesseract3生成的box格式有所区别。
下面是tesseract5中识别的内容。
文档中说明了一行内容之后,必须标注一个结束行。
4、下载训练文件
从github仓下载traineddata_best类型的traineddata文件,可以选择eng.traineddata,用来初次训练字体;下载地址:https://github.com/tesseract-ocr/tessdata_best,下载后保存在当前工作目录下,另外拷贝一份到系统变量“TESSDATA_PREFIX”路径下,也即tesseract安装路径的tessdata\\文件夹下,这里一定要下载tessdata_best目录下面的,不能是tesssdata下面的,否则后面会报:
eng.lstm is an integer (fast) model, cannot continue training
这样的错误。
同时,将eng.traineddata文件复制一份到图片目录下,如下所示。
5、生成生成基于通用模型的lstm文件
D:\agvtest2>combine_tessdata -e eng.traineddata eng.lstm
可以看到目录下多了一个eng.lstm文件
6、生成lstmf文件
如果前面使用的是makebox生成的lstmf文件,需要将lstmf文件删除,重新执行一下生成listbox的命令。生成lstmf文件的执行命令:
tesseract agv.normal.exp1.tif agv.normal.exp1 --psm 6 lstm.train
可以看到目录下多了一个lstmf文件
7、设置.lstm文件路径
新建一个eng.trainingfile.txt文件,在文件中填写lstmf文件的完整路径。
8、开始训练
新建output目录,执行命令:
D:\agvtest2>lstmtraining --model_output=output\agv.traineddata --continue_from="D:\agvtest2\eng.lstm" --train_listfile="D:\agvtest2\eng.trainingfile.txt" --traineddata="D:\agvtest2\eng.traineddata" --debug_interval -1 --max_iterations 5000 --target_error_rate 0.01
注意路径冒号不要有空格
–modeloutput 模型训练输出的文件目录
–continue_from 训练从哪里继续,这里指定从上面提取的 eng.lstm文件,
–train_listfile 指定上一步创建的文件的路径
–traineddata 指定.traineddata文件的路径
–debug_interval 当值为-1时,训练结束,会显示训练的一些结果参数
–max_iterations 指明训练遍历次数
–target_error_rate 0.01 期望错误率
此时命令窗口中会有滚动的训练历程,这一步操作比较耗费时间。
如果在第8步的时候报了“Compute CTC targets failed for D:\agvtest2\agv.normal.exp1.lstmf!”,需要检查一下box文件内容的格式,是否是采用listbox生成的,如果不是,重新生成一次,并重新校正内容,在重新生成lstmf文件。
命令执行成功后,看到如下的日志信息:
然后在output目录下生成了一些output_checkpoint文件,如下所示。
9、生成traineddata文件
执行命令:
D:\agvtest2>lstmtraining --stop_training --model_output=output\agv.traineddata --continue_from="D:\agvtest2\eng.lstm" --traineddata=eng.traineddata
–stop_training 停止训练
–traineddata=eng.traineddata 训练使用的字体,当前工作目录下
–continue_from="D:\agvtest2\eng.lstm" 中间文件名称
--model_output=output\agv.traineddata 生成字体文件的traineddata文件名称
可以看到,在output目录下生成了agv.traineddata文件。
10、测试训练的模型
将agv.traineddata文件拷贝到tesseract的tessdata目录下:
执行命令:
D:\agvtest2>tesseract 2.jpg result -l agv
如下所示:
输出了识别结果到result.txt文件中,但识别结果不准。
11、提升准确率
从前面的训练步骤可以看到,开始训练时需要用到一个已经存在的字体eng.traineddata,比如第5步抽取它的lstm文件、第9步的训练等。既然这个原始字体训练出来的新字体识别的准确率不高,很可能跟选择的这个初始字体有关,那是不是可以用我们训练好的新字体替代eng.traineddata再训练一次呢,这样产生的第2代的新字体是不是可以有更好地表现?如此迭代多次之后,得到第3代、第4代、第5代字体呢? 将eng.traineddata相关的内容替换为agv.traineddata,新生成的第2代字体取名为agv2,依次替代命令行里面的参数训练第2代字体,类似的方法再训练出第3、第4、第5代字体,将每一代字体都用测试集进行测试。
常见问题解决:
1、Deserialize header failed: D:\agvtest2\agv.normal.exp1.lstmf
这是因为在eng.trainingfile.txt文件中,lstmf文件路径的换行符问题,如下所示。
将其中的CR去掉,只保留LF。
最简单的解决办法是去掉2个换行符\r\n(CR LF)。 当使用多个lstmf文件训练时,每个文件名之间必须要保留一个换行符,则必须去掉\r(CR)符号,只保留\n(LF)。去掉的方式如下所示。