赞
踩
将自己训练的目标检测模型【YOLO-V5s】移植到瑞芯微【3566】芯片平台,使用NPU推理,最终得到正确的结果。整个过程涉及模型量化、转换,C++部署。
芯片参数介绍:https://www.rock-chips.com/a/cn/product/RK35xilie/2021/0113/1273.html
CPU:四核,1.8GHZ.
NPU:1TOPs@Int8,每秒一万亿次运算。
通常每一款芯片都有其对应的使用文档和工具链,以此作为开发的参考。通过官方文档,可以确认开发环境(Ubuntu, python版本等),工具链版本,不同深度学习框架的Demo,以及一些特别的注意事项等。
- python 版本工具链
rknn-toolkit2:https://github.com/rockchip-linux/rknn-toolkit2.
- C 版本工具链
rknpu2:https://github.com/rockchip-linux/rknpu2,用于编译在RK板子上推理的工具链。
部署流程:
- 安装 Python 版本的工具链(RKNN-ToolKit2),可以在PC端将(.onnx,.pt,.ckpt)导出为(.rknn)模型。该步骤可以验证自己训练的模型是否可以成功导出,卷积算子是否支持,预测效果是否可用,量化效果等功能。
- PC 端配置 C 版本工具链(RKNPU2),编译自己的 C++ 推理工程,编译得到的可执行文件可以在RK芯片运行。
- 将得到RKNN模型和可执行文件,以及RK一些必要的依赖库(.so)放入芯片上,可以直接运行。
下图是Python版本工具链目录结构,在【DOC】目录中提供了英文版和中文版的使用文档。
初次使用该工具链的时候,仔细阅读如下文档:
- “Rockchip_Quick_Start_RKNN_SDK_V1.4.0_CN.pdf”,该文档主要介绍了安装教程,运行demo以及一些基本的硬件参数,内容相对较少,(配置环境,运行demo建议阅读此文档)。
- “Rockchip_User_Guide_RKNN_Toolkit2_CN-1.4.0.pdf”,详细介绍了API接口得使用规则,以及其它相关内容,(具体API的使用,可以参考此文档)。
本教程使用【pip】的方式安装,docker也是官方建议的安装方式,看自己对哪种方式更为熟悉。结合文档的流程,具体操作过程如下:
- 创建虚拟环境
conda create -n rknn2 python=3.6
conda activate rknn2- 安装依赖库
- 进入工程的根目录
- 安装必要相应版本的依赖包
pip install -r doc/requirements_cp36-1.4.0.txt (下图是官方给的问题解决办法)
值得注意:在配置软件包的过程中,遇到“匹配不到XX版本”的问题,按照上述方式,并不能解决。
解决办法:首先安装Numpy(pip install numpy==1.19.5),然后执行上述命令,pip install -r doc/requirements_cp36-1.x.x.txt. 可能还有其它的错误,要根据错误提示,具体问题,具体分析。- 安装RKNN软件包
pip install packages/rknn_toolkit2-1.4.0_22dcfef4-cp36-cp36m-linux_x86_64.whl
- 1
- 检查RKNN-Toolkit2是否安装成功
如下图所示,没有出错,则表示安装成功
- 测试官方 YOLO-V5 Demo
- 运行目录下的【test.py】
python test.py
如下图所示,运行平台是PC(linux)模拟器,转换得到【yolov5s.rknn】模型。
主要介绍板子上为Linux系统64位的编译以及使用,具体流程如下:
- 下载编译工具链(Arm版)
由于板子上是Linux系统,所以下载gcc编译器,下图是【官方推荐】的gcc版本以及下载链接,
遇到问题:上述GCC的下载链接不存在,也没有找到gcc-9.3版本的下载链接。后来又找到gcc-9.3(没有测试是否可用),https://gitlab.com/firefly-linux/prebuilts/gcc/linux-x86/aarch64/gcc-buildroot-9.3.0-2020.03-x86_64_aarch64-rockchip-linux-gnu.
解决办法:下载其它版本的交叉编译器,【gcc-6.3】,下载链接如下,
http://releases.linaro.org/components/toolchain/binaries/6.3-2017.05/aarch64-linux-gnu/(参考博客为:https://blog.csdn.net/song_lee/article/details/105487177)。- 下载部署源码
下载地址:https://github.com/rockchip-linux/rknpu2.- 编译官方 YOLOV5 Demo
Git官方上的方法如下:https://github.com/rockchip-linux/rknpu2/tree/master/examples/rknn_yolov5_demo
仿照上述方式,针对自己下载的版本,终端命令如下:
export TOOL_CHAIN=/opt/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/
./build-linux_RK356X.sh
按照上述方法,仍并无法编译成功,报错如下图所示,找不到如下可执行文件 “aarch64-linux-gnu-gcc”
为此,修改【build-linux_RK356X.sh】脚本,将编译器所在目录写完整,具体修改如下图所示:
至此,可以成功编译YOLO-V5的例子,会在当前路径下生成【install】目录,目录中包含了扫地机上运行所需要的库,模型(可以通过rknn-toolkit2转换得到),测试图片,可执行程序,目录展开如下:
板子上运行(使用adb)
下图是Git上给的方式,将adb线插到扫地机,进行扫地机和PC端进行数据传输
Xshell 连接板子,运行程序即可。
移植自己训练的YOLOV5s,由于应用任务场景的不同,输出与官方YOLOV5的输出略有差异。与官方的Demo相比,需要修改一些输出的尺寸。具体流程如下:
- 导出RKNN模型
注意修改网络的输出大小:官方的模型yolov5s 输出的形状如下
output[0].shape=(1, 255, 80, 80), 自训练的模型输出为(1, 3, 80, 80,21)
output[0].shape=(1, 255, 40, 40), 自训练的模型输出为(1, 3, 40, 40,21)
output[0].shape=(1, 255, 20, 20), 自训练的模型输出为(1, 3, 20, 20,21)
为了适配官方提供的后处理,可以导出中间层的模型。用软件【Netron】打开自训练的模型,获得指定输出层的编号,如下图所示,得到输出为 (1, 63, 40, 40),
根据上述的网络节点的编号,代码需要修改的位置如下图所示,这样导出的模型可以完全与官方的后处理代码兼容。
- 编译RK板子的运行程序
参考上面的流程,修改相应的输出,直接编译即可。- 板子上运行
参考上面的流程,运行即可。
CMakeLists.txt 依赖库常见的添加方式,比如 CV,PCL等。具体内容如下,根据自己的库路径,相应修改即可:
cmake_minimum_required(VERSION 3.4.1)
project(${PROJECTNAME})
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(libcode ${CMAKE_SOURCE_DIR}/../Libcode)
include_directories(${libcode}/include)
include_directories(${CMAKE_SOURCE_DIR}/include)
# onnxruntime api
# set(ONNX_API_PATH ${CMAKE_SOURCE_DIR}/../libs/onnxruntime/onnxruntime-linux-aarch64-1.11.1)
# set(ONNX_API_PATH ${CMAKE_SOURCE_DIR}/../libs/onnxruntime/onnxruntime-linux-x64-1.11.1)
# message(${ONNX_API_PATH} )
# include_directories(${ONNX_API_PATH}/include)
# set(ONNX_API_LIB ${ONNX_API_PATH}/lib/libonnxruntime.so)
# rknn api
if(TARGET_SOC STREQUAL "rk356x")
set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../../libs/rknnruntime/RK356X/${CMAKE_SYSTEM_NAME}/librknn_api)
elseif(TARGET_SOC STREQUAL "rk3588")
set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../libs/rknnruntime/RK3588/${CMAKE_SYSTEM_NAME}/librknn_api)
else()
message(FATAL_ERROR "TARGET_SOC is not set, ref value: rk356x or rk3588 or rv110x")
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
set(RKNN_RT_LIB ${RKNN_API_PATH}/${CMAKE_ANDROID_ARCH_ABI}/librknnrt.so)
else()
if (CMAKE_C_COMPILER MATCHES "aarch64")
set(LIB_ARCH aarch64)
else()
set(LIB_ARCH armhf)
endif()
set(RKNN_RT_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknnrt.so)
endif()
include_directories(${RKNN_API_PATH}/include)
include_directories(${CMAKE_SOURCE_DIR}/../3rdparty)
# # opencv
set(OPENCV_PATH ${CMAKE_SOURCE_DIR}/../../../libs/opencv/opencv410_aarch64)
# set(OPENCV_PATH ${CMAKE_SOURCE_DIR}/../libs/opencv/opencv_pc)
message(${OPENCV_PATH} )
# opencv:头文件
include_directories(${OPENCV_PATH}/include/)
# opencv:动态库
file(GLOB OPENCV_LIBS ${OPENCV_PATH}/lib64/*.so*)
## PCL
set(TOOLCHAIN_LIB /home/xyy/LL_DATA/Furniture_project/yolov5-onnxruntime-mobile/yolov5_Furniture_inspection/libs)
##SET(TOOLCHAIN_LIB /opt/rk3566-rockchip-linux-toolchain/gcc-6.3.1-aarch64-linux-gnueabihf)
SET(BOOST_LIB_IOSTREAM ${TOOLCHAIN_LIB}/3rdParty/lib/libboost_iostreams.so)
SET(BOOST_LIB_SYSTEM ${TOOLCHAIN_LIB}/3rdParty/lib/libboost_system.so)
SET(BOOST_LIB_FILESYSTEM ${TOOLCHAIN_LIB}/3rdParty/lib/libboost_filesystem.so)
SET(BOOST_LIB_ZLIB ${TOOLCHAIN_LIB}/3rdParty/lib/libboost_zlib.so)
SET(BOOST_LIB ${BOOST_LIB_IOSTREAM} ${BOOST_LIB_SYSTEM} ${BOOST_LIB_FILESYSTEM} ${BOOST_LIB_ZLIB})
SET(PCL_LIBS
${TOOLCHAIN_LIB}/3rdParty/lib/libflann_cpp_s.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_features.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_filters.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_segmentation.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_search.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_kdtree.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_common.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_io.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_io_ply.a
${TOOLCHAIN_LIB}/3rdParty/lib/libpcl_sample_consensus.a
)
INCLUDE_DIRECTORIES(${TOOLCHAIN_LIB}/3rdParty/include/eigen3)
INCLUDE_DIRECTORIES(${TOOLCHAIN_LIB}/3rdParty/include/flann)
INCLUDE_DIRECTORIES(${TOOLCHAIN_LIB}/3rdParty/include/)
INCLUDE_DIRECTORIES(${TOOLCHAIN_LIB}/3rdParty/include/pcl-1.9)
set(CMAKE_INSTALL_RPATH "lib")
add_executable(${PROJECTNAME}
src/RKNN_main.cpp
src/RKNN_detector.cpp
src/RKNN_postprocess.cpp
${libcode}/src/utils.cpp
${libcode}/src/ALL_postprocessing.cpp
)
#target_link_libraries( aruco_single_estimator -lpthread -lm)
target_link_libraries(${PROJECTNAME}
#${ONNX_API_LIB}
${OPENCV_LIBS}
${BOOST_LIB}
${PCL_LIBS}
${RKNN_RT_LIB}
dl
)
# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/../../install/RK3566)
install(TARGETS ${PROJECTNAME} DESTINATION ./)
install(DIRECTORY ../models DESTINATION ./)
install(PROGRAMS ${OPENCV_LIBS} DESTINATION lib)
install(PROGRAMS ${BOOST_LIB} DESTINATION lib)
install(PROGRAMS ${PCL_LIBS} DESTINATION lib)
install(PROGRAMS ${RKNN_RT_LIB} DESTINATION lib)
对应的 build.sh
#!/bin/bash
rm -R build
set -e
TARGET_SOC="rk356x"
# for rk1808 aarch64
GCC_COMPILER=/home/xyy/LL_DATA/Furniture_project/yolov5-onnxruntime-mobile/yolov5_Furniture_inspection/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu
PROJECTNAME=furniture3D
ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd )
echo ${ROOT_PWD}
# 进入build文件
mkdir ${ROOT_PWD}/build
cd ${ROOT_PWD}/build
cmake .. \
-DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \
-DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ \
-DCMAKE_SYSTEM_NAME=Linux \
-DTARGET_SOC=${TARGET_SOC} \
-DPROJECTNAME=${PROJECTNAME}
make -j10
make install
cd ${ROOT_PWD}
/home/xyy/LL_DATA/Furniture_project/yolov5-onnxruntime-mobile/yolov5_Furniture_inspection/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-strip ../../install/RK3566/${PROJECTNAME}
md5sum ../../install/RK3566/${PROJECTNAME}
date +%Y/%m/%d%t%H:%M:%S
adb push ../../install/RK3566/${PROJECTNAME} /userdata/kang/model
cp ../../install/RK3566/${PROJECTNAME} /home/xyy/MOUNT_241/PersonalData/LL_dataset/tmp/kang/model
直接 sh build.sh
即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。