EasyOCR распознаёт печатный текст на фотографиях, сканах и отдельных страницах документов, возвращая для каждого найденного фрагмента координаты рамки, расшифровку и оценку уверенности. Пользователь может выбрать русский и другие языки, ограничить допустимые символы, обработать повёрнутые надписи, объединить строки в абзацы, настроить чувствительность детектора и получить результат через Python-код или команду в терминале.
Рабочий процесс строится вокруг объекта Reader: сначала задаются языки и вычислительное устройство, затем модель один раз загружается в память, после чего метод readtext последовательно принимает изображения. В обычном режиме ответ представляет собой список троек из четырёхугольника, текста и вероятности; для простого извлечения строк достаточно отключить подробности, а для раздельной настройки этапов доступны методы detect и recognize.
У EasyOCR нет окон с панелями, мастером импорта и кнопкой сохранения: роль интерфейса выполняют аргументы функций, вывод ноутбука и параметры командной строки. Это даёт точный контроль над пакетной обработкой и интеграцией в собственные сценарии, но требует самостоятельно подготовить изображения, преобразовать страницы PDF в растровый вид, выбрать формат экспорта и проверить сомнительные фрагменты по показателю confidence.
Скачать EasyOCR
- Редактирование PDF
- Русский интерфейс
- Просто новичкам
- Нет графического интерфейса
- PDF требует растрирования
- Нужны отдельные модели
Как устроен рабочий процесс EasyOCR
Распознавание разделено на два логических этапа. Детектор сначала ищет области, похожие на строки или отдельные слова, и описывает их прямоугольными либо свободно ориентированными четырёхугольниками. Затем распознаватель вырезает найденные области, нормализует их высоту и переводит последовательность визуальных признаков в символы. Метод readtext скрывает эту связку за одним вызовом, поэтому для первого результата достаточно передать путь к изображению. Когда требуется контролировать области, повторно распознавать только часть страницы или менять порядок блоков, этапы вызывают отдельно через detect и recognize.
Создание Reader — самая дорогая подготовительная операция: она загружает детектор и языковую сеть в память. Объект следует создавать один раз на весь пакет файлов, а не внутри цикла по страницам. Иначе программа заново проверяет модели, выделяет память и увеличивает время обработки. В серверном процессе Reader обычно хранится рядом с очередью заданий; в ноутбуке его оставляют в отдельной ячейке и повторно запускают только после изменения списка языков, вычислительного устройства или типа сети.
Минимальный сценарий состоит из трёх строк: импорт модуля, создание Reader и вызов readtext. В список языков передаются коды, а не полные названия. Для русского используется ru; английский можно добавить как en, если на изображениях встречаются адреса сайтов, артикулы, латинские фамилии или маркировка оборудования. Английская модель совместима с другими языками, однако произвольный набор письменностей собрать нельзя: несовместимая комбинация завершается сообщением о том, что выбранные языки не поддерживаются вместе.
import easyocr
reader = easyocr.Reader(['ru', 'en'], gpu=False)
result = reader.readtext('scan.png')
for box, text, confidence in result:
print(confidence, text, box)

В примере gpu=False принудительно выбирает процессор. Без этого параметра EasyOCR пытается использовать доступное ускорение PyTorch и при его отсутствии сообщает о переходе на CPU. Само предупреждение не означает ошибку: распознавание продолжится, но крупные изображения и длинные серии страниц обрабатываются медленнее. Для воспроизводимого пакетного процесса лучше задавать режим явно, чтобы запуск на другом компьютере не изменил потребление памяти и время выполнения неожиданным образом.
Установка и проверка окружения
Надёжнее всего выполнять установку в отдельном виртуальном окружении Python. Это изолирует версии PyTorch, OpenCV, Pillow и NumPy от других проектов. После активации окружения ставят PyTorch, соответствующий операционной системе и выбранному типу ускорения, а затем EasyOCR. На Windows особенно важно не смешивать сборку PyTorch для одной версии CUDA с драйвером и библиотеками другой версии; для обработки только на процессоре выбирают CPU-вариант PyTorch.
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux и macOS
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install easyocr
После установки сначала проверяют импорт и создание Reader на одной небольшой картинке. Такой тест отделяет проблемы окружения от ошибок в собственном конвейере. Команда python -m pip show easyocr показывает путь, из которого загружается пакет; это полезно, когда в системе несколько интерпретаторов и терминал запускает не то окружение. Вывод python -c с импортом torch помогает увидеть версию PyTorch и доступность CUDA до загрузки моделей OCR.
python -c "import easyocr, torch; print(easyocr.__version__); print(torch.cuda.is_available())"

