PaddleOCR: OCR и структура таблицы — это два разных маршрута одной библиотеки. Общий конвейер распознаёт текст, а PP-StructureV3 восстанавливает документную разметку и отдаёт Markdown или JSON. Ниже — установка, учебный stock.png, ручной эталон и проверка пар ячеек.
Архитектура PaddleOCR и границы версии
Продуктовая архитектура PaddleOCR в актуальной документации разделена на два уровня. Первый — общий конвейер распознавания текста, который в README проекта описан как универсальное распознавание сцены и документов. Второй — документный разбор, где основную роль играет PP-StructureV3: по описанию в README он преобразует сложные PDF и изображения в Markdown или JSON и даёт более детальные координаты, включая координаты ячеек таблиц и координаты текста. Это разделение задаёт границу ответственности: за символы отвечает OCR, за связи «заголовок — значение» отвечает структурный конвейер.
Версия в сохранённой инструкции по установке обозначена как PaddleOCR 3.5. Именно она использует унифицированную конфигурацию inference engine и может работать через бэкенды PaddlePaddle и Transformers. README проекта отдельно фиксирует релиз 3.5.0 от 2026.04.21: гибкие бэкенды вывода, интеграция с экосистемой Hugging Face, поддержка Transformers у двадцати основных моделей и конвертация офисных документов Word, Excel и PowerPoint в Markdown. Тот же README описывает более поздние релизы 3.6.0 и 3.7.0, поэтому при чтении сторонних руководств стоит сверять номер версии с официальной страницей.
Границы версии важны по практической причине. Историческая статья LearnOpenCV по PP-OCRv3 показывает стадии OCR и собственные замеры на Tesla K80, но её импорты и численные результаты относятся к старому API. Использовать их как текущую инструкцию нельзя: установка, имена классов и способ сохранения результатов в 3.x отличаются. Актуальный API сверяется с официальной документацией проекта; руководство paddleocr.dev дополнительно показывает собственные примеры Python API и CLI.
Третья ветка архитектуры — PaddleOCR-VL. README описывает её как компактную vision-language модель на 0.9B параметров с динамическим энкодером и языковой моделью ERNIE-4.5-0.3B, поддерживающую 109 языков и распознавание текста, таблиц, формул и графиков. Для нашей задачи это отдельный инструмент: он решает документный разбор другим способом, а маршрут с PP-StructureV3 остаётся документированным путём для структурированного вывода с координатами. Выбор между ними зависит от того, нужны ли вам точные координаты ячеек.
Ещё один элемент архитектуры — разделение зависимостей. Официальная инструкция по установке перечисляет группы: doc-parser для документного разбора, ie для извлечения информации, trans для перевода, doc2md для конвертации офисных файлов, all для полного набора. Базовое распознавание текста и предобработка изображений не требуют дополнительных групп. Это означает, что для проверки структуры таблицы достаточно группы doc-parser для нужной процедуры.
Установка и учебный вход stock.png
Установка начинается с выбора Python. Официальная инструкция сообщает: пакет paddleocr и группа doc2md поддерживают Python 3.8 и новее, остальные группы требуют Python 3.9 и новее из-за вышестоящих зависимостей. Базовая установка выполняется командой pip install paddleocr, полный набор — pip install «paddleocr[all]». Для документного разбора достаточно группы doc-parser.
После пакета ставится inference engine. Инструкция подчёркивает: чтобы действительно запускать вывод модели, нужно установить выбранный движок по отдельному руководству по inference engine и конфигурации. Без движка библиотека установлена, но вывод не выполняется. Для обучения и экспорта моделей существует отдельная ветка установки: клонирование репозитория, установка PaddlePaddle и requirements.txt. Инструкция предупреждает, что при наличии другого движка вроде Transformers возможны конфликты зависимостей и рекомендует чистое окружение.
Учебный вход в нашем разборе — файл stock.png. Он создаётся детерминированным генератором: заголовок Stock, таблица с заголовками Item и Qty, строками A | 12 и B | 7, примечание Not for sale. PNG содержит настоящую сетку таблицы и отдельную оговорку под ней. Генератор ниже создаёт stock.png из того же полного учебного набора. Для него нужен пакет Pillow, который можно установить командой python -m pip install Pillow.
from PIL import Image, ImageDraw
image = Image.new("RGB", (200, 120), "white")
draw = ImageDraw.Draw(image)
draw.text((12, 4), "Stock", fill="black")
for y in (24, 44, 64, 84):
draw.line((12, y, 180, y), fill="black")
for x in (12, 96, 180):
draw.line((x, 24, x, 84), fill="black")
for text, xy in [
("Item", (20, 28)), ("Qty", (104, 28)),
("A", (20, 48)), ("12", (104, 48)),
("B", (20, 68)), ("7", (104, 68)),
]:
draw.text(xy, text, fill="black")
draw.text((12, 96), "Not for sale", fill="black")
image.resize((800, 480), resample=Image.Resampling.NEAREST).save("stock.png")
Координаты и размер здесь задают только оформление вымышленного входа. Этот код создаёт изображение для следующего шага и не запускает PaddleOCR.
Схема документа задаётся до генерации и выглядит так:
# Схема учебного документа stock.png
document = {
"title": "Stock",
"table": {
"columns": ["Item", "Qty"],
"rows": [["A", 12], ["B", 7]],
},
"note": "Not for sale",
}
Ручной эталон текста: Stock, Item, Qty, A, 12, B, 7, Not for sale. Ручной эталон структуры: columns=[‘Item’,’Qty’]; rows=[[‘A’,12],[‘B’,7]]; note=’Not for sale’. Эти два эталона проверяются отдельно. Текстовый эталон отвечает на вопрос, все ли символы найдены. Структурный эталон отвечает на вопрос, связаны ли значения со своими заголовками и строками.
Важно, что это эталон собственного учебного документа. Он не является выполненным прогоном PaddleOCR, и выход модели в нашем разборе не запускался. Confidence модели неизвестен. Читатель получает полностью заданный вход и критерии приёмки, а сам запускает код в своём окружении.
Копируемый маршрут: два режима и файлы
Маршрут состоит из двух независимых режимов. Режим 1 — общий OCR через класс PaddleOCR. Режим 2 — документный разбор через PPStructureV3. Оба режима сохраняют результаты в отдельные каталоги, чтобы файлы не перезаписывали друг друга.
Полный документированный путь сохранения, который читатель выполняет самостоятельно:
from paddleocr import PaddleOCR, PPStructureV3
ocr = PaddleOCR(use_doc_orientation_classify=False,
use_doc_unwarping=False, use_textline_orientation=False)
for result in ocr.predict(input="stock.png"):
result.save_to_json(save_path="out_ocr")
parser = PPStructureV3()
for result in parser.predict(input="stock.png"):
result.save_to_json(save_path="out_structure")
result.save_to_markdown(save_path="out_structure")
Разберём блок по частям. Конструктор PaddleOCR получает три флага, отключающие классификацию ориентации документа, выпрямление и ориентацию текстовой строки. Для ровного учебного PNG эти шаги не нужны, и их отключение убирает лишние модели из памяти. Метод predict вызывается с именованным аргументом input. В этом примере результаты predict обходятся циклом, поэтому каждый элемент сохраняется отдельным вызовом. Для каждого результата вызывается save_to_json с каталогом сохранения.
Второй режим создаёт объект PPStructureV3 без аргументов и вызывает predict с тем же файлом. Для каждого результата сохраняются два формата: JSON и Markdown. Официальная инструкция по PP-StructureV3 описывает эти форматы вывода, а README проекта подтверждает, что PP-StructureV3 конвертирует документы в Markdown или JSON и предоставляет координаты ячеек таблиц. Каталог out_structure получает оба файла.
Необходимые файлы на диске после запуска: stock.png в рабочем каталоге, каталог out_ocr с JSON-результатом OCR, каталог out_structure с JSON и Markdown структурного разбора. Если каталоги не существуют, save_to_json и save_to_markdown создают их по документированному поведению. Перед запуском убедитесь, что установлен совместимый inference engine и зависимости по официальной инструкции.
Сравнение двух режимов по явным критериям:
| Критерий | Режим 1: PaddleOCR | Режим 2: PPStructureV3 |
|---|---|---|
| Что возвращает | Текст и координаты строк | Разметку документа, таблицы, примечания |
| Форматы сохранения | JSON | JSON и Markdown |
| Координаты ячеек | Не предоставляет | Предоставляет по README |
| Зависимости | Базовая установка | Группа doc-parser |
| Проверка пар ячеек | Проверка требует сопоставления текста и координат. | Доступна через структуру |
| Примечание под таблицей | Входит в общий текст | Отдельный элемент разметки |
Таблица показывает, почему для проверки структуры нужен второй режим. Первый режим возвращает распознанный текст и координаты, которые можно дополнительно сопоставлять для проверки строк. Второй режим извлекает структуру таблицы, а её соответствие парам A→12 и B→7 всё равно проверяется по эталону.
Проверка фактов, полей и отрицательных случаев
Приёмка результата начинается с текстового эталона. Сравните множество распознанных символов с эталоном Stock, Item, Qty, A, 12, B, 7, Not for sale. Если все восемь элементов присутствуют, текстовый контракт выполнен. Отсутствие любого элемента означает пропуск: например, примечание Not for sale может не попасть в результат, если модель сочла его частью таблицы или шумом.
Структурный эталон проверяется парами. Ожидаемые пары: A→12 и B→7. Проверка сопоставляет значения в каждой строке таблицы. Строка вида A12 B7 без структуры содержит все символы, но не проходит структурный контракт: связи между элементом и количеством нет. Это ключевое различие между двумя режимами, и оно определяет выбор инструмента.
Отрицательные случаи помогают откалибровать проверку. Первый: A→13 и B→7. Число в строке A неверно, строка B верна. Это ошибка распознавания одного значения при правильной структуре. Второй: A→7 и B→12. Обе пары неверны, хотя набор чисел {7, 12} правильный. Это ошибка привязки: значения перепутаны между строками. Третий: отсутствие Not for sale. Примечание пропущено, текстовая полнота нарушена.
Раздельная приёмка OCR и структуры даёт точный диагноз. Если текст полный, а пары неверны, проблема в структурном конвейере. Если пары верны, но символов не хватает, проблема в распознавании. Если неверны и символы, и пары, начните с качества входного изображения: разрешение, контраст, ровность сетки.
Проверка отдельных полей структуры включает заголовки столбцов. Ожидаемые columns=[‘Item’,’Qty’]. Если заголовок распознан как Item с лишним символом или Qty слит с соседним текстом, структура строк останется верной, но имена столбцов потребуют ручной правки. Поле note должно содержать Not for sale как отдельное значение.
Для автоматизации проверки удобно сравнивать JSON-выход с эталоном программно. Ниже — функция сравнения, которую читатель адаптирует под фактическую схему своего JSON:
# Сравнение структурного результата с ручным эталоном
expected_rows = [["A", 12], ["B", 7]]
expected_columns = ["Item", "Qty"]
expected_note = "Not for sale"
def check_structure(parsed_rows, parsed_columns, parsed_note):
errors = []
if parsed_columns != expected_columns:
errors.append(f"columns: {parsed_columns}")
if parsed_rows != expected_rows:
errors.append(f"rows: {parsed_rows}")
if parsed_note != expected_note:
errors.append(f"note: {parsed_note}")
return errors
Функция возвращает список расхождений. Пустой список означает, что структура совпала с эталоном. Такой подход отделяет проверку структуры от проверки текста и делает приёмку воспроизводимой.
Чужие замеры и выводы о качестве
Сторонние руководства содержат собственные измерения, и переносить их на учебный пример нельзя. Историческая статья LearnOpenCV по PP-OCRv3 приводит замеры скорости на Tesla K80 и использует вызовы вида ocr.ocr и draw_ocr. Эти данные относятся к версии PP-OCRv3 и конкретному железу 2022 года. Текущий API 3.x строится на predict и save_to_json, поэтому старые вызовы и численные результаты не описывают поведение актуальной библиотеки.
Руководство paddleocr.dev публикует собственные тесты, примеры объектов результата и рекомендации по батчингу. Это наблюдения издания о его окружении. Для нашего маршрута API сверяется с официальной документацией проекта.
README проекта приводит маркетинговые метрики: PP-OCRv6 с приростом +4.6% по детекции и +5.1% по распознаванию относительно PP-OCRv5, ускорение CPU в 5.2 раза, 0.13 секунды на A100 GPU, три тира моделей tiny 1.5M, small 7.7M, medium 34.5M. PaddleOCR-VL-1.6 заявлена с точностью 96.3% на OmniDocBench v1.6. Эти числа описывают публичные бенчмарки и конкретные конфигурации. Они не переносятся на учебный stock.png: у нас другой вход, другая задача и отсутствие прогона.
Тарифы и условия облачного использования в нашем разборе не рассматриваются. README упоминает официальный сайт с интерактивным центром опыта и API, а также размещение моделей на HuggingFace и ModelScope. Конкретные условия доступа, лимиты и цены этих сервисов относятся к их владельцам и требуют отдельной проверки на актуальных страницах. Доступность сервисов из России в сохранённых источниках не описана.
Выводы о качестве также остаются у своих источников. Утверждение README о превосходстве над закрытыми решениями в публичных бенчмарках — это заявление проекта о своих замерах. Независимое руководство paddleocr.dev даёт собственные наблюдения по API. Наш учебный пример показывает только то, как проверить структуру на конкретном документе, и не подтверждает и не опровергает чужие метрики.
Практический вывод для читателя: используйте чужие замеры для выбора конфигурации под своё железо, а приёмку результата стройте на собственном эталоне. Ручной эталон из восьми текстовых элементов и трёх структурных полей даёт проверяемый критерий, который не зависит от версии бенчмарка.
Неизвестные значения и условия отказа
Часть значений в этом разборе остаётся неизвестной, и это влияет на приёмку. Confidence модели на учебном документе не измерялся. Выход модели не запускался в рамках подготовки материала. Это означает, что порог уверенности, при котором результат можно принять автоматически, читатель определяет сам по своим данным.
Условия, при которых результат нельзя принять, формулируются через эталон. Текстовый результат нельзя принять, если отсутствует хотя бы один элемент из восьми: Stock, Item, Qty, A, 12, B, 7, Not for sale. Структурный результат нельзя принять, если хотя бы одна пара не совпала: A→12 или B→7. Результат нельзя принять, если заголовки столбцов отличаются от Item и Qty или примечание отличается от Not for sale.
Отдельный случай — совпадение набора чисел при неверных парах. Если результат содержит 7 и 12, но привязка перепутана, автоматическая проверка по множеству чисел пройдёт, а структурный контракт будет нарушен. Поэтому проверка пар обязательна и должна идти по строкам.
Качество входного изображения задаёт границы применимости. Учебный PNG создан детерминированным генератором с ровной сеткой и чётким шрифтом. Реальные сканы с наклоном, искажением, бликами и фотографиями экрана требуют включения предобработки: классификации ориентации, выпрямления и ориентации текстовой строки. В нашем примере эти шаги отключены флагами конструктора, и для сложных входов их стоит вернуть.
Версия библиотеки также влияет на приёмку. Инструкция по установке описывает PaddleOCR 3.5, README фиксирует релизы вплоть до 3.7.0. При обновлении меняются доступные модели и параметры конвейеров. Перед приёмкой зафиксируйте версию пакета и версию inference engine в своём окружении, чтобы результат был воспроизводим.
Наконец, разделение зависимостей влияет на доступные функции. Базовая установка даёт общий OCR и предобработку. Для PP-StructureV3 нужна группа doc-parser. Если структурный режим не запускается, проверьте установленную группу зависимостей и наличие inference engine по официальной инструкции.
Частые вопросы
Что такое PaddleOCR простыми словами?
PaddleOCR — библиотека распознавания текста и документного разбора. Общий конвейер извлекает текст и координаты строк, а PP-StructureV3 восстанавливает разметку документа и отдаёт Markdown или JSON. README проекта описывает её как инструмент преобразования PDF и изображений в структурированные данные, готовые для языковых моделей.
Чем OCR отличается от структуры таблицы?
OCR отвечает за символы и их расположение на изображении. Структура таблицы отвечает за связи между заголовками, строками и значениями. В нашем примере текст A, 12, B, 7 может быть распознан полностью, а пары A→12 и B→7 при этом останутся непроверенными без структурного режима.
Как установить PaddleOCR для разбора таблиц?
Установите пакет командой pip install paddleocr, затем добавьте группу doc-parser для документного разбора. После этого установите совместимый inference engine по официальной инструкции. Базовая установка поддерживает Python 3.8 и новее, остальные группы требуют Python 3.9 и новее.
Как проверить, что таблица распознана правильно?
Сравните результат с ручным эталоном: columns=[‘Item’,’Qty’], rows=[[‘A’,12],[‘B’,7]], note=’Not for sale’. Проверяйте соответствие элемента и количества в каждой строке. Отсутствие примечания Not for sale означает пропуск элемента разметки.
Почему пары ячеек могут быть перепутаны?
Ошибка привязки возникает, когда модель верно распознаёт числа, но неверно связывает их со строками. Случай A→7 и B→12 показывает обе неверные пары при правильном наборе чисел. Проверка по строкам выявляет такую ошибку, проверка по множеству значений её пропускает.
