Разработка системы распознавания номерных знаков (ANPR/LPR)

Допустим, на парковке торгового центра камера фиксирует въезжающий автомобиль. Система должна за доли секунды распознать номер и принять решение: открыть шлагбаум или внести в чёрный список. Если OCR ошибается — пробка у въезда и негатив посетителей. Как построить ANPR/LPR, который стабильно отрабат

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

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

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

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1461
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1314
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1014
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1275
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    727
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1019

Допустим, на парковке торгового центра камера фиксирует въезжающий автомобиль. Система должна за доли секунды распознать номер и принять решение: открыть шлагбаум или внести в чёрный список. Если OCR ошибается — пробка у въезда и негатив посетителей. Как построить ANPR/LPR, который стабильно отрабатывает в дождь, ночью и на скорости 60 км/ч? Мы годами отлаживали пайплайн, и делимся проверенной архитектурой. Наша система экономит до 30% бюджета за счет использования open-source моделей и оптимизации инференса.

Как работает двухэтапный пайплайн распознавания номерных знаков?

Видео/Фото → Детекция автомобиля → Детекция номерного знака → OCR → База данных 

Двухэтапный подход (авто → номер) точнее одноэтапного, так как позволяет обрабатывать разные форматы номеров из разных стран. На первом этапе YOLO ищет автомобили, на втором — специализированная модель детектирует номер в кропе.

from ultralytics import YOLO from paddleocr import PaddleOCR import cv2 import numpy as np import re class ANPRSystem: def __init__(self, vehicle_model: str = 'yolov8l.pt', plate_model: str = 'plate_detector.pt'): self.vehicle_detector = YOLO(vehicle_model) self.plate_detector = YOLO(plate_model) # дообученный на номерах self.ocr = PaddleOCR( use_angle_cls=True, lang='en', rec_algorithm='SVTR_LCNet' ) def process(self, frame: np.ndarray) -> list[dict]: # Детекция транспортных средств vehicles = self.vehicle_detector(frame, classes=[2, 3, 5, 7], # car/moto/bus/truck conf=0.5) results = [] for vehicle_box in vehicles[0].boxes.xyxy: x1, y1, x2, y2 = map(int, vehicle_box) vehicle_crop = frame[y1:y2, x1:x2] # Детекция номерного знака в кропе автомобиля plates = self.plate_detector(vehicle_crop, conf=0.5) for plate_box in plates[0].boxes.xyxy: px1, py1, px2, py2 = map(int, plate_box) plate_crop = vehicle_crop[py1:py2, px1:px2] # OCR номера plate_text = self._recognize_plate(plate_crop) if plate_text: results.append({ 'plate': plate_text, 'vehicle_bbox': [x1, y1, x2, y2], 'plate_bbox': [x1+px1, y1+py1, x1+px2, y1+py2], 'confidence': float(plates[0].boxes.conf[0]) }) return results def _recognize_plate(self, plate_img: np.ndarray) -> str | None: # Предобработка plate_img = self._preprocess_plate(plate_img) result = self.ocr.ocr(plate_img, cls=False) if not result or not result[0]: return None text = ''.join([line[1][0] for line in result[0]]) text = re.sub(r'[^A-Z0-9А-Я]', '', text.upper()) # Валидация формата российского номера if re.match(r'^[АВЕКМНОРСТУХ]\d{3}[АВЕКМНОРСТУХ]{2}\d{2,3}$', text): return text return text if len(text) >= 6 else None 

Почему важна предобработка изображения? — разработка системы распознавания

Качество OCR напрямую зависит от того, как подготовлен кроп номера. Мы используем масштабирование до высоты 64 пикселя, выравнивание по углу наклона и нормализацию яркости. Это снижает процент ошибок на 15–20% по сравнению с сырым кадром.

def _preprocess_plate(self, image: np.ndarray) -> np.ndarray: # Масштабирование до стандартной высоты target_h = 64 scale = target_h / image.shape[0] new_w = int(image.shape[1] * scale) image = cv2.resize(image, (new_w, target_h), interpolation=cv2.INTER_CUBIC) # Конвертация в оттенки серого gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Нормализация яркости normalized = cv2.normalize(gray, None, 0, 255, cv2.NORM_MINMAX) return normalized 

Как решаем проблему разных форматов номеров?

Российские номера: X000XX00[0] (стандарт), X000XX000 (транзитные). Дополнительные форматы: таможенные, дипломатические, военные. Для международных систем — мультиязычная OCR + несколько наборов регулярных выражений валидации. Мы накопили библиотеку из более чем 20 масок для стран СНГ и Европы.

Пример из практики: парковка ТРЦ на 8 камер

Для крупного торгового центра требовалась система, которая обрабатывает поток 30 машин в минуту, работает в режиме 24/7 и интегрируется с существующим шлагбаумом. Мы развернули двухэтапный пайплайн на сервере с GPU T4. Точность распознавания составила 98%, ложные срабатывания — менее 1%. Время отклика — 45 мс на кадр. Спустя год эксплуатации система не требовала переобучения — лишь периодическая калибровка камер.

Сравнение: наша система vs типовые решения на OpenALPR

Наш пайплайн в 2 раза быстрее обрабатывает кадры при той же точности: 45 мс против 95 мс на T4. За счет тонкой настройки YOLO и PaddleOCR мы добились accuracy 98% против 93% у OpenALPR на сложных номерах. Кроме того, мы поддерживаем больше форматов — более 20 масок против 5 стандартных.

Пошаговое внедрение системы ANPR/LPR

  1. Аудит места установки и подбор камер с нужным разрешением и ИК-подсветкой.
  2. Сбор датасета: 5000+ кадров в разных условиях для дообучения моделей.
  3. Обучение детектора и OCR на вычислительном кластере (обычно 2-3 дня на GPU A100).
  4. Интеграция с СКУД через REST API, настройка Redis для LPR-списков.
  5. Тестирование в течение недели с реальным трафиком, коррекция порогов.
  6. Деплой на сервер заказчика, передача документации и обучение персонала.

Производительность в продакшене

Метрика Значение
Accuracy (хорошее освещение, < 80 км/ч) 96–99%
Accuracy (ночь, ИК-подсветка) 92–96%
Accuracy (высокая скорость, 120+ км/ч) 80–88%
Latency (T4 GPU, 1080p кадр) 35–50 ms
False positive rate < 2%

Что входит в разработку под ключ?

  • Анализ места установки и подбор камер
  • Обучение/дообучение моделей детекции и OCR
  • Настройка предобработки и постобработки
  • REST API для интеграции с СКУД и базами данных
  • Redis для горячего списка (whitelist/blacklist)
  • PostgreSQL с pg_trgm для нечёткого поиска (учитывает ошибки OCR: 0/O, I/1, B/8)
  • Документация и обучение персонала
  • Гарантийная поддержка 6 месяцев

Сроки внедрения

Масштаб системы Срок
1–4 камеры, парковочный контроль 3–5 недель
8–16 камер, городская система 6–10 недель
50+ камер, распределённая инфраструктура 12–18 недель
Дополнительно: лицензии и сертификаты Мы используем open-source компоненты (YOLO, PaddleOCR) под лицензиями Apache 2.0 и MIT. Для коммерческого использования не требуется дополнительных отчислений. По запросу предоставляем полный список зависимостей и сертификаты соответствия стандартам безопасности.

Стоимость рассчитывается индивидуально — зависит от числа камер, требуемой точности и глубины интеграции. Наши инженеры имеют сертификаты по MLOps и суммарный опыт 10+ лет в Computer Vision. Пишите — оценим ваш проект за один рабочий день. Гарантируем прозрачный результат и соблюдение сроков. Получите консультацию: свяжитесь с нами для оценки вашего проекта.

Используемые технологии: YOLOv8, PaddleOCR, PyTorch, Redis, PostgreSQL.