Skip to content

Прототип помощника для водителей, который будет оповещать их о дорожных знаках.

License

Notifications You must be signed in to change notification settings

medphisiker/drivers_helper

Repository files navigation

Описание проекта

Прототип помощника для водителей, который будет оповещать их о дорожных знаках.

Демо работы сервиса

Визуализация обнаружения дорожных знаков и уведомления для водителя

drivers_helper

Смотрите полные демо видео работы сервиса на его YouTube-плейлисте (ссылка)

Или отдельные демо видео:

Источники тестовых видео

Список видео с видеорегистраторов, используемых для тестов:

Структура проекта

Структура проекта была создана под вдохновением от Cookiecutter Data Science template (link).

Исходная структура данного шаблона показалась нам перегруженной для небольшого проекта со сроком выполнения 2 недели.

Мы создали упрощенный вариант, который всегда может быть расширен, компонентами структуры исходного шаблона по мере необходимости и развития проекта.

Структура нашего проекта выгладит так

├── LICENSE            <- The MIT License (MIT).
├── README.md          <- Описание проекта README ля других разработчиков использующих проект.
├── data
│   ├── analysis       <- Данные используемые для анализа. Например, кропы с представителями классов дорожных знаков.
│   ├── external       <- Данные из других источников. Например, видео с YouTube для теста работы нашей модели.
│   ├── interim        <- Преобразованные датасеты для более удобного использования, но еще не в форме для обучения модели.
│   ├── processed      <- Финальная версия датасета используемая для обучения моделей.
│   └── raw            <- Датасеты в своей исходной форме.
│
├── models             <- Обученные и сериализованные модели и их метрики.
│
├── notebooks          <- Jupyter notebooks. Ноутбуки для исследования и анализа данных.
│
├── reports            <- Отчеты по анализу данных в виде Excel, HTML, PDF, LaTeX, etc.
│   └── figures        <- Графики и диаграммы в виде картинок используемые для отчетов или документации.
│
├── pyproject.toml     <- Мы используем poetry для создания виртуальной среды для разработки.
│
├── src                <- Source code используемый в данном проекте.
    │
    ├── data           <- Скрипты для обработки данных
    │
    ├── models         <- Скрипты для обучения моделей и упаковки их в архив для сохранения в облаке.
    │
    └── visualization  <- Скрипты для визуализации данных. Например, для визуализации кропов классов дорожных знаков.

Code style

Для соблюдения единого стиля оформления кода используются Black(ссылка) и isort(ссылка) плагины для VS code.

Развернуть рабочее окружение

Проект использует poetry для управления зависимостями. Устанавливаем poetry в нашу систему если он не установлен согласно офф. документации (ссылка).

Для создания виртуального рабочего окружения с poetry выполняем команду:

poetry install

Для его активации выполняем команду:

poetry shell

Скачиваем датасет

Скачиваем датасет Russian traffic sign images dataset (RSTD) c Kaggle (ссылка) для детекции дорожных знаков России.

Располагаем archive.zip датасета по пути data/raw/archive.zip.

https://www.kaggle.com/datasets/meowmeowmeowmeowmeow/gtsrb-german-traffic-sign/

Преобразование данных

  • разархивируем датасет и преобразуем его структуру под FiftyOne's MS COCO формат (src/data/RTSD_arhive_unzip.py)
  • преобразуем train и val подвыборки датасета RSTD с помощью src/data/RTSD_dataset_COCO_to_CVAT_convert.py из MS COCO -> CVAT images
  • создаем файл label.json описания классов для task на разметку в CVAT (src/data/convert_labels_to_CVAT_json.py) для
    1. data/interim/RTSD_cvat_train
    2. data/interim/RTSD_cvat_val
  • архивируем папки с картинками (src/data/images_folder_arhivier.py) для
    1. data/interim/RTSD_cvat_train
    2. data/interim/RTSD_cvat_val

Загрузить данные в CVAT

Загрузим в CVAT train-подвыборку с помощью cvat-cli выполнив команду:

cvat-cli --auth USER --server-host IP-ADRESS --server-port 8080 create "RSTD_train" --labels data/interim/RTSD_cvat_train/label.json --image_quality 100 --annotation_path data/interim/RTSD_cvat_train/labels.xml --annotation_format "CVAT 1.1" local data/interim/RTSD_cvat_train/data.zip

