Rychagov S.
🔢 Computer Vision · OCR · PyTorch

Обучение OCR-модели распознавания автомобильных номеров России на PyTorch

Практический разбор: от постановки задачи OCR номерных знаков до обучения CRNN + CTC модели на 42 600 изображениях с нуля.

TL;DR

Задача — распознавание текста российских автомобильных номеров с изображения (кропа номерного знака).

Архитектура CRNN (CNN + BiLSTM + CTC) — классический и легковесный подход для OCR, ~9M параметров.

Датасет: 37 775 обучающих и 4 891 валидационное изображение. Алфавит — 22 символа (цифры + кириллица).

Mixed Precision (AMP) на NVIDIA RTX 5090 даёт ~2x ускорение обучения.

Итог: plate accuracy 95%+ после 50–100 эпох обучения с warmup и cosine annealing.

Постановка задачи

Распознавание текста российских автомобильных номеров с изображения — задача оптического распознавания символов (OCR), формулируемая как sequence-to-sequence прогноз: на входе — изображение номера фиксированного размера, на выходе — последовательность символов.

Алфавит

22 символа: 0–9 (цифры) и АВЕКМНОРСТУХ (кириллица с визуальными аналогами в латинице).

Формат входа

Grayscale-изображение 1×32×256 (1 канал, высота 32px, ширина 256px).

Формат выхода

Последовательность символов (8 или 9 символов для российских номеров).

Подход

CRNN + CTC — обучение без посимвольной разметки,只知道 итоговый текст номера.

Где используется: в составе Video Analytics Platform для распознавания номеров в видеопотоке в реальном времени.

Архитектура модели

Изображение (1x32x256)
    ↓
[CNN Backbone] — Feature Extraction
    ↓
Tensor (B, 512, 1, 63) → (B, 63, 512)
    ↓
[BiLSTM x2] — Sequence Modeling
    ↓
[Linear 512→23] — Classification
    ↓
[CTC Decoding] — Greedy Decode
    ↓
Текст номера

CRNN (Shi et al., 2015) — классическая архитектура для OCR. Три блока: CNN извлекает признаки, BiLSTM моделирует последовательность, CTC обучает без посимвольной разметки.

CNN-бэкбон (Feature Extraction)

Свёрточная нейросеть извлекает из изображения последовательность признаков. Архитектура состоит из 5 блоков с BatchNorm после каждого свёрточного слоя.

Ключевые решения:

1) BatchNorm после каждого слоя — стабилизирует обучение и позволяет использовать более высокие learning rates.

2) MaxPool(2,1) в блоках 3 и 4 — уменьшает только высоту, сохраняя ширину (горизонтальное разрешение важно для последовательности символов).

3) Последний Conv с kernel=2 без padding — сводит высоту к 1, подготавливая данные для RNN.

Итоговый тензор (B, 512, 1, 63) переставляется в формат (B, 63, 512) — 63 временных шага, каждый с 512 признаками.

Блок Слои Выход (H×W)
Блок 1Conv(1→64)+BN+ReLU, Conv(64→64)+BN+ReLU, MaxPool(2×2)16×128
Блок 2Conv(64→128)+BN+ReLU, Conv(128→128)+BN+ReLU, MaxPool(2×2)8×64
Блок 3Conv(128→256)+BN+ReLU, Conv(256→256)+BN+ReLU, MaxPool(2,1)4×64
Блок 4Conv(256→512)+BN+ReLU, Conv(512→512)+BN+ReLU, MaxPool(2,1)2×64
Блок 5Conv(512→512, kernel=2)+BN+ReLU1×63

BiLSTM (Sequence Modeling)

Двунаправленная LSTM обрабатывает последовательность признаков, захватывая контекст в обоих направлениях. Это критично для понимания границ символов.

nn.LSTM(
    input_size=512,
    hidden_size=256,
    num_layers=2,
    bidirectional=True,
    dropout=0.2,
)

Конфигурация: input_size=512, hidden_size=256, 2 слоя, bidirectional=True, dropout=0.2.

Bidirectional означает, что каждый временной шаг получает информацию как слева, так и справа. 2 слоя дают достаточную глубину, а dropout 0.2 — регуляризацию.

CTC Loss и декодирование

CTC (Connectionist Temporal Classification) — ключевой компонент для обучения без посимвольной разметки. Мы знаем только итоговый текст номера, но не знаем, какой пиксель соответствует какому символу.

Вводится blank-токен (индекс 0) — «нет символа». Модель предсказывает распределение по всем 23 классам (22 символа + blank) для каждого из 63 временных шагов.

CTC loss суммирует вероятности всех путей выравнивания, которые приводят к целевому тексту. zero_infinity=True — защита от NaN на ранних этапах.

Декодирование (greedy): для каждого временного шага берётся символ с максимальной вероятностью, затем удаляются дубликаты и blank-токены.

Подготовка данных

Датасет: 37 775 обучающих и 4 891 валидационное изображение (~88.5% / 11.5%). Лейблы извлекаются из имён файлов (например, A001AA50.png → A001AA50).

Предобработка: OpenCV (BGR→RGB), grayscale (1 канал), ресайз до 32×256, нормализация к диапазону [-1, 1].

Аугментации (только для train)

Для повышения устойчивости к реальным условиям съёмки:

Аугментация Вероятность Цель
Gaussian Noise40%Имитация шума матрицы камеры
Brightness/Contrast40%Разные условия освещения
Gaussian Blur25%Расфокусировка, движение

Процесс обучения

Оптимизатор Adam с learning rate 1e-4. Warmup + Cosine Annealing: первые 5 эпох LR линейно возрастает от 0 до 1e-4 (плавный старт), затем косинусное затухание до 1e-12.

Mixed Precision (AMP): forward pass в float16, GradScaler предотвращает underflow градиентов. На RTX 5090 — ~2x ускорение и увеличение batch size.

Gradient Clipping по норме max_norm=5.0 — предотвращает «взрыв градиентов» в LSTM, особенно на ранних этапах обучения.

Модель сохраняется при улучшении validation loss (не train) — предотвращает переобучение.

Гиперпараметры

Параметр Значение
Batch size64
Epochs200
Learning rate1e-4
Warmup epochs5
Gradient clip5.0
LSTM layers / hidden2 / 256
Параметры модели~8.9M

Метрики и результаты

Plate Accuracy

Доля номеров, распознанных полностью без ошибок — главная метрика. 95%+ после 50–100 эпох.

Character Accuracy

Доля отдельных символов, распознанных правильно. 90%+ уже к 10–20 эпохе.

CTC Loss

Функция потерь для оптимизации. Быстро падает в первые эпохи, выходит на плато к 100 эпохе.

Динамика обучения

Первые эпохи — CTC loss быстро падает. К 10–20 эпохе — char accuracy 90%+. К 50–100 эпохе — plate accuracy 95%+. Косинусное затухание LR обеспечивает плавную сходимость.

Сравнение с альтернативами

В ходе работы тестировались два подхода:

PyTorch CRNN (v2) TensorFlow EfficientNetV2L
ФреймворкPyTorch 2.11TensorFlow 2.21
БэкбонCustom CNN (~9M params)EfficientNetV2L (~120M params)
GPU на WindowsCUDA 12.8 работаетТолько CPU (TF drop GPU)
ВходGrayscale 32×256RGB 200×50

Почему PyTorch: TensorFlow с версии 2.15 прекратил поддержку GPU на Windows. PyTorch с CUDA 12.8 полностью использует RTX 5090 — ускорение обучения в десятки раз по сравнению с CPU.

Технологический стек

Компонент Технология
ФреймворкPyTorch 2.11 + CUDA 12.8
GPUNVIDIA GeForce RTX 5090 (32 GB VRAM)
Обработка изображенийOpenCV, torchvision
МониторингTensorBoard
Датасет~42 600 изображений (кропы номеров)

Типичные ошибки при обучении OCR

1) Обучать без аугментаций — модель не переносится на реальные условия (шум, освещение, blur).

2) Использовать RGB вместо grayscale — номера не требуют цветовой информации, а 3 канала увеличивают модель.

3) Не использовать gradient clipping — LSTM склонна к «взрыву градиентов» на ранних этапах.

4) Сохранять модель по train loss, а не по val loss — приводит к переобучению.

5) Начинать с полного LR без warmup — деструктивные обновления весов на раннем этапе.

6) Игнорировать формат номеров (разная длина) — без правильной collate-функции CTC не обучится.

Мониторинг обучения

Интеграция с TensorBoard для визуализации: графики train/val loss по эпохам, plate accuracy и character accuracy, изменение learning rate.

Запуск: tensorboard --logdir runs/v2_ocr

FAQ

Почему CRNN, а не Transformer?

CRNN + CTC — легковесная архитектура (~9M параметров), которая отлично работает для фиксированных доменов (номера, чеки). Transformer требует значительно больше данных и ресурсов.

Сколько нужно данных для обучения?

Для российских номеров хватило ~38k обучающих примеров. Качество сильно зависит от разнообразия аугментаций, а не только от объёма данных.

Можно ли использовать для других типов номеров?

Да, нужно заменить алфавит и дообучить модель на новых данных. Архитектура универсальна для OCR последовательностей.

Насколько быстро работает inference?

На RTX 5090 — real-time для видеопотока. На CPU — пакетная обработка видеофайлов без проблем.

Почему не использовать готовые OCR (Tesseract, EasyOCR)?

Универсальные OCR хуже на узких доменах. Собственная модель точнее на российских номерах, легче и быстрее.

Key Takeaways

1) CRNN + CTC — эффективная и легковесная архитектура для OCR номеров (~9M параметров).

2) Mixed Precision + RTX 5090 дают значительное ускорение обучения.

3) Warmup + Cosine Annealing обеспечивают стабильную сходимость без осцилляций.

4) Аугментации критичны для устойчивости к шуму и освещению в реальных условиях.

5) PyTorch — единственный вариант для GPU-обучения на Windows на текущий момент.

Кому подходит

Командам Computer Vision, разработчикам систем видеонаблюдения, специалистам по OCR и ML-инженерам, которым нужно распознавание номеров или других последовательностей символов с изображения.

Связаться в Telegram