1. PP-PicoDet

1.1. PicoDet介绍

PaddleDetection 中提出了全新的轻量级系列模型PP-PicoDet,在移动端具有卓越的性能。

PP-PicoDet详细的技术细节请参考 arXiv技术报告

接下来我们将在鲁班猫RK系列板卡上部署 PicoDet-S 模型。

1.2. 环境搭建

1、安装Paddle等环境

# 使用conda创建一个名为picodet的环境,并指定python版本
conda create -n picodet python=3.11

# 进入环境
conda activate picodet

然后安装相关工具:

# paddle
python -m pip install paddlepaddle==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/

paddlepaddle安装详细参考下 这里

2、安装rknn-Toolkit2

使用paddlepaddle训练保存的Paddle模型,在板卡上部署rknn模型,目前需要先转换成onnx,然后转成rknn模型。模型转换使用rknn-Toolkit2工具, 该工具安装参考下前面章节 RKNN Toolkit2

1.3. 模型转换

PP-PicoDet是轻量级实时移动端目标检测模型,该模型的介绍参考下 这里 。 教程测试picodet_s尺寸的模型,输入图像是416*416。

1、转换成onnx模型

rknn-Toolkit2暂时不支持Paddle模型直接导出为RKNN模型,需要使用Paddle2ONNX转成onnx模型,然后导出rknn模型。 在PC ubunut系统中:

# 启用虚拟环境
# 这里测试直接下载Paddle静态图模型并解压
wget https://paddledet.bj.bcebos.com/deploy/Inference/picodet_s_416_coco_lcnet.tar
tar xvf picodet_s_416_coco_lcnet.tar

# 静态图模型转换onnx模型,
cd tools/rknpu2/picodet_s_416_coco_lcnet/

paddle2onnx --model_dir picodet_s_416_coco_lcnet \
        --model_filename model.pdmodel \
        --params_filename model.pdiparams \
        --save_file picodet_s_416_coco_lcnet/picodet_s_416_coco_lcnet.onnx \
        --enable_dev_version True

# 固定shape
python -m paddle2onnx.optimize --input_model picodet_s_416_coco_lcnet/picodet_s_416_coco_lcnet.onnx \
                            --output_model picodet_s_416_coco_lcnet/picodet_s_416_coco_lcnet.onnx \
                            --input_shape_dict "{'image':[1,3,416,416]}"

# 最后模型保存在当前目录下picodet_s_416_coco_lcnet/picodet_s_416_coco_lcnet.onnx

2、导出RKNN模型

切换到获取的FastDeploy源码tools/rknpu2/目录下(或者从配套程序获取模型转换程序),并复制picodet_s_416_coco_lcnet到该目录下。

然后使用 Netron 可视化前面导出的onnx模型:

broken

找到NonMaxSuppression节点,确认输出节点名称,然后修改程序下面export_rknn.py中输出节点的名称(环境不同,转换模型的输出节点名称可能有所不同)。

export_rknn.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 省略...................
if __name__ == '__main__':
    model_path, platform, do_quant, output_path = parse_arg()

    # Create RKNN object
    rknn = RKNN(verbose=False)

    print('--> Config model')
    rknn.config(target_platform=platform, mean_values=[[123.675,116.28,103.53]], std_values=[[58.395,57.12,57.375]])
    print('done')

    # Load model
    print('--> Loading model')
    ret = rknn.load_onnx(
        model=model_path,
        inputs=["image", "scale_factor"],
        outputs = ["Div.1", "Concat.9"],
        input_size_list=[[1, 3, 416, 416], [1,2]],
    )
    if ret != 0:
        print('Load model failed!')
        exit(ret)
    print('done')

    # Build model
    print('--> Building model')
    ret = rknn.build(do_quantization=do_quant)
    if ret != 0:
        print('Build model failed!')
        exit(ret)
    print('done')

    # Export rknn model
    print('--> Export rknn model')
    ret = rknn.export_rknn(output_path)
    if ret != 0:
        print('Export rknn model failed!')
        exit(ret)
    print('done')

    # Release
    rknn.release()

模型转换的环境中需要安装rknn-Toolkit2(参考下前面 章节 ), 执行命令导出rknn模型:

# 参数
Usage: python3 export_rknn.py onnx_model_path [platform] [dtype(optional)] [output_rknn_path(optional)]
   platform choose from [rk3566, rk3568, rk3576, rk3588]
   dtype choose from [fp] for [rk3566, rk3568, rk3576, rk3588]

# 测试设置platform参数:如果是lubancat-3设置rk3576,lubancat-4/5设置 rk3588,lubancat-2设置rk3568,lubancat-0设置rk3566
# 教程测试lubancat-4,设置rk3588
(toolkit2_2.3.2) llh@llh:/xxx$ python export_rknn.py ./picodet_s_416_coco_lcnet/picodet_s_416_coco_lcnet.onnx  rk3588 fp ./picodet_3588.rknn
I rknn-toolkit2 version: 2.3.2
--> Config model
done
--> Loading model
W load_onnx: If you don't need to crop the model, don't set 'inputs'/'input_size_list'/'outputs'!
I Loading : 100%|█████████████████████████████████████████████| 490/490 [00:00<00:00, 374423.20it/s]
done
--> Building model
I OpFusing 0: 100%|██████████████████████████████████████████████| 100/100 [00:00<00:00, 589.89it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 327.13it/s]
I OpFusing 0 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 212.46it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 202.78it/s]
I OpFusing 2 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 192.71it/s]
I OpFusing 0 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 182.16it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 175.25it/s]
I OpFusing 2 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 129.93it/s]
# 省略........
I rknn building done.
done
--> Export rknn model
done

将会在当前目录下生成picodet_3588.rknn模型文件,然后使用 Netron 查看模型的输入输出:

broken

1.4. 部署模型

在板卡上拉取例程,并将前面转换的rknn模型传输到板卡,然后放到例程的model目录下。

# 安装相关库等等
sudo apt install gcc cmake g++ libsndfile1-dev git

# 获取程序,例程可能没有及时更新
git clone https://gitee.com/LubanCat/lubancat_ai_manual_code.git
cd lubancat_ai_manual_code/example/picodet/cpp

# 然后复制前面转换获取的rknn模型到model目录下

# 直接编译例程,如果是鲁班猫3设置-t rk3576,鲁班猫4和5设置-t rk3588,教程测试鲁班猫4
# -r参数设置是否使用librga进行图像处理,默认不加表示使用librga
cat@lubancat:~/lubancat_ai_manual_code/example/picodet/cpp$ ./build-linux.sh -t rk3588
./build-linux.sh -t rk3588
===================================
TARGET_SOC=rk3588
INSTALL_DIR=/home/cat/lubancat_ai_manual_code/example/picodet/cpp/install/rk3588_linux
BUILD_DIR=/home/cat/lubancat_ai_manual_code/example/picodet/cpp/build/build_rk3588_linux
DISABLE_RGA=OFF
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
===================================
-- The C compiler identification is GNU 13.3.0
-- The CXX compiler identification is GNU 13.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/aarch64-linux-gnu-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
# 省略.............
[ 66%] Linking C static library libimageutils.a
[ 66%] Built target imageutils
[ 75%] Building CXX object CMakeFiles/picodet_demo.dir/postprocess.cc.o
[ 83%] Building CXX object CMakeFiles/picodet_demo.dir/picodet_demo.cc.o
# 省略.............
[ 33%] Built target fileutils
[ 50%] Built target imagedrawing
[ 83%] Built target picodet_demo
[100%] Built target audioutils
Install the project...
-- Install configuration: ""
# 省略.............
-- Installing: /home/cat/lubancat_ai_manual_code/example/picodet/cpp/install/rk3588_linux/./model/coco_80_labels_list.txt
-- Installing: /home/cat/lubancat_ai_manual_code/example/picodet/cpp/install/rk3588_linux/lib/librknnrt.so
-- Installing: /home/cat/lubancat_ai_manual_code/example/picodet/cpp/install/rk3588_linux/lib/librga.so

生成了推理可执行程序picodet_demo ,获取测试图片,然后推理测试。

# 复制推理参数文件、模型文件和推理可执行程序,存放到一个目录下
cat@lubancat:~/xxx/install/rk3588_linux$ ls
lib  model  picodet_demo

# 拉取测试图片,或者使用默认model目录下的测试图像
cat@lubancat:~/xxx/test$ wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg

# 执行程序
# ./picodet_demo <model_path> <image_path>
cat@lubancat:/xxx/install/rk3588_linux$ ./picodet_demo ./model/picodet_rk3588.rknn  000000014439.jpg
load lable ./model/coco_80_labels_list.txt
model input num: 2, output num: 2
input tensors:
index=0, name=image, n_dims=4, dims=[1, 416, 416, 3], n_elems=519168, size=1038336, fmt=NHWC, type=FP16,
qnt_type=AFFINE, zp=0, scale=1.000000, ,size_with_stride=1038336, w_stride=416
index=1, name=scale_factor, n_dims=2, dims=[1, 2, 0, 0], n_elems=2, size=4, fmt=UNDEFINED, type=FP16,
qnt_type=AFFINE, zp=0, scale=1.000000, ,size_with_stride=4, w_stride=0
output tensors:
index=0, name=Div.1, n_dims=3, dims=[1, 3598, 4, 0], n_elems=14392, size=28784, fmt=UNDEFINED, type=FP16,
 qnt_type=AFFINE, zp=0, scale=1.000000, ,size_with_stride=28784, w_stride=0
index=1, name=Concat.9, n_dims=3, dims=[1, 80, 3598, 0], n_elems=287840, size=575680, fmt=UNDEFINED,
 type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000, ,size_with_stride=575680, w_stride=0
model is NHWC input fmt
model input height=416, width=416, channel=3
origin size=640x404 crop size=640x400
input image: 640 x 404, subsampling: 4:4:4, colorspace: YCbCr, orientation: 1
rga_api version 1.10.1_[0]
-- inference_picodet_model use: 65.624001 ms
person @ (159 84 201 167) 0.819
person @ (413 90 510 283) 0.806
person @ (264 81 299 170) 0.787
person @ (105 47 127 94) 0.754
person @ (584 116 613 179) 0.691
person @ (327 41 344 81) 0.625
person @ (378 43 395 84) 0.583
person @ (510 116 598 277) 0.541
kite @ (163 88 598 345) 0.584
write_image path: out.png width=640 height=404 channel=3 data=0xaaaadc0c5dc0

简单测试结果显示:

broken

以上就是在鲁班猫RK系列板卡上部署PicoDet-S模型,详细程序请查看教程 配套例程 ,可自行去优化。