Tesseract OCR 适配器

HPDFTesseractRecognition 为可搜索 OCR 文本层提供实现 IHPDFOCREngine 的可选 Windows 引擎

原生 DLL 工厂

function HPDFCreateTesseractDLLOCREngine(const LibraryPath,
  TessDataDirectory, Language: string): IHPDFOCREngine; overload;
function HPDFCreateTesseractDLLOCREngine(const LibraryPath,
  TessDataDirectory, Language: string;
  const Options: THPDFTesseractOptions): IHPDFOCREngine; overload;

提供一个暴露 Tesseract 5 兼容 C API 的现有 Tesseract DLL、一个 tessdata 目录,以及 ASCII 语言标识符或组合,例如 eng、chi_sim 或 chi_sim+eng

库架构必须与应用匹配:Win32 应用加载 32 位 DLL,Win64 应用加载 64 位 DLL

必需的依赖 DLL 要放在所选库旁边或标准 Windows 加载器目录中;适配器加载显式库路径,不改变当前目录或进程搜索路径

工厂会校验每个请求的 .traineddata 文件,加载库并在返回之前解析必需的导出;无效路径、模型、选项、缺失导出、架构不匹配和依赖不可用都会抛出异常

不会捆绑任何 OCR 运行时或模型,也不会自动下载

两个工厂在 Windows FPC/Lazarus 包以及 Delphi 和 C++Builder 构建中均可用;使用 HPDFTesseractRecognition 之前,请先针对目标架构重新构建 Lib/FPC/HotPDFLaz.lpk

原生 FPC 适配器读取当前 LCL 原生图像(包括经 scanline 写入的像素),并独立于系统 ANSI 代码页保留 Unicode 单词

选项

THPDFTesseractOptions = record
  PageSegMode: THPDFTesseractPageSegMode;
  EngineMode: THPDFTesseractEngineMode;
  TimeoutMilliseconds: Cardinal;
  MaxPixels: Integer;
  class function Default: THPDFTesseractOptions; static;
end;

覆盖字段之前先调用 THPDFTesseractOptions.Default;同一份选项记录既可配置原生 DLL 工厂,也可配置本地 CLI 的选项重载

字段默认值含义
PageSegModetpsAuto自动页面分割,不检测方向
EngineModetemDefault所选语言模型支持的引擎模式
TimeoutMilliseconds60000请求时限,取值 1 到 3,600,000 毫秒;DLL 与取消协作,CLI worker 超时即被终止
MaxPixels16777216输入像素预算,可配置为 1 到 67,108,864 像素
THPDFTesseractPageSegMode = (
  tpsOSDOnly, tpsAutoOSD, tpsAutoOnly, tpsAuto, tpsSingleColumn,
  tpsSingleBlockVertical, tpsSingleBlock, tpsSingleLine, tpsSingleWord,
  tpsCircleWord, tpsSingleCharacter, tpsSparseText, tpsSparseTextOSD,
  tpsRawLine);
THPDFTesseractEngineMode = (
  temLegacyOnly, temLSTMOnly, temLegacyAndLSTM, temDefault);

tpsOSDOnly 与 tpsAutoOnly 不执行单词识别,会被适配器拒绝;tpsAutoOSD 与 tpsSparseTextOSD 还需要 osd.traineddata

单行文本用 tpsSingleLine,均匀文本块用 tpsSingleBlock,分散文本用 tpsSparseText;这些模式不会修复扫描件的透视畸变,也不提供通用的版面保证

temLSTMOnly 需要 LSTM 模型,legacy 模式需要对应的 legacy 模型组件;不受支持的组合会在原生初始化期间失败

可搜索 PDF 示例

PDF 必须已经加载,且 DLL、依赖和语言模型必须已安装在所示位置

uses SysUtils, HPDFDoc, HPDFTesseractRecognition;

procedure AddNativeOCRText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  NativeOptions: THPDFTesseractOptions;
  LayerOptions: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  NativeOptions := THPDFTesseractOptions.Default;
  NativeOptions.EngineMode := temLSTMOnly;
  NativeOptions.PageSegMode := tpsAuto;
  Engine := HPDFCreateTesseractDLLOCREngine(
    'C:\OCR\libtesseract-5.dll', 'C:\OCR\tessdata',
    'chi_sim+eng', NativeOptions);
  LayerOptions := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, LayerOptions, Info) then
    raise Exception.Create(string(Info.Diagnostic));
end;