В состав зависимостей входят torch, torchvision, opencv-python-headless, scipy, numpy, Pillow, scikit-image, python-bidi, PyYAML, Shapely, pyclipper и ninja. Поэтому небольшой wheel EasyOCR не отражает общий объём установки: основную часть занимают PyTorch и веса распознавания. При нехватке места нужно учитывать кэш менеджера пакетов, каталог виртуального окружения и папку моделей. После успешной установки кэш pip можно очистить, но модельные файлы удалять нельзя, если распознавание должно работать без повторного скачивания.
Ошибка No matching distribution found for torch обычно относится не к EasyOCR, а к сочетанию версии Python, архитектуры и доступных сборок PyTorch. Решение начинают с проверки разрядности интерпретатора и таблицы совместимости PyTorch, затем создают новое окружение с поддерживаемой версией Python. Попытка принудительно установить случайный старый NumPy редко исправляет причину и может породить конфликт ABI с OpenCV или scikit-image.
Модели, каталоги и первый запуск
При первом создании Reader программа проверяет наличие детектора и распознавателя для выбранной письменности. Если файлов нет и download_enabled оставлен включённым, они скачиваются автоматически. Прогресс может занимать заметное время, а после завершения веса читаются с диска и размещаются в памяти. Для последующих запусков сеть берётся из кэша, поэтому повторное скачивание указывает на изменение каталога пользователя, контейнера, переменной окружения или прав доступа.
Путь к моделям можно задать через model_storage_directory. Это предпочтительно для серверов, контейнеров и общих рабочих станций, где домашняя папка временная либо недоступна сервисной учётной записи. При отсутствии явного пути EasyOCR ищет данные с учётом EASYOCR_MODULE_PATH, затем MODULE_PATH и стандартного каталога .EasyOCR в домашней директории. В управляемой среде следует выбрать один каталог, выдать процессу права на чтение и не позволять нескольким экземплярам одновременно распаковывать один и тот же файл.
reader = easyocr.Reader(
['ru', 'en'],
gpu=False,
model_storage_directory='models/easyocr',
download_enabled=False
)
Параметр download_enabled=False полезен после предварительной подготовки автономного узла. Если нужного файла нет, программа завершится ошибкой вместо попытки выйти в сеть. Перед переносом проверяют не только распознаватель, но и модель детекции. Для русского набора используется сеть кириллического письма; одного английского файла недостаточно. Контрольная проверка должна создавать Reader именно с тем списком языков, который будет применяться в эксплуатации.
Если загрузка обрывается, удаляют только недокачанный или повреждённый файл, а не весь каталог. Затем повторяют запуск при стабильном соединении либо скачивают веса вручную из официального Model Hub и помещают их в подпапку model. Бесконечное повторение прогресса часто связано с тем, что процесс каждый раз запускается в новом контейнере без постоянного тома. В таком случае каталог моделей монтируют отдельно и проверяют, что пользователь внутри контейнера может создавать и читать файлы.
Какие изображения принимает readtext
Входом может быть путь к файлу, байтовая строка, массив NumPy или объект изображения, преобразованный в массив. Это позволяет читать файлы с диска, результаты загрузки из базы данных, кадры OpenCV и изображения, уже прошедшие предварительную обработку. Для массива важны порядок каналов и тип данных. OpenCV обычно использует BGR, а многие библиотеки визуализации — RGB; неправильная перестановка цветов не всегда приводит к исключению, но может ухудшить контраст и распознавание цветного текста.
Поддержка конкретного файлового контейнера фактически зависит от библиотек декодирования. Надёжными входами служат PNG и JPEG; TIFF, WebP и другие варианты следует проверять на целевой сборке Pillow или OpenCV. Многостраничный TIFF нельзя считать одной страницей автоматически: кадры нужно извлечь по отдельности. PDF также не передаётся напрямую в readtext как документ — каждую страницу требуется визуализировать в растровое изображение с подходящим разрешением.
Перед распознаванием проверяют, что изображение действительно прочитано. cv2.imread при ошибке пути возвращает None, а дальнейшая обработка может дать неочевидное исключение. У путей с нелатинскими символами на старых сборках OpenCV бывают проблемы; устойчивый обходной путь — прочитать файл как bytes и декодировать через cv2.imdecode либо Pillow. Для сервисного конвейера полезно отдельно журналировать имя, размер, число каналов и результат декодирования до вызова EasyOCR.
from pathlib import Path
import cv2
import numpy as np
data = np.frombuffer(Path('скан.png').read_bytes(), dtype=np.uint8)
image = cv2.imdecode(data, cv2.IMREAD_COLOR)
if image is None:
raise ValueError('Изображение не декодировано')
result = reader.readtext(image)
Массивы серого, трёхканального BGR и четырёхканального RGBA приводятся к рабочему виду внутри подготовки входа. Однако альфа-канал с прозрачным фоном может скрывать светлый текст после неудачной композиции. Для таких PNG лучше заранее наложить изображение на белый или другой ожидаемый фон. Снимки с очень высокой разрядностью также переводят в диапазон 0–255, иначе пороги детектора не соответствуют фактической яркости.
Подготовка сканов и страниц PDF
Качество результата сильнее всего зависит от того, сколько пикселей приходится на высоту символа. Слишком низкое разрешение стирает перемычки и точки, а чрезмерное увеличивает расход памяти без гарантии лучшей точности. Для обычного печатного документа разумно начать с визуализации страницы около 250–300 dpi, затем оценить мелкий шрифт. Если буквы имеют высоту меньше примерно десяти пикселей, их легко отфильтрует min_size и распознаватель увидит недостаточно деталей.
При преобразовании PDF важно не делать повторную JPEG-компрессию. Страница сначала рендерится в массив или PNG, затем передаётся Reader. Если в PDF уже есть текстовый слой, OCR может быть избыточен: сначала стоит извлечь существующий текст и применять распознавание только к страницам без него. EasyOCR не создаёт новый PDF со скрытым слоем, закладками и сохранённой геометрией; такую сборку выполняет отдельная библиотека на основании координат полученных рамок.
import fitz # PyMuPDF
import numpy as np
from PIL import Image
doc = fitz.open('document.pdf')
for page_no, page in enumerate(doc):
pix = page.get_pixmap(dpi=300, alpha=False)
image = Image.frombytes('RGB', [pix.width, pix.height], pix.samples)
result = reader.readtext(np.array(image), detail=1)
print(page_no + 1, result)
Косой скан лучше выровнять до OCR, особенно если наклон одинаков для всей страницы. rotation_info предназначен для поворота отдельных найденных фрагментов на 90, 180 или 270 градусов, а не для коррекции произвольного угла листа. Для наклона на несколько градусов применяют deskew по линиям текста или границам страницы. После выравнивания не следует обрезать край слишком плотно: детектору нужен небольшой фон вокруг букв, а параметр add_margin расширяет уже найденные области, но не возвращает пиксели, потерянные при кадрировании.
Шумы, тени от сгиба и просвечивающий оборот требуют осторожной подготовки. Жёсткая бинаризация может удалить тонкие штрихи кириллицы и знаки пунктуации. Обычно сравнивают исходное цветное изображение, серую копию с нормализацией контраста и мягко очищенный вариант. Побеждает не тот вариант, который выглядит контрастнее человеку, а тот, на котором выше полнота детекции и меньше ложных рамок. Полезно сохранять контрольные страницы и измерять число пропусков на одинаковом наборе, а не менять фильтры по одному удачному примеру.
Формат результата и координаты
При detail=1 каждый элемент содержит четырёхугольник, распознанную строку и confidence. Координаты идут по вершинам области и позволяют нарисовать контур, обрезать фрагмент или привязать текст к полю формы. Число confidence лежит около диапазона от нуля до единицы, но не является гарантированной вероятностью ошибки в статистическом смысле. Порог следует калибровать на собственных документах: значение 0,6 для крупного заголовка и 0,6 для мелкого артикула могут означать разные риски.
Для простого списка строк задают detail=0. Такой ответ удобен для быстрого поиска ключевых слов, но теряет положение и уверенность. Если далее нужно восстановить колонки, подсветить сомнительные места или провести ручную проверку, отключать детали не стоит. Более структурированный вывод можно запросить как словари или JSON в тех интерфейсах, где поддерживается output_format; при самостоятельной сериализации координаты NumPy необходимо преобразовать в обычные целые или вещественные числа.
records = []
for box, text, confidence in result:
records.append({
'box': [[int(x), int(y)] for x, y in box],
'text': text,
'confidence': float(confidence)
})

Порядок элементов приблизительно следует расположению текста, но сложная верстка не превращается автоматически в правильный порядок чтения. На двух колонках соседние строки могут чередоваться, подпись под рисунком попасть между абзацами, а боковая надпись — в середину списка. Для документов с колонками координаты группируют по диапазонам x, затем сортируют внутри колонки по y. Таблицы требуют отдельного анализа линий или сетки: EasyOCR сообщает текстовые области, но не строит строки, столбцы и объединённые ячейки.
Для визуальной проверки удобно рисовать четырёхугольники поверх копии изображения и подписывать confidence. Это позволяет отличить ошибку детекции от ошибки распознавания. Если нужная строка не обведена, меняют масштаб, пороги и подготовку. Если рамка есть, но текст неверен, проверяют язык, allowlist, контраст и декодер. Такая диагностика быстрее, чем одновременно менять все параметры readtext.
Языки и сочетания письменностей
Список lang_list определяет набор символов и словарь, доступные распознавателю. Для русскоязычного документа обычно используют ['ru'] или ['ru', 'en']. Добавление ненужных языков не повышает универсальность безусловно: похожие символы получают больше конкурентов, модель занимает больше памяти, а несовместимая письменность вообще не загрузится. Состав выбирают по реальному документу, а не по всем языкам, которые теоретически могут встретиться в архиве.
Русские буквы и латиница визуально пересекаются: А, В, Е, К, М, Н, О, Р, С, Т, Х похожи на латинские символы. Поэтому в кодах товаров, доменах и фамилиях возможно смешение алфавитов. После OCR такие поля проверяют правилами предметной области: российский номер документа, артикул или адрес электронной почты имеют известный набор допустимых знаков. Приведение похожих символов без контекста опасно, поскольку можно испортить корректное слово.
Для документа, где на разных страницах используются разные письменности, эффективнее держать несколько Reader и выбирать нужный по метаданным или быстрой классификации страницы. Один объект для русского и английского, другой — для японского и английского, третий — для арабского и английского. Это предсказуемее, чем пытаться создать один невозможный набор. Объекты занимают память, поэтому на слабой машине их загружают последовательно или распределяют по рабочим процессам.