где

  • USER - логин администратора CVAT
  • IP-ADRESS - ip-адрес сервера на котором располагается CVAT

для выполнения команды CVAT попросит нас ввести пароль администратора под логином которого мы выполняем данную команду.

Загрузим в CVAT val-подвыборку с помощью cvat-cli выполнив команду:

cvat-cli --auth USER --server-host IP-ADRESS --server-port 8080 create "RSTD_val" --labels data/interim/RTSD_cvat_val/label.json --image_quality 100 --annotation_path data/interim/RTSD_cvat_val/labels.xml --annotation_format "CVAT 1.1" local data/interim/RTSD_cvat_val/data.zip

Распределение классов в RTSD датасете

После этого средствами CVAT мы собрали статистику по встречаемости классов, оказалось, что некоторых классов пренебрежимо мало.

RTSD_train_subset_classes_distribution

Выбрали классы которые по количеству размеченных на них bbox составляли не менее 1% от всех bbox датасета.

Данные классы перечислены в include_classes.txt.

Фильтрация классов по количеству представителей

  • профильтруем датасет по классам, выполнив скрипт src/data/RTSD_dataset_CVAT_filter_by_labels.py для
    1. data/interim/RTSD_cvat_train
    2. data/interim/RTSD_cvat_val

получим датасеты только с тем классами, которые мы решили оставить:

  1. data/processed/RTSD_train_cvat_filtered
  2. data/processed/RTSD_val_cvat_filtered
  • создаем файл label.json описания классов для task на разметку в CVAT (src/data/create_labels_for_CVAT_json.py) для

    1. data/processed/RTSD_train_cvat_filtered
    2. data/processed/RTSD_val_cvat_filtered
  • архивируем папки с картинками (src/data/images_folder_arhivier.py) для

    1. data/processed/RTSD_train_cvat_filtered
    2. data/processed/RTSD_val_cvat_filtered

Загрузить данные с отобранными классами в CVAT

Загрузим в CVAT train-подвыборку с помощью cvat-cli выполнив команду:

cvat-cli --auth USER --server-host IP-ADRESS --server-port 8080 create "RSTD_train_filtered" --labels data/processed/RTSD_train_cvat_filtered/labels.json --image_quality 100 --annotation_path data/processed/RTSD_train_cvat_filtered/labels.xml --annotation_format "CVAT 1.1" local data/processed/RTSD_train_cvat_filtered/data.zip

где

  • USER - логин администратора CVAT
  • IP-ADRESS - ip-адрес сервера на котором располагается CVAT

Загрузим в CVAT val-подвыборку с помощью cvat-cli выполнив команду:

cvat-cli --auth USER --server-host IP-ADRESS --server-port 8080 create "RSTD_val_filtered" --labels data/processed/RTSD_val_cvat_filtered/labels.json --image_quality 100 --annotation_path data/processed/RTSD_val_cvat_filtered/labels.xml --annotation_format "CVAT 1.1" local data/processed/RTSD_val_cvat_filtered/data.zip

Преобразовать train и val подвыборки для обучения YOLOv8

Преобразуем датасеты с отобранными классами

  1. data/processed/RTSD_train_cvat_filtered
  2. data/processed/RTSD_val_cvat_filtered

в формат датасета YOLOv5 c помощью скрипта src/data/RTSD_dataset_CVAT_to_YOLOv5_convert.py.

В результате получим датасет data/processed/RSTD_filtered_yolov5, который будет содержать сразу train и val подвыборки.

Скачаем датасеты с отобранными классами

download dataset

cvat-cli --auth USER --server-host IP-ADRESS  --server-port 8080 dump --format "COCO 1.0" --with-images True 117 RTSD_val_coco.zip

Обучение моделей

Обучение моделей в целом

Для обучения модели запустим скрипт src/models/yolov8_train.py.

В результате была обучена модель на распознавание данных классов:

