Адаптеры Tesseract OCR

HPDFTesseractRecognition предоставляет опциональные движки Windows, реализующие IHPDFOCREngine для текстовых слоёв OCR с поддержкой поиска

Фабрика нативной DLL

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

Подготовьте существующую DLL Tesseract с C API, совместимым с Tesseract 5, каталог tessdata и ASCII-идентификатор языка или комбинацию вроде eng, chi_sim или chi_sim+eng

Архитектура библиотеки должна совпадать с приложением: приложение Win32 загружает 32-битную DLL, а приложение Win64 — 64-битную

Держите нужные зависимые DLL рядом с выбранной библиотекой или в стандартных каталогах загрузчика Windows; адаптер загружает явно указанный путь к библиотеке, не меняя текущий каталог и пути поиска процесса

Фабрика проверяет каждый запрошенный файл .traineddata, загружает библиотеку и разрешает требуемые экспорты перед возвратом; неверные пути, модели или опции, отсутствующие экспорты, несовпадение архитектуры и недоступные зависимости выбрасывают исключение

Ни OCR-рантайм, ни модели не поставляются в комплекте и не скачиваются автоматически

Обе фабрики доступны в пакете Windows FPC/Lazarus, а также в сборках Delphi и C++Builder; пересоберите Lib/FPC/HotPDFLaz.lpk под целевую архитектуру, прежде чем использовать HPDFTesseractRecognition

Нативный FPC-адаптер читает текущее сырое изображение LCL, включая пиксели, записанные через scanline, и сохраняет Unicode-слова независимо от системной ANSI-кодовой страницы

Опции

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-воркер по таймауту завершается
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;

Результаты и владение

Адаптер копирует одолженный bitmap в буфер градаций серого с порядком строк сверху вниз, передаёт DPI запроса и распознаёт через нативный экземпляр API, локальный для запроса

Слова сохраняют нативный порядок чтения, провалидированный Unicode-текст UTF-8, пиксельные границы от левого верхнего угла и уверенность, перемасштабированную из диапазона 0–100 в 0–1; дополнительные символы расходуют по две единицы UTF-16

Доступные базовые линии слов передаются дальше с обоими концами; когда базовой линии нет, действует обычный геометрический fallback текстового слоя

При преимущественно вертикальной базовой линии нативный адаптер использует ширину рамки слова как TextHeightPixels; горизонтальные базовые линии используют высоту рамки, включая обращённые направления чтения, поэтому длина вертикального слова не превращается в его размер шрифта

Это оценка по доминирующей оси: выровненные по осям рамка слова и базовая линия сами по себе не позволяют восстановить точную высоту текста при произвольных углах наклона

Пустая страница завершается успешно с пустым массивом слов; повреждённый UTF-8, встроенные управляющие символы, невалидная геометрия или уверенность, исчерпанные бюджеты слов или текста, отмена и сбои распознавания возвращают False, очищают все частичные слова и заполняют диагностику

Каждый запрос освобождает свой итератор, выделенные нативные строки, монитор и экземпляр API; освобождение адаптера выгружает его ссылку на библиотеку

Лимиты и отмена

Каждое входное измерение должно быть не больше 32,767 пикселей и укладываться в MaxPixels; распознанный текст должен умещаться в бюджет MaxTextCodeUnits запроса и лимит адаптера в 1,048,576 единиц UTF-16, а число слов — в MaxWords

Адаптер проверяет отмену и прошедшее время при конвертации bitmap и обходе результатов, а во время распознавания передаёт нативный монитор с оставшимся дедлайном и callback отмены

Нативная отмена кооперативная: монитор Tesseract покрывает распознавание слов и не прерывает каждый шаг инициализации или анализа разметки; такие вызовы могут завершиться раньше, чем будет сообщена запрошенная отмена или истёкший дедлайн

Бюджеты пикселей и вывода не накладывают жёсткого лимита на память моделей или распознавания нативной библиотеки; если приложению нужен отдельно завершаемый воркер, используйте процессный адаптер

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, использует настроенный таймаут и проверяет MaxPixels до сохранения одолженного bitmap или запуска воркера

Существующая перегрузка с таймаутом сохраняет автоматическую сегментацию страницы и режим движка, выбранный исполняемым файлом, без нового лимита пикселей адаптера; когда нужен явный лимит входа, используйте перегрузку с опциями

Обе перегрузки сохраняют запрошенный DPI, TSV-вывод, ограниченные наследуемые дескрипторы, опрос отмены и завершение воркера при сбое; 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-пример, параметры рендеринга, группировку в optional content и ограничения соответствия смотрите в разделе Текстовые слои OCR с поддержкой поиска