rodion02 / yolov5_khadas

0 stars 1 forks source link

Данное руководство предназначенно для работы с khadas Vim3 Pro и запуска на этой модели нейронных сетей при помощи фреймфорка

KSNN

Оглавление:

Запуск примера
Работа с кастомным датасетом
Конвертация весов
Ускорение алгоритма

Запуск примера

Для начала нужно установить на khadas последнюю версию ubuntu с официального сайта. Как только у нас появился образ, давайте установим все необходимые репозитории (он всего один):

```sh $ git clone https://github.com/khadas/ksnn ``` Следуем инструкциям: ```sh $ sudo apt install python3-pip $ pip3 install matplotlib ``` На данный момент актуальной является 1.4 версия, так что я поставил её ```sh $ pip3 install ksnn/ksnn-1.4-py3-none-any.whl ``` В репозитории ksnn есть папка examples с примерами различных сеток, нас тут интересует yolov8n (полный путь ksnn/examples/yolov8n/). yolov8n-picture.py для одиночных изображений, а yolov8n-cap.py уже для потока видео с камеры. В папках ./libs/ и ./models/VIM3/ находятся примеры скомпилированной библиотеки - libnn_yolov8n.so и конвертированных весов оригональной модели yolov8n - yolov8n.nb. yolov8n-picture.py: ```sh $ python3 yolov8n-picture.py --model ./models/VIM3/yolov8n.nb --library ./libs/libnn_yolov8n.so --picture ./data/horses.jpg ``` yolov8n-cap.py ```sh $ python3 yolov8n-cap.py --model ./models/VIM3/yolov8n.nb --library ./libs/libnn_yolov8n.so --device X ``` В параметр **model** мы передаем путь к .nb файлу В параметр **library** мы передаем путь к .so файлу **picture** ожидает путь к изображению, а **device** номер камеры

Работа с кастомным датасетом

Для обучения и последующей конвертации нам потребуется стороннее устройство, я лично использовал ноутбук с Ubuntu 22.04.
Yolov8 Ultralitics
Для начала необходимо установить Yolov8:

Затем следуем инструкциям с официального сайта и меняем по инструкции файл head.py (полный путь ultralytics/nn/modules/head.py) 42 строчка (добавляем 2 строки): ```sh def forward(self, x): """Concatenates and returns predicted bounding boxes and class probabilities.""" if torch.onnx.is_in_onnx_export(): return self.forward_export(x) ``` 84 строчка (добавляем новый метод): ```sh def forward_export(self, x): results = [] for i in range(self.nl): dfl = self.cv2[i](x[i]).contiguous() cls = self.cv3[i](x[i]).contiguous() results.append(torch.cat([cls, dfl], 1)) return tuple(results) ``` Или можно вставить уже измененный файл. Теперь нужно установить библиотеку Yolov8 ```sh pip install ultralytics ``` Теперь начнём обучение: ```sh from ultralytics import YOLO # Загружаем модель model = YOLO('yolov8n.pt') # берем предобученную ``` Обучать можно как на GPU: ```sh results = model.train(data='coco128.yaml', epochs=100, imgsz=640, batch=4, imgsz=640, device=0) ``` (по умолчанию batch=16, так что если система не особо производительная, то лучше его взять меньше) Так и с помощью CPU: ```sh results = model.train(data='coco128.yaml', epochs=100, imgsz=640) ``` Более подробно всё описано тут.
Конвертация весов
После обучения мы получим .pt веса, которые нам нужно конвертировать в .onnx ```sh from ultralytics import YOLO model = YOLO("./runs/detect/train/weights/best.pt") results = model.export(format="onnx") ``` Теперь по инструкции устанавливаем репозиторий:

```sh $ git clone --recursive https://github.com/khadas/aml_npu_sdk.git ``` Переходим в ```sh $ cd aml_npu_sdk/acuity-toolkit/python ``` тут нас интересует convert, с помощью которого мы и будем конвертировать наши веса. Сразу подготовьте .onnx файл с весами и папку с колибрационным набором изображений для датасета (5% от всего набора, я беру не больше 100) и .txt файл, в котором будут прописаны пути к каждому изображению (.../data/image1.jpg итд) ```sh $ ./convert \ --model-name yolov8n \ --platform onnx \ --model ./yolov8n.onnx \ --mean-values '0 0 0 0.00392156' \ --quantized-dtype asymmetric_affine \ --source-files ./data/dataset.txt \ --kboard VIM3 \ --print-level 1 ``` **model-name** - название для выходного файла **platform** - формат весов (для yolo это onnx) **model** - путь к весам **mean-values** - средние значения R, G и B каналов по вашему датасету. Про то, как их вычислить можно прочитать тут, но помните что эти значения. **quantized-dtypes** - способы квантования (оставьте лучше тот, что в примере). **source-files** - путь к файлу с путями к изображениям из колибрационного датасета. В результате мы получим yolov8n.nb и yolov8n.so файлы в папке outputs (полный путь aml_npu_sdk/acuity-toolkit/python/outputs) Теперь можно запустить и посмотреть на примеры работы алгоритма с вашими данными как в самом начале.

Ускорение алгоритма

Основной алгоритм обрабатывает изображение за 300ms, из которых 260ms уходят на post-process. Я это ускоряю при помощи библиотеки **numba** и некоторого изменения исходного кода. Чтобы запустить мой алгоритм необходимо передать ему некоторые параметры: ```sh $ python3 ./khadas_stream.py \ --library ./yolov8n.so \ --model ./yolov8n.nb \ --source 0 \ --visualize 0 \ --conf ./data.json \ --level 1 ``` **library** - путь к .so библиотеке. **model** - путь к .nb весам. **source** - либо номер камеры (0, 1 итд) или ссылка на stream/ip камеру. **visualize** - демонмтрировать ли результат работы камеры, по умолчанию False, чтобы не тпатить на это ресурсы. **conf** - путь к конфигурационному файлу .json, который содержит имена классов и доп. настройки. data.json: ``` { "CLASSES":["class1", "class2'...], "SETTINGS":{ "SPAN": 1, "MAX_BOXES": 500, "OBJ_THRESH": 0.4, "NMS_THRESH": 0.5} } ``` То есть для внесения изменений вам не нужно трогать .py файл, достаточно внести изменения в .json файл. С файлом обязательно должен быть res.py так как при запуске алгоритм компилируется и ему нужны данные из этого Или можно вставить уже измененный файл.