5.19.1 Пешеходный переход
2_1 Главная дорога
5_16 Автобусная остановка
3_24 Внимание, ограничение скорости
5_15_2 Обратите внимание на движение по полосам
2_4 Пожалуйста, уступите дорогу
3_27 Остановка запрещена
1_23 Осторожно, дети
4_1_1 Движение прямо
5_20 Внимание, Лежачий полицейский
3_20 Начало полосы
5_15_3 Однополосное движение переходитв двуполосное
5_15_1  Проверьте на какой полосе вы находитесь
5_15_2_2 Обратите внимание на полосу для поворота
1_17 Осторожно, возвышение на дороге
4_2_3 Объезд препятствия справа и слева
5_15_5 Конец полосы
4_2_1 Объезд препятствия справа
4_1_4 Движение прямо и направо
7_3 Автозаправка
6_4 Парковка
6_16 Остановитесь

Визуализация 20 кропов представителей каждого из классов classes_visualize

Визуализация получена последовательным применением скриптов

  • для вырезания указанного количества кропов с представителями каждого класса src/visualization/crop_bboxes_with_class_sample.py
  • для визуализации указанного количества кропов с представителями каждого класса src/visualization/visualize_classes_samples.py

на датасете для обучения YOLOv8.

Выбор моделей для обучения

Модель будет запускаться на мобильном устройстве (смартфон, планшет).

Вычисления будут производится на ЦПУ.

Согласно таблице сравнения ЦПУ в мобильных устройствах (рассматриваем устройства А-класса) (ссылка), современный ЦПУ смартфона имеет конфигурацию 6-8 с частотами 2.8-3.6 ГГц.

Эта конфигурация примерно соответствует имеющемуся ЦПУ на нашем сервере Intel Core i5-12600.

Мы знаем количество GFLOPS необходимое для вычисления предсказания на одной картинке для различных моделей YOLOv8.

Однако, FLOPS указывают в основном только для ГПУ.

Учитывая, что мощность нашего ЦПУ примерно сопоставима с мощностью топ смартфонов, мы решили померить производительность моделей на нем.

Важно оценить возможности моделей экспортированных в форматы ONNX и OpenVino для запуска на мобильных устройствах.

Были протестированы следующие подходы для оптимизации производительности модели:

  • PyTorch fuse - запуск PyTorch модели с layer fusion
  • ONNX - экспорт модели в ONNX
  • ONNX Simplify - экспорт модели в ONNX с последующей оптимизацией графа нейросети
  • ONNX Simplify half - экспорт модели в ONNX с последующей оптимизацией графа нейросети и квантизацией до float16
  • OpenVino - экспорт модели в OpenVino
  • OpenVino half - экспорт модели в OpenVino c квантизацией до float16

Сейчас мы хотим отобрать модели, которые могут работать на ЦПУ Intel Core i5-12600 в режиме реального времени.

Вначале проанализируем, экспорт моделей и потенциальную их производительность на конечном целевом устройстве.

Анализ модели YOLOv8s на COCO

Вначале оценим характеристики и опции экспорта моделей для мобильных устройств на примере yolov8s

Анализ произведен с помощью src/eval_models/eval_yolov8s_on_coco.py.

Результаты приведены для val части MS COCO 2017 в файле reports/report_coco_yolov8s_640.csv.

Все тесты производились на CPU 12th Gen Intel(R) Core(TM) i5-12600.

Рассмотрим их подробнее

model_name preprocess ms inference ms loss ms postprocess ms working_time ms bbox map50-95 bbox map50 bbox map75 size Mb
yolov8s_640_torch 0.17 48.52 0.0012 0.63 49.32 0.447 0.613 0.484 21.53
yolov8s_640_openvino 0.29 44.63 0.0016 0.83 45.74 0.447 0.612 0.485 42.87
yolov8s_640_openvino_half 0.28 44.10 0.0018 0.82 45.21 0.447 0.612 0.485 21.62
yolov8s_640_onnx 0.34 59.37 0.0017 0.95 60.67 0.447 0.612 0.485 42.76
yolov8s_640_onnx_simplify 0.36 61.87 0.0017 1.02 63.25 0.447 0.612 0.485 42.71
yolov8s_640_onnx_simplify_half 0.35 70.74 0.0016 1.06 72.16 0.447 0.612 0.485 42.71