Направление письма учитывается в обработке языков справа налево, а для арабского результата применяется перестановка отображения. Тем не менее смешанные числа, латинские обозначения и знаки пунктуации нужно тестировать отдельно. Отображение строки в консоли может отличаться от фактического порядка Unicode из-за bidi-поддержки терминала. Проверку лучше проводить в редакторе или интерфейсе, который корректно показывает двунаправленный текст.
Ограничение алфавита через allowlist и blocklist
allowlist заставляет распознаватель выбирать только из указанного набора символов. Параметр особенно полезен для серийных номеров, цен, дат, телефонных кодов, показаний счётчиков и номерных знаков. Он не улучшает детекцию: если область не найдена, ограничение алфавита не поможет. Зато после корректного выделения рамки оно снижает путаницу между O и 0, I и 1, B и 8, кириллическими и латинскими аналогами.
digits = reader.readtext(
'meter.jpg',
allowlist='0123456789.,',
detail=1
)
Набор должен включать все допустимые разделители. Если в цене возможны пробел, запятая, точка и знак валюты, их добавляют осознанно либо распознают число без валюты в заранее обрезанной области. Слишком узкий allowlist может превратить буквы в похожие цифры и создать правдоподобную, но ложную строку. Поэтому поле сначала локализуют по шаблону документа, а затем проверяют длину, контрольную сумму, диапазон и соседнюю подпись.
blocklist действует наоборот: исключает символы, но игнорируется, если одновременно задан allowlist. Он подходит, когда нужно запретить несколько знаков, сохранив широкий алфавит. Для критичных идентификаторов белый список обычно безопаснее, поскольку явно описывает допустимое множество. Параметры применяют на уровне вызова recognize или readtext, поэтому один Reader можно использовать для обычного текста и отдельных цифровых зон без повторной загрузки модели.
Поворот и вертикальные надписи
rotation_info принимает список углов, которыми программа дополнительно поворачивает каждый найденный текстовый фрагмент и выбирает лучший вариант. Типичный набор [90, 180, 270] помогает при перевёрнутых этикетках, боковых подписях и фотографиях, где часть объектов ориентирована иначе. Цена — несколько проходов распознавания для каждой рамки, поэтому включать все углы на обычных прямых документах невыгодно.
result = reader.readtext(
'labels.jpg',
rotation_info=[90, 180, 270],
detail=1
)
Если вся страница лежит боком, быстрее повернуть изображение один раз до detect. rotation_info полезен именно для смешанной ориентации, когда общий поворот не решает задачу. Вертикальный текст и сильно вытянутые области могут потребовать изменения параметров объединения, поскольку соседние символы детектор разделяет не так, как горизонтальную строку. Результат проверяют по контурам: слишком большая рамка может включить несколько вертикальных подписей, а слишком маленькие рамки разорвут слово на символы.
Поворот на 180 градусов иногда даёт высокий confidence для неверной короткой строки. Поэтому при выборе ориентации для кодов полезно учитывать словарь или формат поля, а не только уверенность модели. Для длинной фразы можно сравнивать долю допустимых символов, число словарных слов и геометрию. В производственном конвейере сохраняют выбранный угол вместе с результатом, чтобы спорный случай можно было воспроизвести.
Контраст и повторное распознавание
Параметры contrast_ths и adjust_contrast управляют повторной обработкой низкоконтрастных областей. Если контраст фрагмента ниже порога, EasyOCR распознаёт исходный и скорректированный вариант, затем сохраняет результат с большей уверенностью. Это полезно для серого текста, выцветших чеков и маркировки на металле, но увеличивает работу распознавателя. На чистых документах агрессивное повышение контраста иногда подчёркивает шум сильнее букв.
Начальные значения лучше менять постепенно. Если рамка найдена, а бледная строка распознаётся плохо, увеличивают целевой контраст и сравнивают текст на контрольном наборе. Если рамки нет, параметры контраста распознавания не решат проблему — сначала корректируют вход, mag_ratio или пороги детектора. Разделение этих случаев предотвращает бесконечный подбор несвязанных настроек.
result = reader.readtext(
'faded_receipt.png',
contrast_ths=0.15,
adjust_contrast=0.7
)
Для чеков с неравномерным фоном полезно вырезать область бумаги и компенсировать освещение до OCR. Глобальное осветление всей фотографии может уничтожить светлую печать на одном участке и оставить тень на другом. Адаптивная нормализация работает лучше, но требует контроля, чтобы не превратить текстуру бумаги в ложные штрихи. Удачный фильтр оценивают одновременно по полноте рамок, правильности символов и числу мусорных фрагментов.
Параметры детектора CRAFT
text_threshold определяет, насколько уверенной должна быть область текста, low_text задаёт нижнюю границу слабых пикселей, а link_threshold влияет на связывание символов в общую область. Снижение порогов повышает полноту, но добавляет рамки вокруг фактуры, линий и мелких деталей. Повышение очищает вывод, однако может пропустить бледные или маленькие надписи. Параметры рассматривают вместе и тестируют на репрезентативных страницах.
canvas_size ограничивает размер, до которого подготавливается изображение для детекции. Очень крупная страница уменьшается, и мелкий текст теряет детали. mag_ratio масштабирует вход перед ограничением canvas_size. Для мелких надписей можно увеличить mag_ratio, одновременно подняв canvas_size при достаточной памяти. Простое увеличение одного параметра не гарантирует эффект, если затем изображение снова ограничивается максимальным холстом.
result = reader.readtext(
'small_labels.png',
text_threshold=0.65,
low_text=0.3,
link_threshold=0.35,
canvas_size=3200,
mag_ratio=1.4
)
min_size фильтрует найденные области по размеру. На странице с номерами сносок, индексами и мелкими подписями слишком большое значение удалит нужный текст. На фотографии с множеством случайных деталей увеличение min_size может заметно сократить шум. Единица измерения связана с пикселями подготовленного изображения, поэтому одинаковое значение ведёт себя по-разному при разных dpi и масштабе.
Для диагностики сначала вызывают detect и визуализируют horizontal_list и free_list. Если целевая надпись входит в рамку вместе с соседней, регулируют связывание и параметры объединения. Если она разделена на слишком много областей, небольшое снижение link_threshold или изменение масштаба может помочь. Менять распознаватель до получения правильных рамок бессмысленно: он работает только с теми фрагментами, которые ему передал детектор.
Объединение рамок и режим paragraph
После детекции EasyOCR группирует близкие прямоугольники. slope_ths ограничивает допустимый наклон между соседями, ycenter_ths — смещение центров по вертикали, height_ths — различие высоты, width_ths — горизонтальный разрыв. Эти параметры выражаются относительно высоты рамки, кроме порога наклона. Они особенно заметны на документах с разреженными буквами, ценниками, вывесками и строками, где слова расположены далеко друг от друга.
paragraph=True дополнительно объединяет фрагменты в более длинные текстовые блоки. x_ths и y_ths задают расстояния для такого объединения. Режим удобен для сплошного текста, но может склеить соседние колонки, подпись и основной абзац либо значения из разных ячеек. В табличных документах безопаснее оставить отдельные элементы и построить строки по координатам самостоятельно.
result = reader.readtext(
'page.png',
paragraph=True,
x_ths=0.8,
y_ths=0.4
)
В paragraph-режиме структура ответа отличается от обычной, а показатель уверенности может быть недоступен для объединённого блока. Если контроль качества опирается на confidence отдельных слов, сначала получают detail=1 без объединения, фильтруют и проверяют фрагменты, затем собирают абзацы собственным алгоритмом. Это также позволяет сохранить связь между итоговой строкой и исходными рамками.
add_margin расширяет область вокруг текста перед распознаванием. Небольшой запас помогает, когда детектор обрезал диакритику, верх кириллической буквы или элементы сложной письменности. Слишком большой запас захватывает соседние строки и линии таблицы. Параметр полезно увеличивать точечно для набора проблемных изображений, а не применять максимальное значение ко всем страницам.
Декодеры и beamWidth
decoder=greedy выбирает наиболее вероятный символ на каждом шаге и работает быстрее. beamsearch рассматривает несколько последовательностей, а beamWidth определяет число сохраняемых вариантов. wordbeamsearch дополнительно использует словарные ограничения там, где они поддерживаются. Для обычных хорошо напечатанных строк greedy часто достаточен; более сложный декодер оправдан, если он стабильно исправляет ошибки на нужном языке и задержка приемлема.
Увеличение beamWidth не превращает неразборчивый фрагмент в надёжный текст. Оно повышает вычислительную цену и может выбрать словарно правдоподобное, но фактически неверное слово. Для артикулов, имён собственных и смешанных кодов словарная коррекция бывает вредной, поэтому там лучше greedy вместе с allowlist и предметной проверкой. Для связного печатного текста можно сравнить декодеры по CER или числу ручных исправлений.
greedy = reader.readtext('line.png', decoder='greedy')
beam = reader.readtext('line.png', decoder='beamsearch', beamWidth=10)
Сравнение проводят на одинаковых вырезках и не ограничиваются средней уверенностью. Полезно подсчитать ошибки символов, пропуски слов и время на страницу. Если beamsearch улучшает только редкие случаи, можно сначала обрабатывать всё быстрым способом, а затем повторно распознавать фрагменты с низкой уверенностью более дорогим декодером. Такой двухступенчатый конвейер экономит время и сохраняет возможность проверки.
Командная строка EasyOCR
После установки создаётся команда easyocr. Она позволяет быстро проверить файл без написания отдельного скрипта и подходит для простых пакетных оболочек. Обязательны список языков и путь к изображению; остальные параметры повторяют основные аргументы readtext. Результат печатается в стандартный вывод, поэтому его можно перенаправить в файл, но для надёжного JSON и обработки ошибок удобнее использовать Python API.
easyocr -l ru en -f scan.png --detail=1 --gpu=False

