tesseract-ocr 第一课
前言
据网上介绍tesseract-ocr性能不错,并且可以支持识别中文了。于是尝试一下.
安装
1.下载地址:
https://code.google.com/p/tesseract-ocr/downloads/list
1.介绍
论文地址:http://tesseract-ocr.googlecode.com/svn/trunk/doc/tesseracticdar2007.pdf
Tesseract OCR引擎是HP研究所生产的。包括 线性查找(Line finding)、特征/分类方法,自适应分类器。
Tesseract 是一个开源OCR引擎,在1984-1994年间,由HP开发。2005年,HP将Tesseract 开源。
2.架构
由于HP独立开发了页码布局分析技术,并用于产品中(因此没开源)。Tesseract 并不需要自己的页码布局分析技术。因此,Tesseract 假设,它的输入是一幅二进制图片,带有可选的多边型文本区域定义。
处理流程遵循传统的 多阶管道,但一些阶段并不常用。第一阶段,是一个组件(component)分析,保存各组件(component)轮廓。此时的计算开销很大,但有一个显著优点:通过检测嵌套轮廓,子轮廓,孙子轮廓,很容易检测反转的文本,将它识别成黑白色文本。Tesseract 可能是第一个能够如此轻微处理黑白文本的OCR引擎。这一阶段,轮廓通过嵌套,被聚集在一起形成块(blob).
块被识别成文本线,这些线和区域被固定的基准或者可能的文本用来分析识别。根据字符空格,文本线被分隔成不同的词。特定基准的文本立即被字符元标定出。通过使用有限的空格或者失真的空格,相应的文本被断成词。
识别过程处理需要两个阶段。首先,尝试轮流识别每个词。每个结果比较满意的词被传给一个自适应分类器作为训练数据。自适应分类器接着有机会精确识别文本。
自适应分类器接着学习一些有用的,并在页顶端作点贡献。接着在页上运行第二步,识别那些并被很好识别的文本。
最后阶段是解析失真的空格,或者为x高的确认可选的假设,来定位小文本(small cap text)。
3.线与词查询
3.1 线查询
线查询算法是tesseract的一小部分,很早就已经发表论文。线查询算法被设计成用来识别de-skew,来保全图片质量的失真。该过程最关键的部分是:块过滤和线构造。
一、tess-two简介
tess-two是托管在GIT上的tesseract-adroid-tools的一个分支,并添加了许多额外功能。tesseract android 工具包含了一整套android api和tesseract OCR和Leptonica图像处理库相关的build文件。
该项目使用tesseract v3.02.02. 依赖tesseract v3.02.02和Leptonica1.69 的源码,它们已经包含在tess-two/jni目录下。
tess-two子目录包含了相关工具来编译tesseract 和Leptonica库。它包含了一个eclipse android库项目,并提供了一个java api来访问native-compiled tesseract和Leptonica api.
二、需要
android 2.2 或更高版本。
相关语言的训练数据。data文件必须被抽放到一个tessdata的子目录中。
三、eyes-two
eyes-two子目录包含了一个二级、分隔库项目,带有额外的图像处理代码,来自eyes-free项目,无任何修改。它包含了相关用于文本检测,模糊检测,光流检测,及门限化。构建eys-two不需要使用tesseract api.
四、编译
tess-two的构建:
git clone git://github.com/rmtheis/tess-two tess
cd tess
cd tess-two
ndk-build
android update project --path .
ant release
eys-two的构建:
cd ..
cd eyes-two
ndk-build
android update project --path .
ant release
继续我们的第三课,这一节主要想介绍一些关于windows下的tesseract的东西,做为一个基础性的介绍(其实我更喜欢在 linux下,下来的包是windows的)
一、目录结构
APIExample: 一个api示例
doc: 文档
java: java api
tessdata: 各种语言的识别训练数据
tesseract-ocr: 项目目录
ambiguous_words.exe: 生成单词四方体的词集,以便更容易找出模糊
claasifier_tester.exe:
cntraining.exe: 字符归一化训练
combine_tessdata.exe: 结合/抽取/重写 tesseract data
dawg2wordlist.exe: 将一个tesseract DAWG转化成wordlist
gzip.exe:
mftraining.exe: 特征训练
shapeclustering.exe:形状聚类训练
unicharset_extractor.exe: 从tesseract的boxfile中抽取unichaset
wordlist2dawg.exe:将一个wordlist转化为一个DAWG
介绍
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 [email protected]#$%^&(),.{}<>/?”,这个就很糟糕。而这个则更好:“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 0p 753 486 776 518 0r 779 494 796 518 0i 799 494 810 527 0n 814 494 837 518 0g 839 485 862 518 0t 865 492 878 521 0u 101 453 122 484 0b 126 453 146 486 0e 149 452 168 477 0r 172 453 187 476 0d 211 451 232 484 0e 236 451 255 475 0n 259 452 281 475 0
因为Tesseract 以英文模式运行,它不能正确识别元音(umlaut)。这种字符需要使用一个合适的编辑器来纠正。可以使用能识别utf8的编辑器。HTML 编辑器是个不错的选择。。。。
理论上,boxfile中的每行都表示了你训练文件中的每个字符,如果你需要水平分隔字符,比如双逗号 ,, 它将具有两个box需要合并。
示例:lines 116-129:
D 101 504 131 535 0e 135 502 154 528 0r 158 503 173 526 0, 197 498 206 510 0, 206 497 214 509 0s 220 501 236 526 0c 239 501 258 525 0h 262 502 284 534 0n 288 501 310 525 0e 313 500 332 524 0l 336 501 347 534 0l 352 500 363 532 0e 367 499 386 524 0” 389 520 407 532 0
你将看到, 最下面的双引号字符被表达成两个单一的逗号。bounding box必须按以下方式合成:
- 第一个数(左)采用两行中最小的(197)
- 第二个数(下)采用两行中最小的(496)
- 第三个数(右)采用两行中最大的(214)
- 第四个数(上)采用两行中最大的(508)
于是,给出:
D 101 504 131 535 0e 135 502 154 528 0r 158 503 173 526 0? 197 497 214 510 0s 220 501 236 526 0c 239 501 258 525 0h 262 502 284 534 0n 288 501 310 525 0e 313 500 332 524 0l 336 501 347 534 0l 352 500 363 532 0e 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 inthe .tr file (in order) like thisUnknownFont <utf8 code(s)> 2mf <number of features>x y length dir 0 0... (there are a set of these determined by <number of features>above)cn 1ypos length x2ndmoment y2ndmoment The mf features are polygon segments of the outline normalized to the1st 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 todistinguish 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 46b 3 Latin 59W 5 Latin 407 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.trmftraining -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. |
为了生成DAWG字典文件,你首先需要为你的语言提供一个wordlist。你需要找到一个合适的字典文件,用来作为一个spellcheckers 的wordlist的基础 (ispell aspell hunspell)== 注意lincense. wordlist格式化成一个utf8的文本文件,每行都有一个词。将wordlist分割成需要的集合: 比如:常用词,其它剩下的词,接着使用worldlist2dawg来生成DAWG文件:
wordlist2dawg frequent_words_list lang.freq-dawg lang.unicharsetwordlist2dawg 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。它表示了在字符或字符集间固有的模糊,这通常整个都是以人工方式生成。为了理解文件格式,查看以下示例:
v13 I I 0 2 u o 33 I - I 1 H 22 ‘ ‘ 1 " 12 ?? 6 1 ?? 11 m 2 r n 03 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
具体的参考链接为:
- ambiguous_words
- cntraining
- combine_tessdata
- dawg2wordlist
- mftraining
- shapeclustering
- tesseract
- unicharset_extractor
- wordlist2dawg
概念介绍:
DAWG:
wordlist: