Текстовые слои OCR с поддержкой поиска

HotPDF может отрисовать выбранные загруженные страницы для переданного приложением OCR-движка и атомарно добавить невидимый Unicode-текст, доступный для поиска и выровненный по каждому распознанному слову

Консольное демо SearchableOCR даёт готовый к запуску сценарий: сгенерируйте трёхстраничный образец из одних изображений с --create-sample, выберите встроенный OCR, RapidOCR или распознавание через Tesseract DLL/CLI, укажите страницы, настройте confidence и лимиты ресурсов и сохраните копию с поддержкой поиска и статистикой конвертации

Интеграция движка

Реализуйте IHPDFOCREngine поверх любого доступного приложению синхронного OCR-провайдера

Движок получает через THPDFOCRRequest одолженный TBitmap, запрошенный DPI, нормализованный поворот страницы, координаты media box, оставшиеся бюджеты слов и UTF-16 и действующий cancellation token

Боксы слов и опциональные базовые линии задаются в пиксельных координатах bitmap от левого верхнего угла, а после возврата из Recognize движок не должен ни удерживать, ни освобождать одолженный bitmap

Опциональные локальные движки

Версия 2.754.0 добавляет явные фабрики Tesseract и RapidOCR, возвращающие IHPDFOCREngine на Windows; перегрузка без движка по-прежнему выбирает существующий встроенный движок

Установите и подготовьте выбранный движок локально до создания его адаптера, затем передайте этот адаптер в перегрузку с движком у ApplyLoadedOCRTextLayer; исполняемые файлы, Python-пакеты и OCR-модели — опциональные внешние зависимости и не поставляются в комплекте с HotPDF

Tesseract

Опциональный нативный Tesseract DLL-адаптер добавляет настраиваемые режимы сегментации страницы и движка, многоязычное распознавание и нативные базовые линии слов через HPDFCreateTesseractDLLOCREngine и THPDFTesseractOptions

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

Объявление находится в HPDFTesseractRecognition; предоставьте исполняемый файл Tesseract, способный к TSV-выводу, и каталог данных с нужной языковой моделью, например chi_sim.traineddata для chi_sim

Перегрузка с опциями принимает THPDFTesseractOptions.Default с явной сегментацией страницы, режимом движка распознавания, таймаутом и лимитом входных пикселей; выбирайте tpsSingleLine, tpsSingleWord или tpsSparseText под макет входных данных, как показано в Tesseract OCR Adapters

Этот пример предполагает, что исполняемый файл и данные уже установлены по показанным путям, а PDF — загруженный THotPDF экземпляр

uses SysUtils, HPDFDoc, HPDFTesseractRecognition;

procedure AddTesseractText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  Options: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  Engine := HPDFCreateTesseractOCREngine(
    'C:\OCR\Tesseract\tesseract.exe',
    'C:\OCR\Tesseract\tessdata', 'chi_sim', 60000);
  Options := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, Options, Info) then
    raise Exception.Create('OCR text layer was not added');
end;

RapidOCR

Нативный RapidOCR DLL-адаптер распознает снимки памяти постоянными внутрипроцессными CPU ONNX-моделями через HPDFCreateRapidOCRDLLOCREngine, с опциональной классификацией наклона и кооперативной отменой в сборках Delphi, C++Builder и Windows FPC/Lazarus

Адаптер локальных моделей RapidOCR также предоставляет перегрузку с THPDFRapidOCROptions для явных путей ONNX-моделей, опциональной классификации наклона, локальных символьных словарей и шрифтов, лимитов потоков CPU и бюджета входных пикселей в сборках Delphi, C++Builder и FPC/Lazarus

function HPDFCreateRapidOCREngine(const PythonExecutable, BridgeScript,
  ModelDirectory: string; TimeoutMilliseconds: Cardinal = 60000): IHPDFOCREngine;

Объявление находится в HPDFRapidOCRRecognition; подготовьте Python с rapidocr и onnxruntime, заданный tools/OCR/rapidocr_tsv.py -мостом и этими тремя локальными моделями

Мост также требует %WINDIR%\Fonts\arial.ttf для контейнера результатов RapidOCR, отключает автоматические загрузки и использует один ONNX-поток на настроенный пул исполнения; отсутствие моделей, пакетов или локального шрифта приводит к сбою распознавания

Текущий мост использует конфигурацию модели упрощённого китайского и сохраняет распознанную пунктуацию без подмены полноширинных и полуширинных форм

uses SysUtils, HPDFDoc, HPDFRapidOCRRecognition;

procedure AddRapidOCRText(PDF: THotPDF);
var
  Engine: IHPDFOCREngine;
  Options: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  Engine := HPDFCreateRapidOCREngine(
    'C:\OCR\Python\python.exe',
    'C:\HotPDF\tools\OCR\rapidocr_tsv.py',
    'C:\OCR\RapidOCR\models', 60000);
  Options := THPDFOCRTextLayerOptions.Default;
  if not PDF.ApplyLoadedOCRTextLayer([0], Engine, Options, Info) then
    raise Exception.Create('OCR text layer was not added');
end;

Обе фабрики проверяют существование путей исполняемого файла и данных и принимают таймаут от 1 до 3 600 000 миллисекунд с дефолтом 60 000; неверная конфигурация выбрасывает EArgumentException

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

Вывод TSV ограничен 64 MiB, вывод диагностического файла — 1 MiB, возвращаемые диагностики обрезаются до 4 096 символов; распознанные слова также должны укладываться в бюджеты слов и UTF-16 запроса и в валидные границы bitmap

