c语言编写ocr软件,开源OCR引擎Tesseract

发布时间:2025-12-09 20:33:06 浏览次数:4

简介

Tesseract是开源的OCR引擎。Tesseract最初设计用于英文识别,经过改进引擎和训练系统,它能够处理其它语言和UTF-8字符。Tesseract 3.0能够处理任何Unicode字符,但并非在所有语言上都工作得很好。Tesseract在庞大字符集语言(比如中文)上较慢,但是工作良好。

Tesseract需要知道相同字符的不同形状,也就是不同字体。最多允许的字体数量在intproto.h中通过MAX_NUM_CONFIGS定义,目前支持64种。当训练字体数量超过32种时,速度显著下降。

使用入门

直接输入无参数命令tesseract可查看其用法:

tesseract

基本使用方法[终端命令]:

tesseract images/9531.jpeg stdout -l eng -psm 7 digits

images/9531.jpeg:输入待OCR的图片;

stdout:输出结果到终端,也可用文件名,表示输出到文件;

-l eng:使用英文识别库;

-psm 7:表示分页方式,7表示将图片视为单行文字;

digits:识别配置文件,这里表示只识别数字。

上图的验证码9531,通过以上命令可正确识别。查看目前支持那些语言:

tesseract --list-langs # chi_sim chi_tra eng osd

语言支持文件位于安装目录的tessdata文件夹中,其中的eng.traineddata文件表示支持英文的识别库。更多语言支持可在github下载。

识别配置文件位于安装目录的tessdata/configs文件夹中,其中的digits文件配置为只识别数字,相当于识别的白名单,内容为

tessedit_char_whitelist 0123456789-.

识别库对字体的识别能力影响很大,比如点阵字体:

识别的参数如下:

tesseract images/bitmap_test.tif stdout -l chi_sim -psm 7

采用google code上老的中文识别库,结果就不太好:

项目名称 = 北京丰台 区花乡四台庄(中失村料技园丰台园东区三期)15 16一2 正地挪

换用github上的3.04版本中文识别库,结果有很大提升:

项目名称 : 北京丰台 区花乡四合庄〔中夫村科技园丰台园东区三期〕1… 16一2 1地块C

通过自己训练识别库,也可得更好的识别结果:

项目名称 : 北京丰台 区花乡四合庄(中关村科技园丰台园京区2期)15 16-2 1地块C

训练识别库

为了训练一种新语言当识别库,需要在tessdata子文件夹中创建一些数据文件,然后用combine_tessdata将它们合并为一个文件。命名约定(naming convention)是languagecode.file_name,其中languagecode按ISO 638-3标准,当然也可使用任何字符串。用于英文识别库(3.00)的文件包括:

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可知目前可接受的文件名。

输入文件(lang.config、lang.unicharambigs、font_properties、box文件、字典的wordlists……)需要满足如下标准:

不含BOM的ASCII或UTF-8编码;

Unix风格的行结束符(‘\n’);

最后一个字符必须是行结束符(没有会报错last_char == '\n':Error:Assert failed...)。

训练识别库至少需要unicharset、inttemp、normproto和pfftable这几个文件。如果只识别有限的字体(例如一种字体),那么单个训练页可能就够了。

训练步骤如下:

命令/工具

输入文件类型

输出文件类型

备注

text2image

ttf

box、tif

可选步骤

tesseract

tif

box

tesseract

tif、box

tr

unicharset_extractor

box

unicharset

set_unicharset_properties

unicharset

unicharset

可选步骤

font_properties

手动步骤

shapeclustering

font_properties、unicharset、tr

shapetable

可选步骤

mftraining

font_properties、unicharset、tr

unicharset、shapetable、inttemp、pffmtable

cntraining

tr

normproto

words_list

手动步骤

wordlist2dawg

words_list

DAWG

可选步骤

unicharambigs

手动步骤

combine_tessdata

*

traineddata

训练流程中有些是手动的(得到font_properties、words_list、unicharambigs文件),用到的相关工具位于training子目录。

生成训练图片

创建训练文件需注意的重要事项:

确保每个字符的最少样本数,10个较理想,但对稀有字符5个也可。

更频繁的字符应该有更多的样本,最少20个。

不要错误地将所有非字符组织在一起。例如:“The quick brown fox jumps over the lazy dog. 0123456789 !@#%^&(),.{}<>/?”就很糟糕,更好的组织是“The (quick) brown {fox} jumps! over the 3,456.78 #90 dog & duck/goose, as 12.5% of E-mail from aspammer@website.com is spam?”。

