12. YOLOv8(旋转目标检测)¶
YOLOv8 OBB 模型是YOLOV8中的一个变体, 专门设计用于检测具有方向的边界框(Oriented Bounding Boxes,OBB),相比传统的水平矩形边界框(Horizontal Bounding Boxes,HBB), OBB模型能够更准确地识别有角度或旋转的物体,适用于航空影像、文本检测等领域。
YOLOv8-OBB模型是在 DOTAv1 数据集上训练。 DOTAv1数据集有15个类别,总共有2800多张图像,图像分辨率从800*800到20000*20000不等。
YOLOv8-OBB不同尺寸模型性能对比:
本章将在鲁班猫rk系列板卡上简单测试YOLOv8n-obb模型。
12.1. YOLOv8安装¶
使用conda创建虚拟环境,然后安装ultralytics。
# 使用conda创建虚拟环境
conda create -n yolov8 python=3.9
conda activate yolov8
# 安装YOLOv8,直接使用命令安装
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装成功后,使用命令yolo简单看下版本
(yolov8) llh@anhao:/$ yolo version
8.2.96
12.2. YOLOv8-OBB简单测试¶
YOLOv8n-obb模型推理测试(使用python编程):
1 2 3 4 5 6 7 | from ultralytics import YOLO
# Load a model
model = YOLO("./yolov8n-obb.pt")
# Predict with the model
results = model("./test.jpg", save=True) # predict on an image
|
# 手动下载yolov8n-obb.pt
(yolov8) llh@anhao: wget https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8n-obb.pt
# 推理测试
(yolov8) llh@anhao: python yolov8_obb.py
image 1/1 /xxx/yolov8/test.jpg: 1024x1024 41.5ms
Speed: 8.6ms preprocess, 41.5ms inference, 126.2ms postprocess per image at shape (1, 3, 1024, 1024)
Results saved to runs/obb/predict
前往runs/obb/predict目录下查看结果:
更多YOLOv8-OBB测试请参考 ultralytics文档 。
12.3. 模型转换¶
使用 airockchip/ultralytics_yolov8 导出适合部署到rknpu上的模型,模型的改动:
修改输出结构, 移除后处理结构(后处理结果对于量化不友好);
dfl结构在NPU处理上性能不佳,移至模型外部的后处理阶段,此操作大部分情况下可提升推理性能;
获取自行训练或者官方的yolov8n-obb模型,根据模型路径调整./ultralytics/cfg/default.yaml中model参数,然后导出模型:
(yolov8) llh@anhao: cd ultralytics_yolov8
(yolov8) llh@anhao: export PYTHONPATH=./
(yolov8) llh@anhao: python ./ultralytics/engine/exporter.py
Update settings with 'yolo settings key=value', i.e. 'yolo settings runs_dir=path/to/dir'.
For help see https://docs.ultralytics.com/quickstart/#ultralytics-settings.
Ultralytics YOLOv8.2.82 🚀 Python-3.9.19 torch-2.4.1+cu121 CPU (Intel Core(TM) i7-14700F)
YOLOv8n-obb summary (fused): 187 layers, 3,080,144 parameters, 0 gradients, 8.3 GFLOPs
PyTorch: starting from '../yolov8n-obb.pt' with input shape (16, 3, 640, 640) BCHW and output shape(s) ((), (16, 1, 8400)) (6.3 MB)
RKNN: starting export with torch 2.4.1+cu121...
RKNN: feed ../yolov8n-obb.onnx to RKNN-Toolkit or RKNN-Toolkit2 to generate RKNN model.
Refer https://github.com/airockchip/rknn_model_zoo/tree/main/models/CV/object_detection/yolo
RKNN: export success ✅ 0.4s, saved as '../yolov8n-obb.onnx' (11.8 MB)
Export complete (3.1s)
Results saved to /mnt/e/work/yolov8
Predict: yolo predict task=obb model=../yolov8n-obb.onnx imgsz=640
Validate: yolo val task=obb model=../yolov8n-obb.onnx imgsz=640 data=runs/DOTAv1.0-ms.yaml
Visualize: https://netron.app
可以使用 netron 查看导出的onnx模型的网络结构:
以yolov8n-obb模型,输入为1*3*640*640为例,yolov8旋转目标检测的模型网络结构,主干部分和yolov8目标检测完全一致,主要是Head部分有区别。 旋转目标检测除了生成3个预测框的特征图(1*64*80*80、1*64*40*40、1*64*20*20)以及3个类别置信度特征图(1*15*80*80、1*15*40*40、1*15*20*20), 还有一个用来预测旋转角度的特征图(1*1*80*80、1*1*40*40、1*1*20*20)。
适配rknn的模型, 输出3个预测框的特征图和类别置信度特征图(1*79*80*80、1*79*40*40、1*79*20*20)和预测旋转角度的特征图(1*1*8400)
12.3.1. 导出rknn模型¶
导出的yolov8-pose模型,使用toolkit2工具将其转换成rknn模型。 如果是lubancat-4/5,模型转换目标设置rk3588,如果是lubancat-0/1/2,需要设置目标为rk3566/rk3568。
# 获取配套例程的转换程序onnx2rknn.py
# python onnx2rknn.py <onnx_model> <TARGET_PLATFORM> <dtype(optional)> <output_rknn_path(optional)>
(toolkit2.2) llh@anhao:/xxx/yolov8$ python onnx2rknn.py ./yolov8n-obb.onnx rk3588 i8
I rknn-toolkit2 version: 2.2.0
--> Config model
done
--> Loading model
I Loading : 100%|██████████████████████████████████████████████| 144/144 [00:00<00:00, 62699.03it/s]
done
--> Building model
I OpFusing 0: 100%|██████████████████████████████████████████████| 100/100 [00:00<00:00, 556.30it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 459.83it/s]
I OpFusing 2 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 213.57it/s]
I GraphPreparing : 100%|███████████████████████████████████████| 175/175 [00:00<00:00, 10597.95it/s]
I Quantizating : 100%|████████████████████████████████████████████| 175/175 [00:16<00:00, 10.66it/s]
# 省略............
I rknn building ...
I rknn buiding done.
done
--> Export rknn model
output_path: ./yolov8_obb.rknn
done
12.4. 部署测试¶
板卡上编译测试例程:
# 获取教程配套例程,也可以https://github.com/airockchip/rknn_model_zoo 获取测试例程,需要注意测试例程编译方式不同。
# 其中-t指定目标设备,这里测试使用lubancat-4,设置rk3588,如果是lubancat-0/1/2就设置rk356x
# 如果系统内存大于4G的,设置参数-d
cat@lubancat:~/xxx/example/yolov8_obb$ ./build-linux.sh -t rk3588 -d
./build-linux.sh -t rk3588 -d
===================================
TARGET_SOC=rk3588
INSTALL_DIR=/xxx/yolov8-obb/cpp/install/rk3588_linux
BUILD_DIR=/xxx/yolov8-obb/cpp/build/build_rk3588_linux
ENABLE_DMA32=TRUE
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
===================================
-- !!!!!!!!!!!CMAKE_SYSTEM_NAME: Linux
-- Configuring done
-- Generating done
-- Build files have been written to: /xxx/yolov8-obb/cpp/build/build_rk3588_linux
[ 16%] Built target fileutils
[ 33%] Built target audioutils
[ 50%] Built target imagedrawing
[ 66%] Built target imageutils
[100%] Built target yolov8_obb_image_demo
# 省略..........
重要
部署使用的librknnrt库的版本需要与模型转换的Toolkit2的版本一致。
编译输出程序在当前目录的install/rk3588_linux中,测试yolov8_obb_image_demo例程:
cat@lubancat:~/xxx/install/$ ./yolov8_obb_image_demo ./model/yolov8_obb.rknn ./model/test.jpg
load lable ./model/yolov8_obb_labels_list.txt
model input num: 1, output num: 4
input tensors:
index=0, name=images, n_dims=4, dims=[1, 640, 640, 3], n_elems=1228800, size=1228800, fmt=NHWC, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
output tensors:
index=0, name=383, n_dims=4, dims=[1, 79, 80, 80], n_elems=505600, size=505600, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=65, scale=0.209463
index=1, name=398, n_dims=4, dims=[1, 79, 40, 40], n_elems=126400, size=126400, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=68, scale=0.202605
index=2, name=413, n_dims=4, dims=[1, 79, 20, 20], n_elems=31600, size=31600, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=42, scale=0.142794
index=3, name=414, n_dims=3, dims=[1, 1, 8400, 0], n_elems=8400, size=8400, fmt=UNDEFINED, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.002982
model is NHWC input fmt
model input height=640, width=640, channel=3
origin size=640x640 crop size=640x640
input image: 640 x 640, subsampling: 4:2:0, colorspace: YCbCr, orientation: 1
scale=1.000000 dst_box=(0 0 639 639) allow_slight_change=1 _left_offset=0 _top_offset=0 padding_w=0 padding_h=0
src width=640 height=640 fmt=0x1 virAddr=0x0x7fb2f9b010 fd=0
dst width=640 height=640 fmt=0x1 virAddr=0x0x7fb2e6f000 fd=8
src_box=(0 0 639 639)
dst_box=(0 0 639 639)
color=0x72
rga_api version 1.10.0_[2]
rknn_run
ship @ (289 539 20 68 angle=0.507482) 0.835
# 省略............
ship @ (348 229 16 58 angle=0.488744) 0.740
ship @ (390 587 19 55 angle=0.432532) 0.740
write_image path: out.png width=640 height=640 channel=3 data=0x7fb2f9b010
测试结果保存在当前目录下: