Человек фотографирует чек из магазина. Или сканирует страницу договора. Ему нужен структурированный текст с — цифры должны сходиться.
Мы запустили три модели по отдельности и упёрлись в стену — тему мы подробно разбираем в статье про :
Модель
Что делает хорошо
Где ломается
PaddleOCR
Печатный текст
Рукопись
Unlimited-OCR
Таблицы
Скорость
VLM (Qwen)
Контекст
Галлюцинации в цифрах
Ни одна модель не покрывает все сценарии. Выход — комбинировать.
Архитектура: три слоя с fallback
Цепочка работает по принципу «кто справился — тот и победил»:
``
Изображение
↓
[Слой 1: PaddleOCR] → текст есть → готово
↓ (пустой результат)
[Слой 2: Unlimited-OCR] → текст есть → готово
↓ (пустой результат)
[Слой 3: VLM (Qwen)] → понимает контекст → готово
`
Практический сценарий:
Простой печатный документ (квитанция, бланк) — PaddleOCR берёт на себя за 2-3 секунды
Таблицы или сложная вёрстка — PaddleOCR возвращает мусор → Unlimited-OCR парсит за 15-25 секунд
Рукопись или фото с плохим качеством — только VLM справляется. Qwen понимает контекст: "на фото кассового чека вот эти цифры — это цены", даже если OCR-модели этого не видят
Что мы пробовали и что не сработало
Tesseract
Первым делом попробовали Tesseract — самый популярный open-source OCR. На русском языке он работал посредственно. CER (Character Error Rate) на наших тестовых документах был около 15-20%. Для чеков, где важна каждая цифра — неприемлемо.
Кроме того, Tesseract плохо работает с:
Смешанным текстом (русский + цифры + спецсимволы)
Документами с нестандартной вёрсткой
Фотографиями (не сканами)
EasyOCR
Попробовали EasyOCR. Лучше, чем Tesseract, но всё равно недостаточно для production. Основная проблема — скорость. На CPU обработка одного документа занимала 10-15 секунд. Для пакетной обработки десятков документов — слишком долго.
Что в итоге осталось
Модель
Скорость
Точность (RU)
Таблицы
Рукопись
Где используем
PaddleOCR
2-3 сек
Хорошая
Плохо
Плохо
Слой 1 (быстрый)
Unlimited-OCR
15-25 сек
Хорошая
Отлично
Средне
Слой 2 (таблицы)
VLM (Qwen)
20-30 сек
Зависит от контекста
Хорошо
Хорошо
Слой 3 (fallback)
Ensemble: три модели параллельно
Помимо цепочки fallback, есть режим ensemble — все три модели работают параллельно, потом LLM объединяет результаты.
`rust
// Упрощённый код из ml_client.rs
let f1 = self.paddleocr_ocr(image_data, mime_type);
let f2 = self.unlimited_ocr_ocr(image_data, mime_type);
let f3 = self.vlm_ocr(image_data, mime_type);
let results = join_all(vec![f1, f2, f3]).await;
`Почему работает: каждая модель видит документ по-своему. Одна ошибается в строке, другая — в таблице, третья — в цифрах. LLM берёт лучшее от каждой.
Промпт для мержа:`
Три OCR-модели распознали одно и то же изображение документа.
Сравни результаты и выведи ОДИН идеальный текст, исправляя ошибки каждой модели.
Правила:
Если модели согласны — оставляй как есть
Если расходятся — выбирай правильный вариант (сверяй по контексту)
Сохраняй структуру документа (таблицы, нумерацию)
`Результат: +5-10% точности к лучшей модели, но 20-30 секунд вместо 2-3. Ensemble включается только для сложных документов.
Математический контроль чеков
Распознать текст — полдела. Нужно ещё проверить, что цифры сходятся.
Российский чек (54-ФЗ) имеет строгую структуру:
`
Молоко 3.2% 89,90 × 2 = 179,80
Хлеб белый 54,00 × 1 = 54,00
ИТОГО: 233,80
``
Наша система:
Распознаёт позицию (название, цена, количество)
Вычисляет price × qty для каждой строки
Сверяет сумму строк с итоговой суммой
Показывает расхождения (если есть)
Почему это сложно: кассиры допускают ошибки, кассовые аппараты округляют по-разному, скидки и акции ломают простые формулы.
Реальные цифры
Вот что мы получили на наших данных:
80% документов — PaddleOCR справляется на первом слое (2-3 сек)
15% документов — Unlimited-OCR нужен для таблиц (15-25 сек)
5% документов — только VLM справляется (20-30 сек)
Ensemble — +5-10% точности к лучшей модели
Мат. контроль чеков — находит ошибки в 3-5% проверенных чеков
Ошибки, которые повторять не стоит
Датасет — в первую очередь. Мы начали с моделей, потом выяснили: русских документов для тестирования нет. Пришлось собирать вручную.
Tesseract — сразу в корзину. Потратили неделю на настройку, прежде чем поняли: он не подходит.
Ensemble — раньше. Тестировали модели по отдельности 2 месяца, прежде чем попробовали комбинировать.
Как попробовать
Если хотите протестировать наш OCR на своих документах — зарегистрируйтесь в TEOM. Бесплатно даём 20 OCR-обработок в месяц. Для разработчиков — API с тем же пайплайном.
Статья написана на основе реального опыта разработки OCR-пайплайна в TEOM|os. Все цифры получены на наших тестовых данных. Если у вас другие документы — результаты могут отличаться.