Розробка AI-системи розпізнавання дорожніх знаків та розмітки

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка AI-системи розпізнавання дорожніх знаків та розмітки
Середній
~1-2 тижні
Часті запитання

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

Етапи розробки AI-рішення

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

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

Розпізнавання дорожніх знаків та розмітки на основі AI

Автономні системи та ADAS вимагають надійного розпізнавання знаків та розмітки – у дощ, туман, вночі, при частковому перекритті, на дорогах з вицвілою розміткою. Завдання дворівневе: детекція знака/розмітки на кадрі та її класифікація. Обидва рівні мають укладатися у сумарні 30–50ms.

Розпізнавання дорожніх знаків

import cv2
import numpy as np
from ultralytics import YOLO
import torch
import torch.nn as nn

class TrafficSignRecognizer:
    def __init__(self, detector_path: str, classifier_path: str,
                 class_names: list):
        # Детектор: YOLO находит все знаки на кадре
        self.detector = YOLO(detector_path)

        # Классификатор: EfficientNet-B3 или MobileNetV3
        self.classifier = torch.load(classifier_path)
        self.classifier.eval()
        self.class_names = class_names

        # Предобработка для классификатора
        from torchvision import transforms
        self.transform = transforms.Compose([
            transforms.ToPILImage(),
            transforms.Resize((64, 64)),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406],
                                  [0.229, 0.224, 0.225])
        ])

    @torch.no_grad()
    def recognize(self, frame: np.ndarray) -> list[dict]:
        # Детекция: находим bboxes знаков
        det_results = self.detector(frame, conf=0.45, classes=[])
        signs = []

        for box in det_results[0].boxes:
            x1, y1, x2, y2 = map(int, box.xyxy[0])
            # Небольшой padding для лучшей классификации
            pad = 8
            x1, y1 = max(0, x1-pad), max(0, y1-pad)
            x2, y2 = min(frame.shape[1], x2+pad), min(frame.shape[0], y2+pad)

            roi = frame[y1:y2, x1:x2]
            if roi.size == 0:
                continue

            # Классификация ROI
            tensor = self.transform(roi).unsqueeze(0)
            logits = self.classifier(tensor)
            probs = torch.softmax(logits, dim=-1)
            top_prob, top_idx = probs.max(-1)

            signs.append({
                'class': self.class_names[top_idx.item()],
                'confidence': float(top_prob),
                'det_confidence': float(box.conf),
                'bbox': [x1, y1, x2, y2]
            })

        return signs

Детекція дорожньої розмітки

class LaneMarkingDetector:
    def __init__(self, model_name: str = 'clrnet'):
        """
        CLRNet (Cross Layer Refinement Network) — лучшее соотношение
        точности и скорости для lane detection в 2024.
        CULane F1 = 0.806, TuSimple F1 = 0.971.
        """
        if model_name == 'clrnet':
            self.model = self._load_clrnet()
        elif model_name == 'ufld':
            # Ultra-Fast Lane Detection v2 — быстрее, чуть хуже
            self.model = self._load_ufld()

    def detect_markings(self, frame: np.ndarray) -> dict:
        lanes = self.model(frame)

        # Классификация типов разметки
        markings = {
            'solid_white': [],
            'dashed_white': [],
            'solid_yellow': [],
            'double_yellow': [],
            'stop_line': []
        }

        for lane in lanes:
            marking_type = self._classify_marking(frame, lane)
            markings[marking_type].append(lane)

        return markings

    def _classify_marking(self, frame: np.ndarray,
                            lane_points: list) -> str:
        """По цвету и прерывистости определяем тип разметки"""
        # Сэмплируем цвет вдоль линии
        colors = []
        for x, y in lane_points[::5]:
            if 0 <= int(y) < frame.shape[0] and 0 <= int(x) < frame.shape[1]:
                colors.append(frame[int(y), int(x)])

        if not colors:
            return 'solid_white'

        mean_color = np.mean(colors, axis=0)
        # Жёлтый: высокий R и G, низкий B
        if mean_color[2] > 150 and mean_color[1] > 120 and mean_color[0] < 100:
            return 'solid_yellow'

        return 'solid_white'

Складні умови: проблеми та рішення

Умова Проблема Рішення
Ніч Знаки видно тільки при світлі фар Навчання на нічних даних (CURE-TSD)
Дощ Блики, розмитість Deblurring + augmentation з мокрими знаками
Сніг на знак Часткове перекриття Few-shot + масковані приклади в датасеті
Вицвіла розмітка Низький контраст CLAHE preprocessing + data augmentation
Декілька знаків поруч Перекриття bbox NMS з IoU 0.3, не 0.5

Датасети для навчання

  • GTSRB (Німеччина): 43 класи, 50k+ зображень — класика для знаків
  • Mapillary Traffic Sign Dataset: 100k зображень, 313 класів, реальні дороги
  • CULane: 133k кадрів, складні умови для lane detection
  • BDD100K: 100k відео, знаки + розмітка + погана погода

Для локалізованих знаків (РФ, BY, UA) завжди потрібна донавчання на місцевих стандартах ГОСТ. У стандартному GTSRB немає знаків радянських стандартів, цегли специфічної форми, тимчасових знаків на помаранчевому фоні.

Продуктивність

EfficientDet-D2 для детекції знаків: [email protected] = 0.87 на GTSRB, latency 22ms на RTX 3060. Для бортового застосування на Qualcomm Snapdragon Ride: квантизуємо в INT8 через QNN, latency 35ms - вкладаємося в ADAS-вимоги.

Завдання Термін
Детектор + класифікатор знаків (1 країна) 4–7 тижнів
Lane marking detection 3-5 тижнів
Комбінована система знаки + розмітка 7–12 тижнів