获得训练图片的方法主要有两类:

通过字体文件自动生成训练图片,通常可以同时得到box文件;

直接收集图片,或者利用先打印后扫描的方式。

自动新方法(3.03版新功能)

该方法通过字体文件,自动获得训练所需的tif/box文件对。

准备一个utf-8文件(training_text.txt),包含符合上述准则的训练文本。获得期望识别字体的truetype/opentype字体文件,利用text2image

text2image --text=training_text.txt --outputbase=chi_jyq.fangsong_gb2312.exp0 --font='FangSong_GB2312' --fonts_dir=./Fonts

这样就可以得到chi_jyq.fangsong_gb2312.exp0.tif和chi_jyq.fangsong_gb2312.exp0.box两个文件。本例采用的training_text.txt文件内容为:

项目名称:北京丰台区花乡四合庄(中关村科技园丰台园东区三期)1516-21地块C

得到的tif图如下:

得到的box文件前部分片段:

项 57 4617 100 4664 0

目 115 4619 144 4662 0

名 156 4619 194 4667 0

称 206 4621 251 4670 0

: 259 4625 267 4651 0

北 306 4624 351 4671 0

京 358 4623 400 4673 0

丰 409 4624 450 4674 0

台 461 4625 497 4673 0

区 512 4628 550 4673 0

花 556 4627 601 4677 0

乡 612 4628 645 4676 0

辅助软件

text2image自动生成tif/box文件对的局限性在于:

只支持truetype/opentype这样的矢量字体,对于bitmap点阵字体无能为力;

这是3.03版本才具有的新功能,而且目前在OSX系统无法正常使用。

因此,需要其它的自动化方案。借助可视化软件jTessBoxEditor,可以不受上述约束,利用其“TIFF/Box Generator”模块,自动生成tif/box文件对。

手动老方法

该方法需要首先得到字符图像(比如通过打印扫描方式),获取字符图像需注意:

打印的时候,字符要分开。若间隔不够,生成tr文件时会导致错误“FAILURE! box overlaps no blobs or blobs in multiple rows”。

训练数据应按字体组织。理想情况下,单个字体的所有样本应组成一个tiff文件。因此,单个字体的全部训练数据可有很多页,这使得能够训练大字符集(large-character-set)语言。

不必对多种尺寸训练,10号字体即可(对小字例外:若想识别窄于15像素的字体,应另外训练或识别前放大图像)。

不要在同一图像文件中混杂多种字体(单个tr文件应当精确)。混搭会使聚类时特征劣化,导致识别错误。

可以使用多达64个(多页的)训练文件(图片),最好是混合字体斜体和粗体风格(在不同文件中)。64个图像文件是对字体数量的限制。每个字体应当放到单个的多页tiff文件,box文件中每个字符坐标后面的数字确定了页码。因此,对给定字体,能够创建任意大的训练数据,使得能够训练大字符集语言。另一种方法是对单个字体创建多个单页的tiff文件,然后必须对每个字体cat(Linux中的文件连接命令)合并多个tr文件为只含一个字体的单个tr文件

获取Box文件

如果只有字符图片数据,还需要为每张图创建一个box文件。它是一个文本文件,列出了训练图像中的字符,按顺序,一个字符一行,包含字符边界框的坐标。此步骤的关键是手动调整该文件,得到字符正确的坐标。

Tesseract根据tif图生成box文件:

tesseract chi_jyq.fangsong_gb2312.exp0.tif chi_jyq.fangsong_gb2312.exp0 -l chi_sim batch.nochop makebox

得到的box存在错误,如下所示:

需要修改box文件,通过可视化工具人工合并,可得到正确的字符框。

紧邻字符的处理方式:

当两个字符靠得很近时,可以通过重新制作训练图片使二者分开;

如果两个相邻字符经常一起出现,那么可以直接将两个字符视为一个对象(box文件第一列为两个字符),并且边界框包含这两个字符

当训练一个新字符集时,一个好的思路是首先在某一种字体上得到box文件,然后继续完成整个训练过程。制作其它字体box文件时,可借助已训练好的识别库,比如上例采用的-l chi_sim参数。这样得到后续的box文件更容易,而且很有可能大部分字符能正确识别。

但是,不存在增量训练方法。每次mfTraining和cnTraining的过程都要用tr文件从头再来,不能直接使用已有的intproto/pffmtable/normproto文件。

优化Tif/Box文件

通过抽取子集或增加不同的字符或形状提升训练数据:

从box文件中过滤掉不需要的字符。

执行tesseract训练(得到tr文件)。