Выводы:

  • текущая версия ultralytics==8.0.212 судя по времени работы моделей не реализует half-precision режим для инференса моделей ONNX и OpenVino. Эту опцию оптимизации можно исключить.
  • модель OpenVino является самой производительной из всех. При этом точность модели не снижается.
  • размер моделей ONNX и OpenVino в 2 раза превышает размер модели PyTorch.

Наиболее перспективным для запуска на мобильном устройстве выглядит использование OpenVino.

Анализ точности и производительности моделей YOLOv8 на COCO

Осуществим перебор всех моделей детекции из семейства YOLOv8 и оценим производительность на ЦПУ, чтобы понять какие модели мы будем обучать для нашего сервиса.

Анализ произведен с помощью src/eval_models/eval_yolos_on_coco.py.

Результаты приведены для val части MS COCO 2017 в файле reports/report_coco_yolos_640.csv

Все тесты производились на CPU 12th Gen Intel(R) Core(TM) i5-12600.

Рассмотрим их подробнее

model_name preprocess ms inference ms loss ms postprocess ms working_time ms bbox map50-95 bbox map50 bbox map75 size Mb
yolov8n_640_torch 0.23 19.86 0.0012 0.84 20.93 0.371 0.521 0.403 6.23
yolov8n_640_openvino 0.29 17.44 0.0017 1.03 18.76 0.370 0.521 0.403 12.34
yolov8n_640_onnx 0.34 25.65 0.0015 1.19 27.18 0.370 0.521 0.403 12.23
yolov8n_640_onnx_simplify 0.34 25.18 0.0015 1.16 26.68 0.370 0.521 0.403 12.18
yolov8s_640_torch 0.20 47.47 0.0014 0.65 48.32 0.447 0.613 0.484 21.53
yolov8s_640_openvino 0.30 44.19 0.0017 0.88 45.37 0.447 0.612 0.485 42.87
yolov8s_640_onnx 0.36 59.56 0.0016 1.00 60.92 0.447 0.612 0.485 42.76
yolov8s_640_onnx_simplify 0.34 62.06 0.0017 1.02 63.42 0.447 0.612 0.485 42.71
yolov8m_640_torch 0.21 112.96 0.0012 0.60 113.77 0.501 0.667 0.546 49.70
yolov8m_640_openvino 0.30 113.13 0.0018 0.79 114.22 0.500 0.666 0.545 99.12
yolov8m_640_onnx 0.37 140.90 0.0017 1.01 142.28 0.500 0.666 0.545 98.97
yolov8m_640_onnx_simplify 0.38 138.77 0.0017 1.07 140.22 0.500 0.666 0.545 98.92
yolov8l_640_torch 0.20 222.44 0.0014 0.58 223.23 0.529 0.695 0.576 83.70
yolov8l_640_openvino 0.28 225.77 0.0017 0.70 226.75 0.527 0.692 0.573 167.01
yolov8l_640_onnx 0.37 268.88 0.0016 1.02 270.27 0.527 0.692 0.573 166.81
yolov8l_640_onnx_simplify 0.38 284.15 0.0016 1.05 285.58 0.527 0.692 0.573 166.77
yolov8x_640_torch 0.20 336.45 0.0013 0.57 337.22 0.540 0.707 0.590 130.53
yolov8x_640_openvino 0.28 353.13 0.0017 0.70 354.12 0.537 0.703 0.586 260.59
yolov8x_640_onnx 0.36 418.36 0.0018 1.03 419.74 0.537 0.703 0.586 260.40
yolov8x_640_onnx_simplify 0.34 430.26 0.0016 1.03 431.64 0.537 0.703 0.586 260.35

В первую очередь для нас важно требование по производительности модели, working_time который обеспечивает FPS для работы в режиме реального времени. Этот параметр определяет с какими моделями мы можем работать. Оставляет, только те, которые могут выдавать не меньше 20 FPS.

Второй важный параметр bbox map50-95, чем более точнее модель работающая в режиме реального времени у нас будет, тем лучше.

Выводы:

  1. Для работы в реальном времени на ЦПУ подходят модели

    • YOLOv8n OpenVino 19 ms ~ 52 FPS. Данная модель будет хорошо работать на смартфонах со средними ЦПУ.
    • YOLOv8s OpenVino 46 ms ~ 21 FPS. Данная модель будет хоошо работать на современных смартфонах А-класса.
  2. От входного разрешения изображения зависит то насколько небольшие объекты сможет находить модель на кадре.

