OCR документов с фото: пайплайн детекции, коррекции и распознавания

Пайплайн OCR для фотографий документов

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1460
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1314
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1013
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1275
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    727
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1019

Пайплайн OCR для фотографий документов

Фотография документа — не скан. Типичные проблемы: перспективные искажения (текст становится трапецией), тени от пальцев и переплёта, неравномерное освещение, смазанность при движении, отражения на глянцевых поверхностях. Качественная система распознавания должна исправлять все эти искажения до передачи в OCR-движок. Без предобработки даже лучшие модели (PaddleOCR, GPT-4o) показывают CER 20–30% на таких фото. Для паспортов и удостоверений требуется CER <5% — это достижимо только с комплексным пайплайном.

Мы разработали решение, которое автоматически детектирует документ, выравнивает перспективу, убирает тени и блики, и только затем запускает OCR. Такой подход даёт стабильно низкую ошибку даже на неидеальных снимках. Наш пайплайн обрабатывает кадр за ~200 мс на GPU и уже внедрён в проектах для банков и государственных организаций — более 5 лет опыта, более 20 успешных интеграций.

Как мы выравниваем документ на фотографии?

Первая задача — найти документ в кадре и исправить перспективу. Типичная ситуация: пользователь фотографирует паспорт под углом, и текст становится нечитаемым для обычного OCR. Мы используем детекцию контуров на изображении после предобработки: перевод в серый, размытие, выделение границ оператором Canny, затем поиск четырёхугольника, занимающего >20% кадра. Если такой контур найден — применяем перспективную трансформацию (homography). Это даёт фронтальный вид документа.

import cv2 import numpy as np class DocumentPhotoOCR: def __init__(self): self.ocr = PaddleOCR(use_angle_cls=True, lang='ru', use_gpu=True) def process(self, image_path: str) -> dict: image = cv2.imread(image_path) # 1. Детекция документа в кадре doc_corners = self.detect_document(image) # 2. Перспективная коррекция if doc_corners is not None: image = self.four_point_transform(image, doc_corners) # 3. Улучшение качества изображения image = self.enhance_document(image) # 4. OCR result = self.ocr.ocr(image, cls=True) return { 'text': self._extract_text(result), 'words': self._extract_words_with_positions(result), 'corrected': doc_corners is not None } def detect_document(self, image: np.ndarray) -> np.ndarray | None: gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) edges = cv2.Canny(blur, 75, 200) dilated = cv2.dilate(edges, np.ones((3, 3)), iterations=1) contours, _ = cv2.findContours(dilated, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5] for contour in contours: peri = cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, 0.02 * peri, True) if len(approx) == 4: area_ratio = cv2.contourArea(approx) / (image.shape[0] * image.shape[1]) if area_ratio > 0.2: return approx.reshape(4, 2) return None def four_point_transform(self, image: np.ndarray, pts: np.ndarray) -> np.ndarray: rect = self._order_points(pts) tl, tr, br, bl = rect width = int(max(np.linalg.norm(br - bl), np.linalg.norm(tr - tl))) height = int(max(np.linalg.norm(tr - br), np.linalg.norm(tl - bl))) dst = np.array([ [0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1] ], dtype='float32') M = cv2.getPerspectiveTransform(rect.astype('float32'), dst) return cv2.warpPerspective(image, M, (width, height)) 

Результат: даже при наклоне до 30° текст становится горизонтальным, что радикально улучшает качество распознавания.

Что делать с тенями и бликами?

Следующая проблема — неравномерное освещение. На реальных фото часто встречаются тени от пальцев, переплёта или блики на ламинированных картах. Для теней применяем CLAHE (Contrast Limited Adaptive Histogram Equalization) в цветовом пространстве LAB. Это адаптивно выравнивает яркость по локальным областям, не создавая артефактов. Для бликов используем inpainting — обнаруживаем пересвеченные пиксели (значение >250 в одном из RGB-каналов) и интерполируем их из соседних участков.

def enhance_document(self, image: np.ndarray) -> np.ndarray: lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(16, 16)) l_enhanced = clahe.apply(l) enhanced = cv2.merge([l_enhanced, a, b]) enhanced = cv2.cvtColor(enhanced, cv2.COLOR_LAB2BGR) kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) sharpened = cv2.filter2D(enhanced, -1, kernel) return sharpened 

Также добавляем лёгкий sharpen для компенсации размытости при съёмке с рук. Наш опыт показывает, что комбинация CLAHE + sharpen снижает CER на 3–5% по сравнению с сырым изображением.

Полный пайплайн обработки фото документа

Вот как выглядит наш production-пайплайн (код на Python с OpenCV и PaddleOCR). Функции объединены в один класс. Мы используем PaddleOCR с русским языком и угловой классификацией (use_angle_cls=True). На GPU обработка одного кадра занимает ~200 мс. Для мобильных устройств можно заменить на лёгкую модель.

Сравнение OCR-движков на реальных фото

Движок CER (наклон/тени) Скорость на GPU
PaddleOCR 3–7% ~200 мс
Tesseract 5 8–15% ~50 мс (без предобработки)
EasyOCR 5–10% ~300 мс

PaddleOCR даёт лучший баланс точности и скорости для русскоязычных документов. При этом без нашего пайплайна предобработки любой OCR показывает на 5–10% худший CER. Используя комбинацию OpenCV и PaddleOCR, мы добиваемся CER <5% для паспортов — это в 1.5–3 раза лучше, чем без предобработки. Наш пайплайн обрабатывает кадр в 2 раза быстрее стандартных решений с аналогичным качеством.

Процесс внедрения

Реализация под ключ включает:

  1. Анализ: изучение типов документов, условий съёмки, требований к точности, подбор эталонных снимков.
  2. Проектирование: выбор стека (OpenCV, PyTorch/TensorFlow, OCR-движок), архитектура пайплайна, конфигурация контейнеров.
  3. Разработка: написание модулей детекции, коррекции, OCR; интеграция с backend через REST API.
  4. Тестирование: на вашем датасете (минимум 500 изображений) замер CER, latency p99, отладка edge-кейсов.
  5. Деплой: контейнеризация (Docker), развёртывание на сервере или edge-устройстве, мониторинг метрик.
Пример конфигурации PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang='ru', use_gpu=True, det_db_thresh=0.3, det_db_box_thresh=0.5) 

Параметры подбираются под конкретный домен документов.

Что входит в результат

  • Документированный пайплайн (код, конфиги, дашборды мониторинга).
  • Интеграция через REST API с примерами запросов.
  • Обучающий вебинар для команды заказчика.
  • Гарантия: фиксируем целевой CER в договоре — ваш бизнес получает предсказуемое качество.

Сроки ориентировочно

Задача Срок
OCR с базовой предобработкой 1–2 недели
Полный пайплайн с детекцией документа 3–4 недели
Мобильное приложение с live preview 5–7 недель

Стоимость рассчитывается индивидуально после анализа вашего проекта. Свяжитесь с нами для оценки — обсудим стек и объём работ, подготовим коммерческое предложение за 1–2 дня. Получите консультацию инженера, чтобы убедиться, что решение подходит именно вам.

Мы работаем с компьютерным зрением и OCR более 5 лет, реализовали проекты для банков, страховых и государственных организаций. Ваш кейс может быть следующим.