В консольном выводе видны координаты, текст и уверенность. При первом запуске туда же попадает прогресс загрузки модели, поэтому слепое перенаправление всего stdout может смешать служебные сообщения с данными. Перед автоматизацией проверяют доступный формат вывода, кодировку терминала и код возврата. На Windows для кириллицы может потребоваться терминал с UTF-8; при записи из Python проще открыть файл с encoding='utf-8'.
Командная строка хороша для единичной диагностики, но при сотнях файлов отдельный запуск процесса на каждый снимок повторяет инициализацию. Эффективнее один Python-процесс, один Reader и цикл по путям. Shell-скрипт можно оставить внешней оболочкой, которая передаёт список заданий единому обработчику. Так модели остаются в памяти, а журнал содержит однозначную запись по каждому файлу.
Пакетная обработка и readtext_batched
Для серии страниц основной выигрыш даёт повторное использование Reader. batch_size внутри распознавания увеличивает число фрагментов, обрабатываемых одновременно, и может ускорить GPU, но требует больше видеопамяти. workers задаёт число потоков загрузчика данных. На Windows и в ноутбуках значение больше нуля иногда усложняет запуск дочерних процессов; начинать безопаснее с workers=0 и повышать после измерений.
readtext_batched принимает несколько изображений, однако они должны иметь одинаковые размеры либо быть приведены к общей форме. Это ограничение важно для страниц разных форматов и фотографий с камер. Простое растягивание искажает символы; лучше дополнить изображения полями до общей ширины и высоты либо группировать по близким размерам. Координаты результата затем переводят обратно с учётом добавленных полей и масштаба.
Для больших архивов строят очередь: чтение и рендеринг PDF выполняются отдельно, OCR получает готовые массивы, а запись результата не блокирует GPU. Размер очереди ограничивают, иначе десятки полноразмерных страниц одновременно займут оперативную память. Если процесс падает на одном файле, журнал должен хранить его идентификатор и продолжать со следующего задания, а не терять весь пакет.
from pathlib import Path
for path in sorted(Path('pages').glob('*.png')):
try:
rows = reader.readtext(str(path), batch_size=4, workers=0)
save_result(path, rows)
except Exception as exc:
log_error(path, exc)
Скорость измеряют после прогрева: первый вызов включает загрузку и инициализацию, поэтому не отражает обычную производительность. Отдельно фиксируют время детекции, распознавания и подготовки страницы. Если узкое место — рендеринг PDF, увеличение batch_size не поможет; если детектор перегружен огромным холстом, следует пересмотреть dpi и canvas_size. Оптимизация начинается с профиля, а не с максимальных значений всех параметров.
Использование GPU и контроль памяти
Параметр gpu может быть логическим значением или указанием устройства, поддерживаемым реализацией. На CUDA-совместимой системе PyTorch должен видеть видеокарту до запуска EasyOCR. Проверка torch.cuda.is_available() и имени устройства позволяет отличить проблему драйвера от настроек OCR. Сообщение о переходе на CPU допустимо для теста, но в производстве его лучше считать изменением режима и записывать в журнал.
Нехватка видеопамяти обычно проявляется на больших страницах, высоком batch_size или при нескольких Reader в одном процессе. Сначала уменьшают batch_size до 1, затем canvas_size и число одновременно загруженных моделей. После исключения в интерактивном ноутбуке память может оставаться занятой ссылками на старые объекты; надёжнее перезапустить ядро, чем многократно создавать Reader и рассчитывать на немедленное освобождение.
CPU-режим обеспечивает одинаковую функциональность, но динамическая квантизация и особенности инструкций процессора могут влиять на скорость. Ошибка illegal instruction указывает на несовместимость бинарной зависимости с доступным набором инструкций, особенно в старой виртуальной машине. Решение — использовать подходящую сборку PyTorch или NumPy для процессора, а не менять пороги OCR. В контейнере также проверяют, какие инструкции фактически предоставляет гипервизор.
Для долгоживущего сервиса полезно ограничивать размер входа до загрузки на GPU. Злоумышленник или повреждённый файл с гигантскими размерами способен вызвать чрезмерное выделение памяти. Проверяют ширину, высоту, число пикселей и фактический формат, затем делают контролируемое уменьшение. Это не только защита, но и способ сохранить стабильную задержку.
Экспорт в TXT, JSON и таблицы
EasyOCR возвращает данные в память и не определяет готовую структуру проекта. Для TXT решают, как восстановить порядок строк и разделять страницы. Для JSON сохраняют исходный файл, номер страницы, координаты, текст, confidence, языковой набор и параметры запуска. Такой протокол позволяет повторно проверить отдельный фрагмент без полного повторения всего архива.
CSV подходит для плоского списка областей: одна строка на рамку, отдельные столбцы x1–y4, текст и уверенность. Переносы строк в распознанном тексте и разделители нужно экранировать стандартным модулем csv, а не собирать строку вручную. Для таблицы документа CSV не возникает автоматически: сначала требуется определить принадлежность рамок к строкам и колонкам.
import csv
with open('result.csv', 'w', newline='', encoding='utf-8-sig') as f:
w = csv.writer(f, delimiter=';')
w.writerow(['page', 'text', 'confidence', 'box'])
for page_no, rows in all_pages:
for box, text, confidence in rows:
w.writerow([page_no, text, float(confidence), box])
При построении поискового индекса полезно хранить и нормализованную, и исходную строку. Нормализованная версия может быть приведена к нижнему регистру, очищена от лишних пробелов и унифицирована по Unicode, но оригинал нужен для показа пользователю. Исправления похожих символов также записывают отдельно, чтобы было видно, что изменил OCR, а что — постобработка.
Если задача — создать searchable PDF, координаты EasyOCR переводят из пикселей изображения в координаты PDF с учётом dpi, масштаба и поворота. Текстовый слой размещают невидимо поверх соответствующих областей. Ошибка коэффициента приведёт к тому, что выделение мышью не совпадёт с изображением. Для сложных четырёхугольников и повёрнутых строк требуется учитывать матрицу преобразования, а не только левый верхний угол.
Русские документы: практические настройки
Для обычной страницы на русском начинают с Reader(['ru', 'en']) и параметров по умолчанию. Затем визуально проверяют рамки и отдельно собирают типичные ошибки: смешение кириллицы с латиницей, пропуск Ё, путаницу З и 3, Ч и 4, О и 0, разрыв слов через дефис. Изменять модельные параметры стоит только после того, как вход имеет достаточное разрешение и корректную ориентацию.
В договорах и письмах порядок чтения часто восстанавливается по строкам: рамки группируют, если их центры y близки относительно высоты текста, затем сортируют по x. Шапку, таблицу реквизитов и подписи обрабатывают отдельными зонами, потому что единое правило порядка редко подходит всей странице. Зоны можно задавать шаблоном для стандартной формы или находить по ключевым словам и геометрии.
Для паспортных и финансовых полей нельзя автоматически принимать строку только из-за высокого confidence. Применяют маску, длину, дату, диапазон, контрольную сумму и согласованность с соседними подписями. Фрагменты ниже выбранного порога отправляют на ручную проверку вместе с вырезкой. При этом порог калибруют отдельно для печатного текста и фотографии документа, а не назначают универсальное число.
Рукописные пометки не следует смешивать с печатным слоем без проверки. Модель ориентирована на печатные и сценовые надписи; курсивные подписи, заполненные от руки поля и сложные штампы дают нестабильный результат. Их можно детектировать как области, но распознавание требует отдельного решения либо ручного ввода. В отчёте такие зоны маркируют как непроверенные, а не подставляют случайную строку в реквизит.
Надписи на фотографиях, вывесках и упаковке
Сценовый текст отличается перспективой, бликами, сложным фоном и разным масштабом. EasyOCR полезен тем, что детектор ищет произвольно ориентированные четырёхугольники, а не только прямые строки документа. Однако результат зависит от того, занимает ли надпись достаточно пикселей. Перед OCR фотографию иногда разумно разрезать на области интереса, чтобы мелкая этикетка не терялась на огромном кадре.

На упаковке сначала находят плоскость этикетки и выправляют перспективу. Затем отдельно распознают название, состав, дату и код партии с разными allowlist. Блики можно уменьшить выбором другого кадра; программное затемнение пересвеченного участка не возвращает потерянные штрихи. Для видеопотока полезно объединять результаты нескольких кадров и принимать символ, который стабильно повторяется в одном месте.
Вывески с декоративным шрифтом, контурными буквами и неоном могут давать несколько вложенных рамок. Повышение text_threshold сокращает ложные срабатывания, но рискует убрать тонкие символы. Иногда лучше маскировать фон по цвету или выделять ожидаемую область. При сравнении параметров сохраняют исходный кадр и визуализацию рамок, иначе невозможно понять, действительно ли улучшилась детекция или просто исчезли сложные надписи.
Номерные знаки — хороший пример узкого конвейера: сначала внешний детектор находит знак, затем изображение выравнивается, а EasyOCR читает небольшой crop с allowlist из разрешённых букв и цифр. Применять readtext ко всему кадру дороги менее эффективно: реклама, дорожные знаки и кузов создают лишние области. Confidence дополняют правилами формата номера и согласованием между кадрами.

Формы, счета и таблицы
EasyOCR извлекает текстовые области, но не понимает семантику формы. Чтобы получить поле Итого, находят подпись, затем ищут ближайшую рамку справа или снизу в допустимой зоне. Для стабильного шаблона координаты задают относительно размера страницы; для разных макетов используют классификацию документа и отдельные правила. Значение проверяют по типу: сумма должна разбираться как число, дата — как календарная дата, ИНН — проходить контроль.
В таблице линии могут мешать детектору или объединять соседние ячейки. Сетку находят средствами обработки изображений, вычисляют границы ячеек и распознают каждый crop отдельно. Такой подход сохраняет структуру и позволяет применять разные списки символов по колонкам. Если сначала запустить paragraph=True на всей таблице, значения разных столбцов могут склеиться в длинную строку.
Многострочная ячейка требует сохранить локальный порядок элементов. Координаты переводят в систему ячейки, группируют по строкам, а затем соединяют пробелами или переносами. Пустая ячейка должна оставаться пустой, а не исчезать из массива и сдвигать столбцы. Поэтому структура создаётся из геометрии сетки, а OCR только заполняет известные позиции.
Печати и подписи часто перекрывают печатный текст. Цветовое разделение синего штампа и чёрного текста иногда помогает, но оно зависит от сканера. Для юридически значимых данных автоматический результат должен сопровождаться изображением области и статусом проверки. Высокая уверенность на частично закрытой строке не гарантирует, что модель восстановила именно исходные символы.
Раздельные методы detect и recognize
detect возвращает horizontal_list и free_list. Первый список описывает горизонтальные прямоугольники как границы x и y, второй — произвольные четырёхугольники. Этот метод применяют, когда нужно увидеть геометрию без распознавания, выбрать области по размеру или положению, либо использовать другой алгоритм для чтения отдельных зон. Параметр optimal_num_chars может выводить вперёд рамки, близкие к ожидаемому числу символов.
horizontal_list, free_list = reader.detect('page.png')
print(horizontal_list[0])
print(free_list[0])
recognize принимает изображение и готовые списки рамок. Если рамки не переданы, всё изображение рассматривается как одна область текста. Это удобно для заранее вырезанной строки или ячейки: детектор не нужен, а распознавание выполняется непосредственно. Reader можно создать с detector=False, если вход всегда состоит из подготовленных текстовых строк; аналогично recognizer=False оставляет только детекцию.
recognizer = easyocr.Reader(['ru'], detector=False, gpu=False)
text = recognizer.recognize('single_line.png', detail=1)
Разделение сокращает лишнюю работу в многоэтапной системе. Например, общий детектор один раз находит поля, после чего разные crop распознаются с цифровым allowlist или полным алфавитом. Оно также упрощает отладку: сохранённые рамки можно повторно прогнать с другим декодером без повторной детекции. Формат координат и масштаб изображения должны оставаться согласованными.
Альтернативный детектор DBNet
EasyOCR поддерживает выбор сети детекции через detect_network. Помимо стандартного CRAFT предусмотрен dbnet18. Переключение влияет только на поиск областей, а язык распознавания и формат результата сохраняются. Альтернативу имеет смысл сравнивать на конкретном наборе: плотный документ, изогнутые вывески и мелкие этикетки могут по-разному реагировать на архитектуру.
reader = easyocr.Reader(
['ru', 'en'],
detect_network='dbnet18',
gpu=True
)
Модель DBNet требует отдельного файла, поэтому первый запуск может инициировать загрузку. При автономной подготовке этот файл включают в каталог моделей наряду с распознавателем. Отдельные сочетания DBNet, Windows и режима устройства могут иметь ограничения, поэтому выбранную конфигурацию необходимо проверить именно на целевой машине. Если конвейер построен вокруг параметров CRAFT, их перенос на DBNet без проверки некорректен.
Сравнивают полноту рамок, число ложных областей, время и устойчивость к масштабу. Один детектор может лучше находить мелкий текст, но хуже разделять соседние строки. В отчёте сохраняют версию параметров и сеть, чтобы повторный запуск давал сопоставимый результат. Для смешанного архива допустимо выбирать детектор по типу документа, но это усложняет эксплуатацию и требует отдельной калибровки.
Собственная модель распознавания
Параметры user_network_directory и recog_network позволяют подключить пользовательскую сеть распознавания. Это нужно для специализированного алфавита, необычного шрифта или области, где стандартная модель систематически ошибается. Пользовательская модель включает конфигурацию, набор символов и файл весов с согласованными именами. Просто положить произвольный файл PyTorch в каталог недостаточно.
Подготовка начинается с набора размеченных строк, а не целых страниц. Данные должны отражать реальные шрифты, фон, масштаб, шум и искажения. Синтетические строки полезны для покрытия символов, но не заменяют примеры с целевой камеры или сканера. Набор делят на обучение, проверку и независимый тест; иначе улучшение может быть результатом запоминания.
После обучения модель проверяют не только по средней точности, но и по критичным символам. Для артикула ошибка одной цифры важнее небольшого улучшения длинного текста. Сравнение выполняют со стандартной сетью на одном тесте, измеряют скорость и размер. Пользовательскую модель развёртывают с фиксированной конфигурацией и контрольной суммой, чтобы обновление не происходило незаметно.
Если задача решается allowlist, геометрическим crop и постпроверкой, обучение может быть избыточным. Оно оправдано, когда ошибки устойчиво связаны с визуальным доменом и остаются после подготовки входа. Для единичных рукописных полей стандартный тренировочный процесс печатного распознавателя также не гарантирует нужного результата.
Контроль качества и пороги уверенности
Порог confidence выбирают по размеченной выборке. Для каждого фрагмента отмечают правильность, затем смотрят, какая доля ошибок остаётся выше порога и сколько правильных строк уйдёт на ручную проверку. Один порог для всех полей редко оптимален: сумма, номер договора и свободный комментарий имеют разную цену ошибки. Критичные поля проверяют строже и дополняют формальными правилами.
Полезно хранить минимум три статуса: принято автоматически, требует проверки и отклонено. В интерфейс проверки передают crop, контекст страницы, распознанную строку и уверенность. Оператор должен видеть исходный фрагмент в достаточном масштабе, а исправление записывается отдельно. Эти данные затем используют для анализа частых ошибок и улучшения входа.
Средняя уверенность по документу может скрыть одну критическую ошибку. Поэтому отчёт включает минимум, распределение, число фрагментов ниже порога и результаты валидации полей. Для длинной строки полезно сохранять исходные элементы до объединения: один слабый токен не должен раствориться в хорошем среднем. При paragraph=True собственная сборка из детальных результатов даёт больше контроля.
Автоматическая замена по словарю допустима только с журналом и возможностью отката. Исправление правдоподобного слова может изменить фамилию, адрес или артикул. Безопасная схема предлагает вариант и сохраняет исходную строку. Для поиска можно индексировать оба варианта, а в юридически значимом экспорте использовать подтверждённый текст.
Типичные ошибки и способы устранения
Reader снова скачивает модель
Проверьте фактический model_storage_directory, домашний каталог пользователя и наличие постоянного тома. Убедитесь, что процесс имеет права читать завершённый файл и записывать временный. В контейнере вынесите папку моделей за пределы одноразового слоя. Если файл повреждён, удалите только его и повторите загрузку; сохраните контрольную сумму после успешной подготовки.
Результат пустой список
Сначала откройте входной массив и убедитесь, что он не пустой, не полностью белый и имеет ожидаемую ориентацию. Затем вызовите detect и уменьшите пороги на тестовой копии. Проверьте масштаб символов относительно min_size и canvas_size. Если текст виден, но не детектируется, увеличьте mag_ratio или вырежьте область интереса; смена языка не влияет на отсутствие рамок.
CUDA недоступна или возникает нехватка памяти
Проверьте torch.cuda.is_available() до импорта рабочего сценария и соответствие сборки PyTorch драйверу. Для нехватки памяти уменьшите batch_size, размер холста и число Reader. Временно запустите gpu=False, чтобы отделить ошибку модели от конфигурации ускорения. Не считайте переход на CPU исправлением производительности: измерьте задержку и задайте режим явно.
AttributeError, связанный с Image.Resampling
Такое сообщение обычно указывает на несовместимое сочетание Pillow и кода зависимости. Обновите Pillow и EasyOCR в чистом окружении либо зафиксируйте согласованный набор версий. Не копируйте случайную правку в site-packages без записи изменений: она исчезнет при переустановке и затруднит воспроизводимость. После обновления повторите минимальный тест импорта и одной картинки.
Колонки склеиваются в один абзац
Отключите paragraph, сохраните отдельные рамки и группируйте их по колонкам на основании x. Уменьшение x_ths может помочь, но на сложной верстке геометрическое разделение надёжнее. Сначала найдите вертикальный промежуток между колонками или используйте зоны страницы, затем сортируйте строки внутри каждой зоны. Таблицы обрабатывайте по ячейкам.
Кириллица превращается в латиницу
Убедитесь, что в lang_list есть ru, а английский добавлен только при необходимости. Для поля с фиксированным алфавитом примените allowlist. После OCR проверяйте похожие символы по формату и контексту, не выполняйте глобальную замену во всём документе. Сохраните исходную строку до нормализации.
Процесс завершается без понятного сообщения
Запустите минимальный скрипт из терминала, включите вывод версий Python, EasyOCR, OpenCV и PyTorch, затем обработайте маленькое PNG. Проверьте системный журнал на нехватку памяти и illegal instruction. Если проблема исчезает в чистом окружении, сравните зависимости. Большой файл уменьшите и проверяйте отдельно, чтобы исключить декодер изображения и лимиты памяти.
Безопасная и воспроизводимая обработка
Параметры запуска нужно хранить рядом с результатом: языки, устройство, детектор, пороги, размер холста, режим абзаца и декодер. Без этого два JSON с одинаковой структурой могут быть получены разными настройками и не поддаваться сравнению. Для пакетного задания создают конфигурационный файл и запрещают неявное изменение значений между страницами.
Модели и пакет фиксируют по версии и контрольным суммам в развёртывании. Обновление зависимостей сначала прогоняют на контрольном наборе и сравнивают CER, число рамок, скорость и потребление памяти. Даже исправление совместимости может изменить поведение косвенной библиотеки. Возврат к предыдущему окружению должен быть возможен без повторной ручной настройки.
Входные файлы валидируют до декодирования: ограничивают размер, проверяют сигнатуру и не доверяют одному расширению. Результат и временные изображения записывают в каталог задания, а не формируют путь из непроверенного имени. Если изображения содержат персональные данные, журнал не должен печатать полные распознанные строки без необходимости; для диагностики можно хранить идентификатор и маскированный фрагмент.
Автономный режим достигается предварительной установкой зависимостей и моделей с download_enabled=False. Тогда распознавание не требует сетевого обращения, но ответственность за обновление и резервное хранение файлов лежит на владельце конвейера. Проверка автономности выполняется в среде без сети на всех языковых наборах, а не только на одном английском примере.
Предварительная обработка без потери исходных данных
Любое преобразование следует выполнять над копией, сохраняя исходное изображение и параметры фильтра. Это позволяет повторить OCR, сравнить методы и показать оператору настоящий фрагмент, а не только усиленную версию. В журнал записывают масштаб, поворот, границы crop и последовательность операций. Без этих данных координаты результата нельзя надёжно сопоставить с исходной страницей, особенно после обрезки и перспективного преобразования.
Изменение размера выполняют с сохранением пропорций. Увеличение может сделать мелкую строку удобнее для детектора, но способ интерполяции влияет на края букв. Для уменьшения обычно подходит фильтр с усреднением, для умеренного увеличения — качественная интерполяция без чрезмерного повышения резкости. После масштабирования координаты EasyOCR делят на коэффициент и добавляют смещение crop, чтобы получить положение в исходном файле.
Серый канал полезен, когда цвет не несёт информации, однако простое среднее RGB может сделать красный или синий текст слишком тёмным либо светлым. На этикетках сравнивают отдельные каналы и цветовые пространства. Если символы выделяются по насыщенности, маска цвета иногда эффективнее общей бинаризации. Выбранный метод проверяют на разных партиях снимков, потому что автоматический баланс белого камеры меняет оттенки.
Морфологические операции применяют только после оценки толщины штрихов. Небольшое замыкание может соединить разорванную термопечать, а расширение — слить соседние цифры. Эрозия удаляет шум, но вместе с ним точки, запятые и тонкие элементы букв. Для критичных полей сохраняют результаты нескольких вариантов и выбирают по формату поля, а не по максимальному confidence без дополнительных ограничений.
Удаление линий таблицы строят на длинных горизонтальных и вертикальных структурах. Маску линий вычитают из копии, но исходные границы ячеек сохраняют отдельно для восстановления структуры. Если линия пересекает символ, грубое вычитание разрывает букву. Поэтому распознавание ячеек часто выполняют с небольшим внутренним отступом, где рамка таблицы уже не попадает в crop.
Резкость и шумоподавление должны соответствовать источнику. Медианный фильтр помогает против одиночных цветных точек, но портит мелкий шрифт; гауссово размытие сглаживает JPEG-артефакты, однако снижает контраст тонких линий. Unsharp mask подчёркивает края и одновременно усиливает ореолы. Вместо универсального фильтра создают несколько профилей для сканера, телефона и термопринтера, затем выбирают профиль по метаданным или тестовой оценке.
Если после подготовки confidence вырос, это ещё не доказательство улучшения. Сравнивают распознанную строку с эталоном, число найденных областей и долю ложных срабатываний. Фильтр способен сделать неверный символ более уверенным. Для небольшого контрольного набора рассчитывают посимвольную ошибку и отдельно отслеживают критичные знаки, например цифры в сумме или номере документа.

Организация ручной проверки результата
Очередь проверки формируют не только по низкому confidence. В неё включают поля, не прошедшие маску, строки с неожиданным алфавитом, пересекающиеся рамки, пустые обязательные зоны и документы с необычным числом фрагментов. Комбинация признаков лучше одного порога: модель может уверенно прочитать похожую цифру, но формат номера сразу обнаружит противоречие.
Карточка оператора показывает страницу, увеличенный crop, распознанный текст, координаты и причину направления на проверку. Исправление не должно затирать исходный ответ EasyOCR. Хранят автоматическую строку, подтверждённое значение, пользователя и время изменения. Это позволяет анализировать систематические ошибки и не смешивать качество модели с качеством ручного ввода.
Для повторяющихся шаблонов исправления агрегируют по полю и источнику. Если один сканер постоянно даёт тёмный край, меняют подготовку изображения; если путается определённая пара символов в кодах, уточняют allowlist и валидацию. Обучать пользовательскую сеть стоит после такого анализа, когда ясно, что проблема относится к визуальной модели, а не к неверной геометрии или формату входа.
Выборка для контроля должна включать случайные автоматически принятые записи. Иначе ошибка выше порога останется незаметной, а метрики будут оценивать только трудные случаи. Доля выборочного контроля зависит от цены ошибки и зрелости процесса. При изменении модели, зависимостей, dpi или профиля фильтра объём проверки временно увеличивают и сравнивают результаты с прежней конфигурацией.
Сравнение EasyOCR с аналогами
| Программа | Лучше подходит для | Главное ограничение |
|---|---|---|
| EasyOCR | Встраивания OCR фотографий и изображений в Python-конвейеры с координатами и confidence | Нет готового редактора и прямой сборки searchable PDF |
| PDF Commander | Распознавания сканов внутри визуального редактирования PDF, правок и сохранения документа | Не предназначен как Python-библиотека для машинного зрения |
| Tesseract OCR | Печатных документов, языковых моделей и вывода TXT, hOCR, TSV, ALTO или PDF | Для сценового текста часто нужна тщательная подготовка и внешняя оболочка |
| PaddleOCR | Сложных документов, многоязычного OCR и структурного анализа в программных конвейерах | Более крупная экосистема и сложнее выбор подходящего пайплайна |
| docTR | Исследовательских и серверных OCR-процессов на PyTorch с детекцией и распознаванием страниц | Требует программной интеграции и самостоятельного экспорта результата |
| OCRmyPDF | Добавления поискового текстового слоя к сканированным PDF с сохранением страниц | Ориентирован на PDF, а не на произвольные сценовые фотографии |
EasyOCR стоит выбирать, когда нужны координаты областей, многоязычное чтение фотографий и непосредственная интеграция с NumPy, OpenCV или собственным сервисом. PDF Commander удобнее пользователю, который хочет открыть скан, распознать и отредактировать PDF через окна и команды без написания кода. Tesseract подходит для традиционных печатных страниц и разнообразных стандартных форматов вывода; OCRmyPDF — когда главная цель состоит именно в получении searchable PDF. PaddleOCR и docTR разумны для более широких инженерных конвейеров, где команда готова настраивать модели, структуру документа и развёртывание.
Как выбрать настройки для конкретной задачи
Для чистого скана начните с 300 dpi, языков ru и en, detail=1 и параметров по умолчанию. Проверьте рамки, затем восстановите строки по координатам. Не включайте paragraph до оценки колонок. Для сомнительных слов сохраните crop и confidence. Если мелкий шрифт пропущен, увеличьте масштаб или canvas_size; если рамок слишком много, поднимите пороги и min_size.
Для фотографии вывески сначала обрежьте область интереса и исправьте перспективу. Оставьте свободный фон вокруг букв, включите rotation_info только при смешанной ориентации. Сравните исходный цвет и нормализованный контраст. Если текст состоит из ограниченного кода, передайте allowlist. Не пытайтесь компенсировать размытие увеличением изображения: интерполяция не создаёт утраченные детали.
Для формы разделите страницу на зоны и распознавайте каждую с подходящими правилами. Цифровые поля получают allowlist, свободный комментарий — полный язык, таблица — сетку ячеек. Значения валидируются по маске и диапазону. Отчёт хранит координаты, исходную строку, нормализованное значение и статус проверки. Такой подход надёжнее единственного readtext по всей странице с последующим угадыванием структуры.
Для большого архива заранее скачайте модели, создайте один Reader на рабочий процесс, ограничьте размер очереди и логируйте каждую страницу. Измерьте производительность после прогрева, подберите batch_size по памяти и сохраняйте конфигурацию. Ошибка одного файла не должна прерывать пакет; повторный запуск должен пропускать уже завершённые страницы и брать только неуспешные задания.
Полный пример конвейера для набора изображений
Ниже показана схема, в которой Reader создаётся один раз, файлы читаются по байтам, результаты преобразуются в сериализуемые типы, а фрагменты с низкой уверенностью отмечаются для проверки. Код не пытается восстановить таблицы или абзацы универсальным правилом: он сохраняет исходную геометрию, чтобы следующий этап принял решение с учётом типа документа.
from pathlib import Path
import json
import cv2
import numpy as np
import easyocr
reader = easyocr.Reader(
['ru', 'en'],
gpu=False,
model_storage_directory='models/easyocr'
)
def read_image(path: Path):
data = np.frombuffer(path.read_bytes(), np.uint8)
image = cv2.imdecode(data, cv2.IMREAD_COLOR)
if image is None:
raise ValueError(f'Не удалось открыть {path.name}')
return image
def run_ocr(path: Path):
rows = reader.readtext(
read_image(path),
detail=1,
paragraph=False,
rotation_info=[180],
batch_size=1,
workers=0
)
return [
{
'box': [[int(x), int(y)] for x, y in box],
'text': text,
'confidence': float(score),
'review': float(score) < 0.65
}
for box, text, score in rows
]
output = {}
for path in sorted(Path('input').glob('*')):
if path.suffix.lower() not in {'.png', '.jpg', '.jpeg'}:
continue
try:
output[path.name] = {'status': 'ok', 'rows': run_ocr(path)}
except Exception as exc:
output[path.name] = {'status': 'error', 'message': str(exc)}
Path('result.json').write_text(
json.dumps(output, ensure_ascii=False, indent=2),
encoding='utf-8'
)
Перед эксплуатацией пример дополняют ограничением размеров, журналированием версий, тайм-аутами и тестами. Порог 0,65 здесь только демонстрационный: его нельзя переносить на реальные документы без разметки. rotation_info=[180] имеет смысл, если в наборе встречаются перевёрнутые страницы; иначе параметр удаляют ради скорости. Список расширений также не заменяет проверку сигнатуры и успешного декодирования.
Если входом служит PDF, внешний цикл сначала рендерит страницы и передаёт их функции run_ocr. Номер страницы записывается в JSON, а координаты остаются в пикселях рендера. Для дальнейшего текстового слоя добавляют dpi и размеры страницы. Временные массивы освобождают после записи результата, чтобы пакет из сотен страниц не накапливался в памяти.