结果与所有权

适配器把借用的位图复制为自上而下的灰度缓冲区,转发请求 DPI,并通过请求局部的原生 API 实例执行识别

单词保持原生阅读顺序、经验证的 UTF-8 Unicode 文本、左上像素边界框,以及从 0-100 缩放到 0-1 的置信度;补充字符占用两个 UTF-16 单元

可用的单词基线连同两个端点一起透传;基线不可用时,应用既有的文本层几何回退

对于以竖排为主的基线,原生适配器用单词框宽度作为 TextHeightPixels;水平基线用框高,包括反向阅读方向,因此竖排单词的长度不会变成它的字号

这是主轴估计:仅凭轴对齐的单词框和基线,无法在任意倾斜角度下恢复精确的文本高度

空页面以空单词数组成功返回;畸形 UTF-8、内嵌控制字符、无效几何或置信度、单词或文本预算耗尽、取消以及识别失败都返回 False,清除所有部分单词并填写诊断信息

每个请求都会释放自己的迭代器、已分配的原生字符串、monitor 与 API 实例;释放适配器会卸载其库引用

限制与取消

输入尺寸每边不得超过 32,767 像素且必须符合 MaxPixels;识别文本必须符合请求的 MaxTextCodeUnits 预算和适配器 1,048,576 个 UTF-16 单元的上限,单词数必须符合 MaxWords

适配器在位图转换和结果迭代期间检查取消与已用时间,并在识别期间提供带剩余时限和取消回调的原生 monitor

原生取消是协作式的:Tesseract 的 monitor 覆盖单词识别,但不会中断每一次初始化或版面分析步骤;这些调用可能在所请求的取消或过期时限被上报之前完成

像素与输出预算不会对原生库的模型或识别内存使用施加硬性限制;应用需要可独立终止的工作进程时,请使用进程适配器

ApplyLoadedOCRTextLayer 校验所有结果并原子地发布每个选定页面,因此适配器失败不会改动已加载的文档

DLL 适配器在返回结果之前拒绝无效的 UTF-8、修剪解码出的单词文本,并拒绝残留的 C0、DEL 和 C1 控制字符,因此畸形文本会让请求失败,而不是被 PDF 文本层悄悄省略

本地 CLI 工厂

function HPDFCreateTesseractOCREngine(const ExecutablePath,
  TessDataDirectory, Language: string;
  TimeoutMilliseconds: Cardinal = 60000): IHPDFOCREngine; overload;
function HPDFCreateTesseractOCREngine(const ExecutablePath,
  TessDataDirectory, Language: string;
  const Options: THPDFTesseractOptions): IHPDFOCREngine; overload;

选项重载把 PageSegMode 转发为 --psm、EngineMode 转发为 --oem,使用配置的超时,并在保存借用位图或启动 worker 之前检查 MaxPixels

既有的超时重载保留自动页面分割和可执行文件自选的引擎模式,不施加新的适配器像素上限;需要显式输入上限时使用选项重载

两个重载都保留请求 DPI、TSV 输出、受限继承句柄、取消轮询和失败时终止 worker;CLI 没有原生基线信息,TSV 输出上限 64 MiB,诊断文件输出上限 1 MiB

创建配置好的引擎时,无效的分割模式、引擎模式、超时和像素上限会抛出 EArgumentException;模型可用性(包括方向模式所需的 osd.traineddata)和模型与引擎的兼容性由可执行文件在识别期间检查

var
  CLIOptions: THPDFTesseractOptions;
  Engine: IHPDFOCREngine;
begin
  CLIOptions := THPDFTesseractOptions.Default;
  CLIOptions.PageSegMode := tpsSingleLine;
  CLIOptions.EngineMode := temLSTMOnly;
  CLIOptions.MaxPixels := 8000000;
  Engine := HPDFCreateTesseractOCREngine(
    'C:\OCR\tesseract.exe', 'C:\OCR\tessdata', 'eng', CLIOptions);
end;

孤立单词用 tpsSingleWord,分散文本用 tpsSparseText,单个竖排块用 tpsSingleBlockVertical 配合适的竖排文本模型;工厂不会自动裁剪页面或选择模型

CLI 适配器严格校验 UTF-8,拒绝识别单词内部的 NUL 字节和 C0/C1 控制字符;如果畸形输出跟在本来有效的单词之后,会清除全部结果

CLI 示例、渲染选项、可选内容分组和一致性限制见可搜索 OCR 文本层