Многие смартфоны снимают разрешения:

  • 1280 × 720 HD
  • 1920 × 1080 Full HD

Модель YOLOv8n, с размером входной картинки 1024х1024:

  • будет различать примерно в 2 раза более меньшие объекты в кадре
  • при этом она будет медленее в 4 раза.

относительно аналогичной модели с входным разрешением 640х640.

Попробуем обучить 3 модели для решения нашей задачи:

  • YOLOv8n 640х640
  • YOLOv8n 1024х1024
  • YOLOv8s 640х640

Гиперпараметры обучения моделей

В целом модели семейства YOLOv8 имеют хорошие параметры обучения по умолчанию, которые подходят в большинстве случаев.

С учетом особенностей нашего сервера были выбраны такие:

  • epochs=20 - на моем опыте, обычно данного количества эпох, хватает для хорошего обучения модели. Если для хорошего обучения на самом деле нужно меньше эпох YOLOv8 отслеживает метрики и в случае исчезновения прогресса по их улучшению произведет остановку обучения модели самостоятельно. Если требуется больше эпох для обучения, мы поймем это по графикам метрик. 20 эпох хорошее начало.
  • patience=5 - если в течении 5 эпох нет улучшения метрик, останавливаем обучение. Данный параметр так же работает хорошо.
  • batch=32 - батч такого размера умещается на нашей ГПУ
  • workers=12 - соответсвует количеству логических ядер ЦПУ нашего сервера
  • seed=20 - фиксируем генератор случайных чисел

Наиболее интересным параметром выгледит размер входного изображения.

Как было описано ранее, стандартные модели с входным разрешением в 640х640 устраивают нас по производительности и обычно достаточно хорошо справляются с небольшими деталями в кадре, если размер кадра не превышает входное разрешение более чем в 2 раза по каждой из сторон.

Интересным выгледит попробовать входное разрешение 1024х1024 для модели YOLOv8n. При этом она сможет различать больше меньших деталей в кадре, но уровень ее производительности снизится до старшей модели YOLOv8s.

Анализ точности и производительности моделей на RSTD

Были обучены 3 модели для решения нашей задачи:

  • YOLOv8n 640х640
  • YOLOv8n 1024х1024
  • YOLOv8s 640х640

Данные обученные модели доступны для скачивания по ссылке.

Скачайте архив интересующей вас модели, и разархивируйте его в каталог models/models. Архив каждой модели так же содержит ее параметры заданные ей при обучении и метрики.

Результаты приведены для val части Russian traffic sign images dataset (RSTD) c Kaggle (ссылка) для детекции дорожных знаков России с сохранением 22 самых популярных классов дорожных знаков.

Анализ произведен с помощью src/eval_models/eval_yolos_on_rtsd.py.

Результаты приведены для val части Russian traffic sign images dataset (RSTD) в файле reports/report_rtsd_yolos.csv

Все тесты производились на CPU 12th Gen Intel(R) Core(TM) i5-12600.

model_name preprocess ms inference ms loss ms postprocess ms working_time ms bbox map50-95 bbox map50 bbox map75 size Mb
yolov8n_1024_torch 0.92 35.78 0.0013 0.35 37.05 0.752 0.974 0.911 5.98
yolov8n_1024_openvino 0.97 40.13 0.0016 0.51 41.62 0.750 0.972 0.908 11.94
yolov8n_1024_onnx 1.02 63.03 0.0015 0.77 64.82 0.750 0.972 0.908 11.94
yolov8n_1024_onnx_simplify 1.08 63.75 0.0016 1.00 65.83 0.750 0.972 0.908 11.79
yolov8n_640_torch 0.12 15.04 0.0012 0.28 15.44 0.696 0.938 0.832 5.93
yolov8n_640_openvino 0.27 16.97 0.0016 0.42 17.66 0.695 0.938 0.830 11.79
yolov8n_640_onnx 0.41 24.36 0.0015 0.68 25.44 0.695 0.938 0.830 11.69
yolov8n_640_onnx_simplify 0.30 24.58 0.0016 0.61 25.49 0.695 0.938 0.830 11.64
yolov8s_640_torch 0.12 36.90 0.0013 0.28 37.29 0.742 0.970 0.893 21.45
yolov8s_640_openvino 0.28 45.95 0.0016 0.41 46.65 0.738 0.967 0.888 42.78
yolov8s_640_onnx 0.34 59.14 0.0014 0.49 59.97 0.738 0.967 0.888 42.68
yolov8s_640_onnx_simplify 0.49 63.70 0.0016 0.98 65.17 0.738 0.967 0.888 42.63

