最近的任务是用C++在板子上部属目标检测算法,板子的完整名称是AIO-3399pro-JD4,如果你的核心板是3399pro,那使用方法应该是一样的。
先吐槽一下firefly供应商的文档乱七八糟,各版本也不兼容,驱动的使用方法也没有教程的,而且问FAE技术支持回答也是有一句没一句。所以我有必要记录一下。
板子的连接方法可以通过网线,或者adb连接,ubuntu其实就是连接typeC接口,然后通过下面命令连接即可。
adb shell
软件方面需要明确几个概念:
1、固件,系统固件和驱动固件,一般是img等文件格式,其实就是要烧录的系统和驱动包。
2、rknpu,开发板硬件npu的驱动程序,一般在npu_fw文件夹下,可以 通过locate命令查看一下。
3、rknn toolkit,rknn即瑞星微npu上使用的神经网络模型,rknn toolkit是其python开发包,onnx格式模型转出rknn需要用到。
4、rknn api,rknn的C++开发包。
要想使用npu部属深度学习算法,要安装系统固件和rknpu和rknnapi,rknn toolkit作为转换工具可以装在电脑上。rknpu驱动,rknn toolki和rknn api版本最好要一致,不一致的版本也许能成功也许不行,具体可以尝试(博主1.7.3rknpu运行1.7.5的代码没问题)。
我首先参考的是知乎链接yolov5-6.2 在 rk3399pro 上的移植,但是最终没有实现,在yolov5模型export转换的时候有问题,导致后面onnx转rknn出现错误。可以参考一下,里面一些解释写的很清楚,虽然复现有bug。
根据我的步骤应该不会有错误,正式的训练和部属流程分为以下几个步骤:1. 标注数据和训练yolov5模型;2.模型导出ONNX;3.ONNX导出RKNN;4.模型部属C++端。
1、标注数据和模型训练
训练环境的安装就正常安装yolov5的环境。数据标注使用工具labelImg,百度一下很多教程,不再解释。博主自己训练使用6.2版本的yolov5,也可以使用官方的yolov5,以防出现问题,推荐使用firefly提供的版本:firefly的yolov5。
2、模型导出onnx
firefly提供的版本firefly的yolov5 与官方的yolov5模型不同的是export导出部分,作用是将yolov5训练的pt转化为onnx。
进入airock_yolov5主目录,执行命令
python export.py --rknpu --weight yolov5s.pt
得到的onnx模型可导入netron查看模型结构,如下图所示。记住右下角的343,345节点。
3、onnx转rknn
onnx转化为rknn需要rknn toolkit,也就是python环境,官方提供了一个链接,有两种方法:(1)直接在python环境中安装;(2)docker环境。但是本人尝试第一种方法会报错,所以推荐使用第二种方法,如下图所示。
在下载的包中需要找一下,找/rknn-toolkit-1.7.5/docker/rknn-tookkit.docker.tar.gz,提取出来,如下图所示。
使用命令构建docker容器:
docker load --input rknn-toolkit-1.7.3-docker.tar.gz
导入完成后执行 docker images,将看到 toolkit-1.7.5 镜像
执行以下命令,启动docker容器
docker run -t -i --privileged -v $PWD:/test rknn-toolkit:1.7.3 /bin/bash
其中 -v $PWD:/test 是指把当前目录映射到docker容器的/test目录内,这样当要和docker容器内部进行文件传输时,只需把需要传输的文件放到当前目录,就能在 docker 容器内的 /test 目录看到,反之亦然。执行成功后,将自动进入docker容器内
可以看到已经有一个 test 目录,test 目录的内容就是服务器当前目录的内容。
在挂载的当前目录中新建onnx2rknn.py:
from rknn.api import RKNN
ONNX_MODEL = './bbab.onnx'
platform = "rk3399pro"
RKNN_MODEL = 'rrrr_yolov5s_a_{}_out_opt.rknn'.format(platform)
if __name__ == '__main__':
add_perm = False # 如果设置成True,则将模型输入layout修改成NHWC
# Create RKNN object
rknn = RKNN(verbose=True)
# pre-process config
print('--> config model')
rknn.config(batch_size=1, mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], reorder_channel='0 1 2', target_platform=[platform],
force_builtin_perm=add_perm, output_optimize=1)
print('done')
# Load tensorflow model
print('--> Loading model')
ret = rknn.load_onnx(model=ONNX_MODEL,outputs=['output0', '343', '345'])# 这里一定要根据onnx模型修改
if ret != 0:
print('Load onnx model failed!')
exit(ret)
print('done')
# Build model
print('--> Building model')
ret = rknn.build(do_quantization=True, dataset='./dataset.txt')
if ret != 0:
print('Build rkmodel failed!')
exit(ret)
print('done')
# rknn.export_rknn_precompile_model(RKNN_MODEL)
rknn.export_rknn(RKNN_MODEL)
rknn.release()
将上方ONNX_MODEL和RKNN_MODEL替换为自己的模型名称,运行该python脚本即可导出rknn。
4.模型部属C++端
参考 C++模型部属,原版依赖cimg和tga图像库,我做了一些修改,项目链接,项目结构如图
3rdparty是第三方依赖库,主要包括firefly提供的图像处理工具库(rga,cimg等)
librknn_api是3399pro的C++api,部属算法必需的库
rknn_yolov5_demo是官方提供的案例,其中加载图像数据使用到了3rdparty中的库
rknn_yolov5_opencv是我自己写的案例,用opencv替换了rga,cimg等函数
使用方法:
cd rknn_yolov5_opencv
cmake -S . -B build
cmake --build build
./build/rknn_yolov5_demo ./model/best8_rk3399pro.rknn ./model/sonarimg110.jpg
参考链接:
知乎:https://zhuanlan.zhihu.com/p/592304551
官方资料:1. NPU开发简介 — Firefly Wiki
YOLOV5:GitHub - airockchip/yolov5: YOLOv5 in PyTorch > ONNX > CoreML > TFLite
C++模型部属:
https://github.com/airockchip/rknn_model_zoo/tree/main/examples/yolov5
RKNN API(C++依赖):GitHub - airockchip/RK3399Pro_npu
RKNN TOOLKIT(python导出rknn):GitHub - rockchip-linux/rknn-toolkit