~~tag> NPU YOLO OpenCV VIM4 ~~
====== YOLOv8n OpenCV VIM4 Demo - 2 ======
{{indexmenu_n>2}}
===== Get Source Code =====
Download YOLOv8 official code [[gh>ultralytics/ultralytics]]
```shell
$ git clone https://github.com/ultralytics/ultralytics
```
Refer ''README.md'' to train a YOLOv8n model. My version ''torch==1.10.1'' and ''ultralytics==8.0.86''.
===== Convert Model =====
==== Build virtual environment ====
Follow Docker official documentation to install Docker: [[https://docs.docker.com/engine/install/ubuntu/|Install Docker Engine on Ubuntu]].
Follow the script below to get Docker image:
```shell
docker pull numbqq/npu-vim4
```
===== Get Convert Tool =====
```shell
$ git lfs install
$ git lfs clone https://gitlab.com/khadas/vim4_npu_sdk.git
$ cd vim4_npu_sdk
$ ls
adla-toolkit-binary adla-toolkit-binary-1.2.0.9 convert-in-docker.sh Dockerfile docs README.md
```
* ''adla-toolkit-binary/docs'' - SDK documentations
* ''adla-toolkit-binary/bin'' - SDK tools required for model conversion
* ''adla-toolkit-binary/demo'' - Conversion examples
==== Get Model Conversion Tools ====
Get source [[gl>khadas/vim4_npu_sdk]].
```shell
$ git clone https://gitlab.com/khadas/vim4_npu_sdk
```
==== Convert ====
After training model, modify ''ultralytics/ultralytics/nn/modules/head.py'' as follows.
```diff head.py
diff --git a/ultralytics/nn/modules/head.py b/ultralytics/nn/modules/head.py
index 0b02eb3..0a6e43a 100644
--- a/ultralytics/nn/modules/head.py
+++ b/ultralytics/nn/modules/head.py
@@ -42,6 +42,9 @@ class Detect(nn.Module):
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)
+
shape = x[0].shape # BCHW
for i in range(self.nl):
x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)
@@ -80,6 +83,15 @@ class Detect(nn.Module):
a[-1].bias.data[:] = 1.0 # box
b[-1].bias.data[:m.nc] = math.log(5 / m.nc / (640 / s) ** 2) # cls (.01 objects, 80 classes, 640 img)
+ 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).permute(0, 2, 3, 1))
+ # results.append(torch.cat([cls, dfl], 1))
+ return tuple(results)
+
```
If you pip-installed ultralytics package, you should modify in package.
Create a python file written as follows to export ONNX model.
```python export.py
from ultralytics import YOLO
model = YOLO("./runs/detect/train/weights/best.pt")
results = model.export(format="onnx")
```
```shell
$ python export.py
```
Use [[https://netron.app/ | Netron]] to check your model output like this. If not, please check your ''head.py''.
{{:products:sbc:vim4:npu:demos:yolov8n-vim4-output.png?600|}}
Enter ''vim4_npu_sdk/demo'' and modify ''convert_adla.sh'' as follows.
```sh convert_adla.sh
#!/bin/bash
ACUITY_PATH=../bin/
#ACUITY_PATH=../python/tvm/
adla_convert=${ACUITY_PATH}adla_convert
if [ ! -e "$adla_convert" ]; then
adla_convert=${ACUITY_PATH}adla_convert.py
fi
$adla_convert --model-type onnx \
--model ./model_source/yolov8n/yolov8n.onnx \
--inputs "images" \
--input-shapes "3,640,640" \
--dtypes "float32" \
--quantize-dtype int16 --outdir onnx_output \
--channel-mean-value "0,0,0,255" \
--source-file dataset.txt \
--batch-size 1 --target-platform PRODUCT_PID0XA003
```
Run ''convert_adla.sh'' to generate VIM4 model. The converted model is ''xxx.adla'' in ''onnx_output''.
```shell
$ bash convert_adla.sh
```
===== Run NPU =====
==== Get source code ====
Clone the source code from our [[gh>khadas/vim4_npu_applications]].
```shell
$ git clone https://github.com/khadas/vim4_npu_applications
```
==== Install dependencies ====
```shell
$ sudo apt update
$ sudo apt install libopencv-dev python3-opencv cmake
```
==== Compile and run ====
=== Picture input demo ===
Put ''yolov8n_int8.adla'' in ''vim4_npu_applications/yolov8n/data/''.
```shell
# Compile
$ cd vim4_npu_applications/yolov8n
$ mkdir build
$ cd build
$ cmake ..
$ make
# Run
$ sudo ./yolov8n -m ../data/yolov8n_int8.adla -p ../data/horses.jpg
```
=== Camera input demo ===
Put ''yolov8n_int8.adla'' in ''vim4_npu_applications/yolov8n_cap/data/''.
```shell
# Compile
$ cd vim4_npu_applications/yolov8n_cap
$ mkdir build
$ cd build
$ cmake ..
$ make
# Run
$ sudo ./yolov8n_cap -m ../data/yolov8n_int8.adla -d 0 -w 1920 -h 1080
```
''0'' is camera device index.
If your **YOLOv8n** model classes are not the same as **COCO**, please change ''data/coco_80_labels_list.txt'' and the ''OBJ_CLASS_NUM'' in ''include/postprocess.h''.