Распознавательный вывод TSV должен быть корректным UTF-8 без байтов NUL и управляющих символов C0/C1 внутри распознанных слов; искажённый вывод срывает весь запрос распознавания, даже если до ошибки были корректные слова

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

Доказательства и ограничения распознавания

Локальная база RapidOCR 3.8.4 прошла все 15 повторений на пяти фиксированных китайских областях сканов: две чистые области при 300 DPI и три низкоразрешённых стресс-области при 150 DPI, оценённые против текущих эталонных расшифровок с частотой символьных ошибок не более 5% и частотой удалений не более 2%

Все повторения прошли проверки порядка чтения, в сумме 5 190 проверок координат слов или символов и равенство видимых пикселей при 72 DPI; две чистые области имели ноль символьных ошибок против этих эталонов

Два визуальных просмотра ИИ сходятся по китайскому тексту и числам, но некоторые кодовые точки пунктуации в растре остаются неоднозначными, и человеческое арбитражное решение ещё ожидается; расхождения в пунктуации всё же считаются ошибками, а эти результаты — свидетельство по корпусу, а не общая гарантия точности

Геометрия и искомый текст

HotPDF обращает страничное преобразование рендерера, поэтому базовые линии слов остаются выровненными на страницах, повернутых на 0, 90, 180 или 270 градусов

Каждое принятое слово пишется в режиме рендеринга текста 3 Tr, с подобранным горизонтальным масштабом текста и матрицей текста с учётом поворота: растр страницы не меняется, а порядок выбираемого содержимого сохраняется

Общий шрифт Type 0 Identity-H назначает ограниченные локальные для документа CID скалярам Unicode и пишет полную карту ToUnicode, включая UTF-16 surrogate-цели для дополнительных символов

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

Обработка сканированного PDF

Demo/Delphi/SearchableOCR/SearchableOCR.dpr — консольный пример загружает сканированный PDF, запускает нативный RapidOCR с явным локальным языковым профилем, публикует невидимый текст Unicode на всех подходящих страницах и сохраняет новый PDF, не открывая просмотрщик

SearchableOCR.exe scan.pdf searchable.pdf --dll C:\HotPDF\Lib\Native\RapidOCR\Win64\HotPDFRapidOCR.dll --models C:\HotPDF\Lib\Native\RapidOCR\Models --language ru --dpi 300

Используйте --language ch для упрощённого китайского или --language chinese_cht для традиционного китайского; DLL должна соответствовать архитектуре исполняемого файла, а выбранный пакет локальных моделей должен быть установлен

Пример отказывается перезаписывать существующий выходной файл и принимает --replace-ocr при обновлении помеченного OCR-слоя HotPDF

Декодирование JPEG-сканов в Windows FPC рисует в итоговый формат пикселей bitmap до распознавания, поэтому преобразование формата LCL сохраняет декодированное изображение

Обновление существующего OCR-слоя

Установите THPDFOCRTextLayerOptions.ReplaceExistingOCRTextLayer в True, чтобы заменять ранее созданные помеченные OCR-потоки HotPDF на распознанных страницах в той же транзакции, что и новый текст

Это обходит SkipPagesWithText только на помеченных страницах и работает после сохранения и перезагрузки; THPDFOCRTextLayerInfo.ReplacedPageCount сообщает число заменённых страниц

Сбои распознавания и страницы без принятых слов сохраняют старый текстовый слой; непомеченные потоки, включая OCR сторонних инструментов и слои, созданные более ранними выпусками HotPDF, сохраняются

Замена отключает старые потоки содержимого OCR, но не удаляет шрифтовые ресурсы и группы optional content, на которые ещё могут быть ссылки в других местах; инкрементальное сохранение может удерживать устаревшие объекты из предыдущих ревизий

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

Границы, отмена и атомарность

THPDFOCRTextLayerOptions.Default включает распознавание при 300 DPI, пропускает страницы, где текст уже есть, и ограничивает число страниц, пикселей, слов, единиц UTF-16 и байтов сгенерированного содержимого

HotPDF валидирует каждый результат движка и строит всё содержимое страниц до запуска единой copy-on-write транзакции графа, поэтому сбои движка, неверная геометрия, исчерпанные бюджеты, отмена или ошибки коммита оставляют граф загруженных объектов неизменным

Пустой массив индексов страниц выбирает все загруженные страницы, а дубликаты индексов учитываются один раз в порядке первого появления

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

Когда бюджет слов или UTF-16 исчерпан, а остаётся ещё подходящая страница, обработка возвращает otlsBudgetExceeded до отрисовки или распознавания этой страницы и не публикует ни один из запланированных текстовых слоёв; страницы, пропущенные из-за уже имеющегося текста, остатка бюджета распознавания не требуют

Группировка в optional content

Установите UseOptionalContentGroup, чтобы привязать весь сгенерированный текст к одному именованному слою через словарь Resources/Properties каждой страницы

Эта опция требует PDF 1.5 и подчиняется StrictVersionLock; по умолчанию невидимый текст остаётся вне группы optional content ради максимальной совместимости

Замечание о соответствии

Сгенерированный слой с поддержкой поиска намеренно использует невстроенный синтетический шрифт, потому что режим рендеринга 3 никогда не рисует глифы

Этот API сам по себе не даёт соответствующего PDF/A вывода OCR, поэтому в PDF/A-сценарии нужен путь текстового слоя со встроенным шрифтом и запуск запрошенной валидации соответствия перед публикацией

Основные API

Progressive Rendering and Cancellation · ExtractLoadedPageText Method