对每种字体,cat(连接)不同语言的tr文件,并加入自定义字体和字符的tr文件。

按照cat(连接)tr文件的顺序和方式,cat(连接)box文件,交付unicharset_extractor使用。

执行之后的训练过程。cntraining和mftraining最多只能采用64个tr文件,必须将不同语言的tr文件按字体连接在一起(每个tr文件的字体要相同)。tr文件中的字符必须和box文件中的字符顺序一致,也就是box的连接顺序要和tr相同。输入cn/mftraining和unicharset_extractor命令的tr和box文件顺序必须一致。

Tesseract训练

对每个训练图像和box文件对,在训练模式运行Tesseract:

tesseract chi_jyq.fangsong_gb2312.exp0.tif chi_jyq.fangsong_gb2312.exp0 box.train.stderr

若上述命令最后一个参数为box.train,出错信息会写入tesseract.log文件而非stderr。该命令输出tr文件,它包含了每个字符的特征,也会输出只包含单个新行的txt文件。

上述命令可能会出错,得到如下输出:

FAIL!

APPLY_BOXES: boxfile line 22/园 ((1108,4637),(1150,4686)): FAILURE! Couldn't find a matching blob

FAIL!

APPLY_BOXES: boxfile line 25/园 ((1258,4641),(1300,4689)): FAILURE! Couldn't find a matching blob

APPLY_BOXES:

Boxes read from boxfile: 40

Boxes failed resegmentation: 2

Found 38 good blobs.

Generated training data for 4 words

Warning in pixReadMemTiff: tiff page 1 not found

意味着“园”字的块没找到,tr文件中就缺失了“园”字的特征。如果出现FATALITIES错误,必须先修正box文件修订错误才能继续。FATALITY通常意味着没有找到box文件中的任何字体。要么是坐标错误,要么是字符图像出了问题。如果字符没有可供使用的样本,它就不能被识别,那么得到的inttemp文件和unicharset文件就不匹配,Tesseract会退出。

如果tif/box文件对是通过jTessBoxEditor可视化工具得到的,那么生成文件时选定“Anti-Aliasing”可消除上述错误。

tr文件中特征含义如下:

Every character in the box file has a corresponding set of entries in

the .tr file (in order) like this

UnknownFont 2

mf

x y length dir 0 0

... (there are a set of these determined by

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 ')

计算字符集

Tesseract需要知道能够输出的字符。利用unicharset_extractor工具,可以从box文件得到unicharset文件:

unicharset_extractor chi_jyq.fangsong_gb2312.exp0.box chi_jyq.fangsong_gb2312.exp1.box

Tesseract需要知道字符的属性(property):isalpha、isdigit、isupper还是islower?这些信息必须编码到unicharset数据文件,文件的每行对应一个字符。

v2版的unicharset文件有4个空格分开的字段:

'character' 'properties' 'script' 'id'

形如:

; 10 Common 46

b 3 Latin 59

W 5 Latin 40

7 8 Common 66

= 0 Common 93

v3.03版的unicharset文件包含了更多的信息:

'character' 'properties' 'glyph_metrics' 'script' 'other_case' 'direction' 'mirror' 'normed_form'

形如:

110

NULL 0 NULL 0

N 5 59,68,216,255,87,236,0,27,104,227 Latin 11 0 1 N

Y 5 59,68,216,255,91,205,0,47,91,223 Latin 33 0 2 Y

1 8 59,69,203,255,45,128,0,66,74,173 Common 3 2 3 1

9 8 18,66,203,255,89,156,0,39,104,173 Common 4 2 4 9

a 3 58,65,186,198,85,164,0,26,97,185 Latin 56 0 5 a

set_unicharset_properties

3.03版本中的新工具可以得到字符集的额外属性:

set_unicharset_properties -U unicharset -O output_unicharset --script_dir=training/langdata

font_properties

3.01版新的要求是font_properties文件。该文件的作用是当字体被识别时,提供字体风格(style)信息。font_properties文件是文本文件,通过-F filename参数输入给命令mftraining。

font_properties文件的每行格式如下:

表示字体名,不允许有空格,其它几个取值为0或1,表示该字体是否具有这个属性。

当运行mftraining时,每个tr文件名必须匹配font_properties文件中的一条,否者mftraining会退出。tr文件命名应当是fontname.tr或[lang].[fontname].exp[num].tr。

一个font_properties文件示例:

fangsong_gb2312 0 0 0 0 0

聚类

当抽取了所有训练数据的字符特征后,需要通过聚类创建原型(prototype)。字符的形状特征可通过shapeclustering(3.02版的新功能)、mftraining和cntraining聚类得到。

shapeclustering -F font_properties -U unicharset chi_jyq.fangsong_gb2312.exp0.tr chi_jyq.fangsong_gb2312.exp1.tr

shapeclustering通过形状聚类创建主形状表,并将它写入shapetable文件。除了Indic语言,目前不要使用shapeclustering。

如果没有执行shapeclustering,mftraining会生成shapetable:

mftraining -F font_properties -U unicharset -O chi_jyq.unicharset chi_jyq.fangsong_gb2312.exp0.tr chi_jyq.fangsong_gb2312.exp1.tr

chi_jyq.unicharset是输出的unicharset,将会用于combine_tessdata。mftraining还会输出inttemp(形状原型)和pffmtable(每个字符的期望特征数)两个文件。该程序也会输出Microfeat,但是这里不会用到。

traineddata文件中必须包含shapetable。

cntraining将会得到normproto(规范化的敏感原型)文件:

cntraining chi_jyq.fangsong_gb2312.exp0.tr chi_jyq.fangsong_gb2312.exp1.tr

字典数据(可选项)

Tesseract对每种语言使用了多达8个字典文件。这些文件都是可选项,用于辅助确定不同可能字符组合的可能性。

其中7个文件为有向无环字图(DAWG,directed acyclic word graph)格式,另外一个是纯UTF-8文本。

为了得到DAWG字典文件,首先需要语言的单词列表(wordlist)。可以用合适的字典文件(比如来自拼写检查器ispell、aspell和hunspell等)作为wordlist的基础。wordlist是UTF-8文本,一行一个单词。将wordlist分割成不同的集合,比如:频繁单词,以及除此之外的单词。然后使用wordlist2dawg得到DAWG文件:

wordlist2dawg frequent_words_list lang.freq-dawg chi_jyq.unicharset

wordlist2dawg words_list lang.word-dawg chi_jyq.unicharset

若需要字典的wordlist示例,可以用combine_tessdata解开已有的traineddata文件,然后用dawg2wordlist提取wordlist文件:

combine_tessdata -u chi_sim.traineddata chi_sim

dawg2wordlist chi_sim.unicharset chi_sim.freq-dawg wordlist

最后的unicharambigs文件

unicharambigs描述了字符之间存在的混淆,该文件可手动填写,一个例子如下:

v1

2 ' ' 1 " 1

1 m 2 r n 0

3 i i i 1 m 0

第1行表示版本,剩下的行是由tab分割的字段,遵循如下格式:

取值为1或0。1表示强制替换,0表示非强制替换。上例中,凡是' '都用"替换。非强制替换的含义:若用target替换source能得从非字典单词创建字典单词,则进行替换。那些利用混淆规则能转换成另一个字典单词的字典单词,不会用于训练自适应分类器。

v2版的unicharambigs文件更为简单

v2

'' " 1

m rn 0

iii m 0

和其它大多数文件一样,unicharambigs必须为UTF-8编码,并以换行符作为文件的结束。该文件不是必须的。

全部组合起来

将生成的所有文件(shapetable、normproto、inttemp、pffmtable等)加上lang.前缀,lang通常是3个字符的语言码,然后执行如下合并:

combine_tessdata lang.

可得识别库文件lang.traineddata,最后就可以进行OCR:

tesseract image.tif output -l lang

Python接口

from pyocr import tesseract

builder = tesseract.builders.TextBuilder()

builder.tesseract_configs = ['-psm', '7', 'scbid']

result = tesseract.image_to_string(Image.open('ocr_test.png'), 'eng', builder)

性能提升

直接修改traineddata文件

针对具体问题,可用combine_tessdata解开traineddata库文件,修改DAWG和unicharambigs文件,然后再生成traineddata文件,从而提高识别率。

参考资料

OSX系统中,由于pango库的原因,text2image命令会导致段错误,该命令是在Linux中执行的。 ↩

原文这样描述:you must cat together the tr files for each font into several single-font tr files. ↩

As of 3.00, there is a limit of 24 bytes for the description of a “character”. This will allow you between 6 and 24 unicodes to describe the character, depending on where your codes sit in the unicode set. If anyone hits this limit, please file an issue describing your situation. ↩

Note the downside of this simpler format is that Tesseract has to encode the utf-8 strings into the components of the unicharset. In complex scripts, this encoding may be ambiguous. In this case, the encoding is chosen such as to use the least utf-8 characters for each component, ie the shortest unicharset components will make up the encoding. ↩

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477