tesseract-ocr 如何训练新语言 && 字符识别---样本训练
2016-11-14 16:14
585 查看
reference: http://tesseract-ocr.github.io/index.html
作者: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 aspammer@website.com 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你的训练图片:
比如:
接下来是最困难的部分。你需要编辑文件 [lang].[fontname].exp[num].box,并为每个字符放至utf8编码在文件是每行起始处。例如:发行版包含了一个图像:eurotext.tif.
运行以上的命令来生成一个文本文件,可 以包含下面的行:
因为Tesseract 以英文模式运行,它不能正确识别元音(umlaut)。这种字符需要使用一个合适的编辑器来纠正。可以使用能识别utf8的编辑器。HTML
编辑器是个不错的选择。。。。
理论上,boxfile中的每行都表示了你训练文件中的每个字符,如果你需要水平分隔字符,比如双逗号 ,, 它将具有两个box需要合并。
示例:lines 116-129:
你将看到, 最下面的双引号字符被表达成两个单一的逗号。bounding box必须按以下方式合成:
第一个数(左)采用两行中最小的(197)
第二个数(下)采用两行中最小的(496)
第三个数(右)采用两行中最大的(214)
第四个数(上)采用两行中最大的(508)
于是,给出:
如果你不能成功地在训练图像中将字符分隔开,其中一些会被圈进另一个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文件:
这将使得第二个box文件更容易生成,一种较好的选择是,tesseract将识别出大多数正确文本。你可以总是重复这个过程,来添加更多的字体到训练集中(比如:命令行工具 mfTraining 和 cnTraining)来制作它们,但是注意,还没有增量模式来允许你添加新的训练数据到存在的字符集中。这意味着每次你运行mfTraining和cnTraing工具,你可以从tr文件中制作新的数据文件,这些工具不会将采用已经存在的intproto/pffmtable/normproto并将它们直接添加进去。
4.3.4 全新提供Tif/Box pair!!
Tif/Box 对在新的下载页提供。(注意:tiff文件采用G4压缩以便节省空间,因此,你必须首先具有libtiff或者未压缩的数据)。你可以遵从以下过程,来为你的语言生成更好的训练数据或添加不同的字符形状到已经存在的语言中:
过滤box文件,只保持你想要的字符。
运行tesseract来训练。
对于每种字体,从多个语言中cat出.tr文件,来获取你想要的字符休,并从你有的字体或字符中添加.tr文件
以相同的方式cat出已经过滤的box文件到.tr文件中,以便在unicharset_extractor中处理
运行训练过程的其它步骤
注意!这听起来并不简单!cntraining和mftraining只能最多采用32个.tr文件,因此,对于相同的字体,你必须从多种语言中,以字体独立的方式,将所有的文件cat到一起来让32种语言结合在一起。cntraining/mftraining以及unicharset_extractor命令行工具必须各自由给定的.tr和.box文件,以相同的顺序,为不同的字体进行不同的过滤。可以提供一个程序来完成以上的事情,并在字符集表中挑出相同字符集。这样会将事情更简单些。
4.3.5 运行 tesseract进行训练
对于你的训练图像,box文件对,以训练模式运行tesseract:
或者
在版本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文件的内容。里面的字体名不必设置。出于好奇,以下是该格式的信息:
5 计算字符集
tesseract需要知道可能要输出的字符集。为了生成unicharset数据文件,在相同的页bounding box文件上使用unicharset_extractor程序进行聚类:
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)
日文或中文字母字符属性由二进制数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> and <fraktur> 是所有简单的0 或 1标记,表示字体具有命名属性。
当运行mftraining时,每个.tr文件名必须有相关entry在font_properties文件中,否则将中止mftraining。。。。。
例如:
font_properties文件如下:
5.2 聚合
当所有训练页的字符特征被抽取出来时,我们需要将它们聚集起来创建prototype文件。这些字符形状特性可以通过使用shapeclustering(在3.02版本之后提供)、mftraining 和 cntraining 程序进行聚焦。
shapeclustering通过形状聚集创建了主形状表,并将它写到一个文件中:shapetable.
-U 文件表示unicharset,由上面的unicharset_extractor 生成, lang.unicharset是输出unicharset,它将由combine_tessdata给出。Mftraining将输出两个其它的数据文件:inttemp(形状原型)和pffmtable(每个字符所希望的特征)。
它将输出normproto 数据文件(character
normalization sensitivity prototypes)
6.字典数据(可选)
tesseract为每种语言使用三个字典文件。两种文件被编码成有向非循环字图.DAWG
( Directed Acyclic Word Graph).其它是普通utf8文本文件:
为了生成DAWG字典文件,你首先需要为你的语言提供一个wordlist。你需要找到一个合适的字典文件,用来作为一个spellcheckers 的wordlist的基础
(ispell aspell hunspell)== 注意lincense. wordlist格式化成一个utf8的文本文件,每行都有一个词。将wordlist分割成需要的集合: 比如:常用词,其它剩下的词,接着使用worldlist2dawg来生成DAWG文件:
对于从右向左的语言(RTL)使用选项 "-r 1". 其它选项参照:wordlist2dawg
Manual Page。
注意:wordlist必须包含至少一个单词!在合并的traineddata文件中不允许存在。
如果单词总是具有标点在其中,比如:google.com , 那么在字典中包含它们很合适。
最后的字典文件称为:user-words,通常为空。
如果你需要字典wordlists的样本文件,解合并(使用combine_tessdata)已经存在的语言数据文件(比如:eng.traineddata),接着使用dawg2wordlist抽取wordlists.
7、最后的文件(unicharambigs)
tesseract最后使用的数据文件称为:unicharambigs。它表示了在字符或字符集间固有的模糊,这通常整个都是以人工方式生成。为了理解文件格式,查看以下示例:
第一行是一个版本标识符。剩下的行包含了5个以tab分隔的字段。第一个字段表示的是第二个字段的字符串数。第三个字段表示的是第四个字段的字符串数。第5个字段是一个类型标识符。第二和第四个字段表示了空格分隔的字符串。这可以是一个utf8格式的文件,因此,每个字符串是一个utf8字符串。每个这样的字符串必须匹配unicharset文件中一些行的第一个字段,比如,它必须是一个可识别单元。
类型表示符的值如下:
替代规则是,
如果第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 ),接着以如下方式运行:
注意,不要忘记加句点。
接着将生成lang.traineddata。tesseract可以识别文本:
实际上,你可以使用语言码中的任何字符串,但是,如果你想任何人能轻易理解,按ISO 639的方式命名。
关于combine_tessdata更多选项,在Manual
Page 或者源码注释中(source
code)。
翻译至: https://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract2 https://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3
原文地址:http://wangjunle23.blog.163.com/blog/static/117838171201323031458171/
Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护,目前发布在Googel Project上。地址为http://code.google.com/p/tesseract-ocr/。
从http://code.google.com/p/tesseract-ocr/downloads/list下载Tesseract,目前版本为Tesseract3.02。因为只是测试使用,这里直接下载winodws下的安装文件tesseract-ocr-setup-3.02.02.exe。安装成功后会在相应磁盘上生成一个Tesseract-OCR目录。通过目录下的tesseract.exe程序就可以对图像字符进行识别了。
2.准备一副待识别的图像,这里用画图工具随便写了一串数字,保存为number.jpg,如下图所示:
3. 打开命令行,定位到Tesseract-OCR目录,输入命令:
[plain] view
plaincopy
tesseract.exe number.jpg result -l eng
其中result表示输出结果文件txt名称,eng表示用以识别的语言文件为英文。
3. 打开Tesseract-OCR目录下的result.txt文件,看到识别的结果为7542315857,有3个字符识别错误,识别率还不是很高,那有没有什么方法来提供识别率呢?Tesseract提供了一套训练样本的方法,用以生成自己所需的识别语言库。下面介绍一下具体训练样本的方法。
1.下载工具jTessBoxEditor. http://sourceforge.net/projects/vietocr/files/jTessBoxEditor/,这个工具是用来训练样本用的,由于该工具是用Java开发的,需要安装JAVA虚拟机才能运行。
2. 获取样本图像。用画图工具绘制了5张0-9的文样本图像(当然样本越多越好),如下图所示:
3.合并样本图像。运行jTessBoxEditor工具,在点击菜单栏中Tools--->Merge TIFF。在弹出的对话框中选择样本图像(按Shift选择多张),合并成num.font.exp0.tif文件。
4.生成Box File文件。打开命令行,执行命令:
[plain] view
plaincopy
tesseract.exe num.font.exp0.tif num.font.exp0 batch.nochop makebox
生成的BOX文件为num.font.exp0.box,BOX文件为Tessercat识别出的文字和其坐标。
注:Make Box File 文件名有一定的格式,不能随便乱取名字,命令格式为:
[plain] view
plaincopy
tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox
其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。
【Yasi】:先前自己定义了tessdata的环境变量 TESSDATA_PREFIX 值为 E:\tesseract\tessdata,但没有从tesseract源文件目录中将tessdata子目录中的内容copy到 E:\tesseract\tessdata
中,造成上面的命令报错,说找不到batch.nochop 和 makebox。解决办法:将 tesseract 源文件目录中所有文件和子文件夹(可能充分但非必要,先不管这些啦)copy到 E:\tesseract\tessdata
中。
5.文字校正。运行jTessBoxEditor工具,打开num.font.exp0.tif文件(必须将上一步生成的.box和.tif样本文件放在同一目录),如下图所示。可以看出有些字符识别的不正确,可以通过该工具手动对每张图片中识别错误的字符进行校正。校正完成后保存即可。
【Yasi】这里必须修改识别错误的字符,否则做出来的traineddata文件也是错的。可以在下面的界面中修改并保存,也可以直接在traineddata文件中修改。
6.定义字体特征文件。Tesseract-OCR3.01以上的版本在训练之前需要创建一个名称为font_properties的字体特征文件。
font_properties不含有BOM头,文件内容格式如下:
[plain] view
plaincopy
<fontname> <italic> <bold> <fixed> <serif> <fraktur>
其中fontname为字体名称,必须与[lang].[fontname].exp[num].box中的名称保持一致。<italic> 、<bold> 、<fixed> 、<serif>、 <fraktur>的取值为1或0,表示字体是否具有这些属性。
这里在样本图片所在目录下创建一个名称为font_properties的文件,用记事本打开,输入以下下内容:
[plain] view
plaincopy
font 0 0 0 0 0
这里全取值为0,表示字体不是粗体、斜体等等。7.生成语言文件。在样本图片所在目录下创建一个批处理文件,输入如下内容。
[plain] view
plaincopy
rem 执行改批处理前先要目录下创建font_properties文件
echo Run Tesseract for Training..
tesseract.exe num.font.exp0.tif num.font.exp0 nobatch box.train
echo Compute the Character Set..
unicharset_extractor.exe num.font.exp0.box
mftraining -F font_properties -U unicharset -O num.unicharset num.font.exp0.tr
echo Clustering..
cntraining.exe num.font.exp0.tr
echo Rename Files..
rename normproto num.normproto
rename inttemp num.inttemp
rename pffmtable num.pffmtable
rename shapetable num.shapetable
echo Create Tessdata..
combine_tessdata.exe num.
将批处理通过命令行执行。执行后的结果如下:
需确认打印结果中的Offset 1、3、4、5、13这些项不是-1。这样,一个新的语言文件就生成了。
num.traineddata便是最终生成的语言文件,将生成的num.traineddata拷贝到Tesseract-OCR-->tessdata目录下。可以用它来进行字符识别了。
[plain] view
plaincopy
tesseract.exe number.jpg result -l eng
识别结果如如图所示,可以看到识别率提高了不少。通过自定义训练样本,可以进行图形验证码、车牌号码识别等。感兴趣的朋友可以研究研究。
将生成的num.traineddata拷贝到E:\tesseract\tessdata,即环境变量TESSDATA_PREFIX 设置的路径下,执行下面的命令(注意第二条命令结尾是num,即新加的traineddata,而不是eng)
[plain]
view plain
copy
E:\tesseract\tesseract-svn\vs2008\LIB_Debug\tesseractd.exe num-yasi.png result-eng -l eng
E:\tesseract\tesseract-svn\vs2008\LIB_Debug\tesseractd.exe num-yasi.png result-num -l num
下图是两次识别结果对比
使用eng traineddata的结果完全不靠谱;使用了自己的traineddata,识别出来的当然都是数字,但正确率实在糟糕。可能是我自己手写的字体和用来做traineddata的手写数字的字体差别太大了吧。
原文地址:http://blog.csdn.net/yasi_xi/article/details/8763385
作者: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 aspammer@website.com 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或者未压缩的数据)。你可以遵从以下过程,来为你的语言生成更好的训练数据或添加不同的字符形状到已经存在的语言中:
过滤box文件,只保持你想要的字符。
运行tesseract来训练。
对于每种字体,从多个语言中cat出.tr文件,来获取你想要的字符休,并从你有的字体或字符中添加.tr文件
以相同的方式cat出已经过滤的box文件到.tr文件中,以便在unicharset_extractor中处理
运行训练过程的其它步骤
注意!这听起来并不简单!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
normalization 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. |
(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)。
翻译至: https://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract2 https://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3
原文地址:http://wangjunle23.blog.163.com/blog/static/117838171201323031458171/
Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护,目前发布在Googel Project上。地址为http://code.google.com/p/tesseract-ocr/。
使用默认的语言库识别
1.安装Tesseract从http://code.google.com/p/tesseract-ocr/downloads/list下载Tesseract,目前版本为Tesseract3.02。因为只是测试使用,这里直接下载winodws下的安装文件tesseract-ocr-setup-3.02.02.exe。安装成功后会在相应磁盘上生成一个Tesseract-OCR目录。通过目录下的tesseract.exe程序就可以对图像字符进行识别了。
2.准备一副待识别的图像,这里用画图工具随便写了一串数字,保存为number.jpg,如下图所示:
3. 打开命令行,定位到Tesseract-OCR目录,输入命令:
[plain] view
plaincopy
tesseract.exe number.jpg result -l eng
其中result表示输出结果文件txt名称,eng表示用以识别的语言文件为英文。
3. 打开Tesseract-OCR目录下的result.txt文件,看到识别的结果为7542315857,有3个字符识别错误,识别率还不是很高,那有没有什么方法来提供识别率呢?Tesseract提供了一套训练样本的方法,用以生成自己所需的识别语言库。下面介绍一下具体训练样本的方法。
训练样本
关于如何训练样本,Tesseract-OCR官网有详细的介绍http://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3。这里通过一个简单的例子来介绍一下如何进行样本训练。1.下载工具jTessBoxEditor. http://sourceforge.net/projects/vietocr/files/jTessBoxEditor/,这个工具是用来训练样本用的,由于该工具是用Java开发的,需要安装JAVA虚拟机才能运行。
2. 获取样本图像。用画图工具绘制了5张0-9的文样本图像(当然样本越多越好),如下图所示:
3.合并样本图像。运行jTessBoxEditor工具,在点击菜单栏中Tools--->Merge TIFF。在弹出的对话框中选择样本图像(按Shift选择多张),合并成num.font.exp0.tif文件。
4.生成Box File文件。打开命令行,执行命令:
[plain] view
plaincopy
tesseract.exe num.font.exp0.tif num.font.exp0 batch.nochop makebox
生成的BOX文件为num.font.exp0.box,BOX文件为Tessercat识别出的文字和其坐标。
注:Make Box File 文件名有一定的格式,不能随便乱取名字,命令格式为:
[plain] view
plaincopy
tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox
其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。
【Yasi】:先前自己定义了tessdata的环境变量 TESSDATA_PREFIX 值为 E:\tesseract\tessdata,但没有从tesseract源文件目录中将tessdata子目录中的内容copy到 E:\tesseract\tessdata
中,造成上面的命令报错,说找不到batch.nochop 和 makebox。解决办法:将 tesseract 源文件目录中所有文件和子文件夹(可能充分但非必要,先不管这些啦)copy到 E:\tesseract\tessdata
中。
5.文字校正。运行jTessBoxEditor工具,打开num.font.exp0.tif文件(必须将上一步生成的.box和.tif样本文件放在同一目录),如下图所示。可以看出有些字符识别的不正确,可以通过该工具手动对每张图片中识别错误的字符进行校正。校正完成后保存即可。
【Yasi】这里必须修改识别错误的字符,否则做出来的traineddata文件也是错的。可以在下面的界面中修改并保存,也可以直接在traineddata文件中修改。
6.定义字体特征文件。Tesseract-OCR3.01以上的版本在训练之前需要创建一个名称为font_properties的字体特征文件。
font_properties不含有BOM头,文件内容格式如下:
[plain] view
plaincopy
<fontname> <italic> <bold> <fixed> <serif> <fraktur>
其中fontname为字体名称,必须与[lang].[fontname].exp[num].box中的名称保持一致。<italic> 、<bold> 、<fixed> 、<serif>、 <fraktur>的取值为1或0,表示字体是否具有这些属性。
这里在样本图片所在目录下创建一个名称为font_properties的文件,用记事本打开,输入以下下内容:
[plain] view
plaincopy
font 0 0 0 0 0
这里全取值为0,表示字体不是粗体、斜体等等。7.生成语言文件。在样本图片所在目录下创建一个批处理文件,输入如下内容。
[plain] view
plaincopy
rem 执行改批处理前先要目录下创建font_properties文件
echo Run Tesseract for Training..
tesseract.exe num.font.exp0.tif num.font.exp0 nobatch box.train
echo Compute the Character Set..
unicharset_extractor.exe num.font.exp0.box
mftraining -F font_properties -U unicharset -O num.unicharset num.font.exp0.tr
echo Clustering..
cntraining.exe num.font.exp0.tr
echo Rename Files..
rename normproto num.normproto
rename inttemp num.inttemp
rename pffmtable num.pffmtable
rename shapetable num.shapetable
echo Create Tessdata..
combine_tessdata.exe num.
将批处理通过命令行执行。执行后的结果如下:
需确认打印结果中的Offset 1、3、4、5、13这些项不是-1。这样,一个新的语言文件就生成了。
num.traineddata便是最终生成的语言文件,将生成的num.traineddata拷贝到Tesseract-OCR-->tessdata目录下。可以用它来进行字符识别了。
使用训练后的语言库识别
用训练后的语言库识别number.jpg文件, 打开命令行,定位到Tesseract-OCR目录,输入命令:[plain] view
plaincopy
tesseract.exe number.jpg result -l eng
识别结果如如图所示,可以看到识别率提高了不少。通过自定义训练样本,可以进行图形验证码、车牌号码识别等。感兴趣的朋友可以研究研究。
【Yasi】试验结果如下:
下面是num-yasi.png将生成的num.traineddata拷贝到E:\tesseract\tessdata,即环境变量TESSDATA_PREFIX 设置的路径下,执行下面的命令(注意第二条命令结尾是num,即新加的traineddata,而不是eng)
[plain]
view plain
copy
E:\tesseract\tesseract-svn\vs2008\LIB_Debug\tesseractd.exe num-yasi.png result-eng -l eng
E:\tesseract\tesseract-svn\vs2008\LIB_Debug\tesseractd.exe num-yasi.png result-num -l num
下图是两次识别结果对比
使用eng traineddata的结果完全不靠谱;使用了自己的traineddata,识别出来的当然都是数字,但正确率实在糟糕。可能是我自己手写的字体和用来做traineddata的手写数字的字体差别太大了吧。
原文地址:http://blog.csdn.net/yasi_xi/article/details/8763385
相关文章推荐
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练 图片识别训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别-样本训练
- 转 Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练 [转]
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别---样本训练
- Tesseract-OCR 字符识别——样本训练 [转]