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

Припустимо, на парковці торговельного центру камера фіксує автомобіль, що в'їжджає. Система має за частки секунди розпізнати номер і прийняти рішення: відкрити шлагбаум або внести до чорного списку. Якщо OCR помиляється — корок біля в'їзду та негатив відвідувачів. Як побудувати ANPR/LPR, який стабіл

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1439
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    997
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1264
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    712
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1002

Припустимо, на парковці торговельного центру камера фіксує автомобіль, що в'їжджає. Система має за частки секунди розпізнати номер і прийняти рішення: відкрити шлагбаум або внести до чорного списку. Якщо 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.