Практический чек-лист перед обработкой
- Определить языки и не добавлять письменности, которых нет в документах.
- Проверить одну контрольную картинку после установки и загрузки моделей.
- Зафиксировать каталог моделей и права сервисной учётной записи.
- Подготовить PDF как изображения без повторной JPEG-компрессии.
- Сохранить detail=1, пока не завершена проверка координат и confidence.
- Отдельно оценить детекцию рамок и качество распознавания символов.
- Калибровать пороги на размеченной выборке, а не на одном удачном скане.
- Не применять paragraph к колонкам и таблицам без проверки геометрии.
- Проверять критичные поля масками, диапазонами и контрольными суммами.
- Записывать параметры, версии и ошибки по каждому файлу.
Этот список предотвращает наиболее дорогие ошибки: повторную загрузку моделей, потерю геометрии из-за detail=0, склейку колонок и принятие правдоподобного неверного номера. После пробного пакета следует вручную проверить как хорошие, так и слабые фрагменты. Только затем можно оценивать долю автоматического принятия и потребность в операторе.
Итоговый порядок работы
Сначала подготовьте устойчивое окружение и загрузите нужные модели в постоянный каталог. Создайте Reader с минимальным набором языков и проверьте один файл. Затем приведите страницы к достаточному масштабу, исправьте общий поворот и сохраните исходные изображения. Получите детальные рамки без paragraph, визуализируйте их и только после этого настраивайте пороги, контраст, объединение и декодер.
Для документов восстановите структуру по координатам и зонам, а не по одному плоскому списку. Для кодов применяйте allowlist и формальную валидацию. Для низкой уверенности сохраняйте вырезку и направляйте запись на проверку. При пакетной обработке переиспользуйте Reader, ограничивайте память и журналируйте параметры каждого запуска. Такой порядок превращает EasyOCR из короткой демонстрации в воспроизводимый инструмент извлечения текста, где результат можно проверить, сопоставить с исходной областью и безопасно передать в следующий этап.