本文档描述了 Tesseract 中的 OCR(光学字符识别)管道,从图像输入到文本输出。它涵盖了识别图像中的文本时发生的关键处理步骤,包括预处理、页面分割、识别和后处理。
有关特定识别引擎的更多详细信息,请参阅 识别引擎。有关输出渲染的详细信息,请参阅 输出渲染器。
上图显示了 Tesseract OCR 管道的高级步骤。该过程以输入图像开始,经过各种分析和识别阶段,最终生成文本输出。
来源: src/api/baseapi.cpp759-842 src/ccmain/tesseractclass.h179-390
OCR 管道的第一步是图像采集和预处理。
Tesseract 可以通过 TessBaseAPI::SetImage 方法接受各种格式的图像
SetImage(const unsigned char*, int, int, int, int)SetImage(Pix*)图像可以是灰度(每像素 8 位)、彩色(每像素 24 或 32 位)或二值(每像素 1 位)。
ImageThresholder 类负责将图像转换为二值格式,这对 OCR 至关重要。Tesseract 提供了三种阈值处理方法:
阈值处理过程会生成一个二值图像,将文本像素与背景分离。此图像成为所有后续处理的基础。
来源: src/ccmain/thresholder.cpp181-274 src/ccstruct/otsuthr.cpp27-35
预处理完成后,Tesseract 会分析图像的布局以识别文本区域。
页面分割过程由 tessedit_pageseg_mode 参数控制,该参数可以设置为不同的值:
| 模式 | 描述 |
|---|---|
| PSM_OSD_ONLY | 仅进行方向和脚本检测 |
| PSM_AUTO_OSD | 自动页面分割,包含方向和脚本检测 |
| PSM_AUTO | 自动页面分割,但不进行 OSD 或 OCR |
| PSM_SINGLE_COLUMN | 将图像视为单栏文本 |
| PSM_SINGLE_BLOCK | 将图像视为单个文本块 |
| PSM_SINGLE_LINE | 将图像视为单行文本 |
| PSM_SINGLE_WORD | 将图像视为单个单词 |
| PSM_SINGLE_CHAR | 将图像视为单个字符 |
| PSM_SPARSE_TEXT | 尽可能多地查找文本,不考虑顺序 |
| PSM_RAW_LINE | 将图像视为单行文本,绕过 Tesseract 特定的 hack |
页面分割过程会生成一个 BLOCK_LIST,其中包含已识别的文本和其他内容的区域。然后对这些块进行进一步处理以查找行、单词和字符。
FindLines() 方法将块分割成行,创建一个包含分割和文本识别结果的 PAGE_RES 对象。
来源: src/ccmain/pagesegmain.cpp101-402 src/api/baseapi.cpp436-441
分割完成后,Tesseract 会继续识别每个片段中的文本。
Tesseract 有两个主要的识别引擎:
使用的引擎由 tessedit_ocr_engine_mode 参数决定。
| 模式 | 描述 |
|---|---|
| OEM_TESSERACT_ONLY | 仅使用旧版 Tesseract 引擎 |
| OEM_LSTM_ONLY | 仅使用 LSTM 神经网络 |
| OEM_TESSERACT_LSTM_COMBINED | 同时使用两种引擎并合并结果 |
| OEM_DEFAULT | 基于可用情况的默认设置 |
在使用 LSTM 引擎时:
LSTMRecognizer::RecognizeLine() 来处理图像。RecodeBeamSearch 寻找最可能的字符序列。在使用旧版引擎时:
classify_word_pass1() 来处理单词。来源: src/api/baseapi.cpp825-842 src/lstm/lstmrecognizer.cpp245-267
在初步识别后,Tesseract 会应用基于词典的校正和其他后处理步骤。
Tesseract 中的词典系统通过以下方式帮助提高识别准确性:
词典过程由以下参数控制:
tessedit_enable_dict_correctiontessedit_enable_bigram_correction每个识别出的单词都会分配一个置信度值。低置信度的单词可能会被
Tesseract 使用以下步骤来处理置信度:
make_reject_map() - 为每个单词创建拒绝映射rejection_passes() - 应用各种拒绝策略quality_based_rejection() - 使用质量指标接受或拒绝单词识别和后处理完成后,可以通过以下方式访问结果:
ResultIterator - 提供对所有已识别元素的访问TessBaseAPI::GetUTF8Text() - 获取完整的识别文本来源: src/api/baseapi.cpp393-402 src/ccmain/tesseractclass.h480-643
整个 OCR 管道可以通过 TessBaseAPI 类访问,该类提供了处理每个阶段的方法。
典型的用法流程是:
TessBaseAPI::Init() 初始化。TessBaseAPI::SetImage() 设置图像。TessBaseAPI::Recognize() 识别文本。TessBaseAPI::GetUTF8Text() 等方法检索结果。TessBaseAPI::End() 进行清理。在整个管道中,使用了几个关键数据结构:
| 数据结构 | 描述 |
|---|---|
Image/Pix | 图像表示。 |
BLOCK_LIST | 页面中已识别块的列表。 |
PAGE_RES | 页面分割和识别的结果。 |
WERD_RES | 特定单词的结果。 |
UNICHARSET | 字符集及相关信息。 |
ETEXT_DESC | 进度监视器和控制接口。 |
ResultIterator | 用于访问识别结果的迭代器。 |
来源: src/api/baseapi.cpp161-865 src/ccmain/tesseractclass.h179-182
Tesseract 提供了几种扩展或自定义 OCR 管道的方法:
ImageThresholder 来实现自定义阈值处理。对于训练新模型,Tesseract 使用相似但修改过的管道。
训练管道:
来源: src/ccstruct/imagedata.cpp216-267 src/ccmain/linerec.cpp37-130