Выводы:

  • yolov8n_640_openvino - дает хорошую точность, при этом работает быстро обеспечивая ~ 55 FPS
  • yolov8s_640_openvino - более высокий уровень точности, при этом работает быстро обеспечивая ~ 21 FPS
  • yolov8n_1024_openvino - дает даже более высокий уровень точности за счет распознавания небольших объектвов, при этом работает так же обеспечивая режим реального времени ~ 23 FPS

Интерес для использования в сервисе представляют все три модели:

  • yolov8n_640_openvino - позволит работать нашему сервису на бюджетных устройствах, обеспечив широкий охват аудитории.
  • yolov8s_640_openvino и yolov8n_1024_openvino смогу обеспечивать более высокую точность для устройств с мощным ЦПУ смартфонов А-класса.

Инференс класс для обученных нейронных сетей

Инференс класс представлен в src/models/YOLOv8_Detector_Inference.py.

Благодаря его методу predict_on_video_and_viz были сгенерированы демо видео сервиса помощника для водителя(ссылка).

Метрики работы сервиса

bbox map является хорошей метрикой для анализа точности предсказаний модели на отдельных кадрах из нашего датасета.

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

Нас интересует, был ли замечен дорожных знак, распознаваемого нашим сервисом типа, за все время нахождения знака в кадре видео?

Процесс расчета метрик похож на детекцию с поправкой на то, что мы рассматриваем все время существования знака в кадре видео:

  • true positive (TP) - хотя бы на одном кадре из всего трека данного знака он был задетектирован и определенный класс знака был верным.
  • false negative(FN) - ни на одном кадре из всего трека данного знака он не был задетектирован.
  • false positive(FP) - некоторый объект в кадре за время его появления в нем был ошибочно принят за дорожный знак.

Оценив TP, FP, FP мы сможем посчитать precision, recall и f1-меру.

Оценивать модели мы решили при непосредственном ручном просмотре видео с визуализацией предсказаний.

Анализ точности моделей на демо видео

С помощью инференс класса были сгенерированы демо видео работы каждой из трех моделей:

  • YOLOv8n 640х640
  • YOLOv8n 1024х1024
  • YOLOv8s 640х640

Для каждой из 3х видео записей с видеорегистратора с различными погодными условиями:

  • Дождливый день
  • Туманный день
  • Обычный день

Смотрите полные демо видео работы сервиса с тремя моделями на его YouTube-плейлисте (ссылка)

Мы решили оценивать все модели по видео Туманный день.

Результаты:

model_name TP FN FP precision recall f1
yolov8n_640 12 1 0 1 0.92 0.96
yolov8n_1024 12 1 0 1 0.92 0.96
yolov8s_640 13 0 0 1 1 1

Видно, что все модели обладают одинаковым precision, но отличаются по recall.

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

Модель yolov8n_1024 в данном тесте не оправдала возможенных на нее надежд, предоствляя precision сравнимую с yolov8n_640, при этом ее производительность сниается до уровня yolov8s_640, которая имеет более высокую recall и f1.

Однако это всего одно тестовое видео, датасет с более чем 95 тыс кадров показывает большой потенциал модели yolov8n_1024.

В целом радует, что в тестах сервиса на реальной видеозаписи в тяжелых погодных условиях - тумане, все отобранные модели работаю хорошо.

Выводы:

Интерес для использования в сервисе представляют все три модели:

  • yolov8n_640_openvino - позволит работать нашему сервису на бюджетных устройствах, обеспечив широкий охват аудитории.
  • yolov8s_640_openvino и yolov8n_1024_openvino смогу обеспечивать более высокую точность для устройств с мощным ЦПУ смартфонов А-класса.

About

Прототип помощника для водителей, который будет оповещать их о дорожных знаках.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published