PC : Ubuntu 18.0+
rknn平台:RK3568
Python版本:3.6.x
安装rknn-toolkit2
1、下载RKNN_SDK 或 RK3568源码SDK,cd进入rknn-toolkit2目录
2、运行pip安装依赖库:pip3 install -r doc/requirement.txt
3、pip安装轮子(.whl):pip3 install rknn_toolkit2-*-cp36-cp36m-linux_x86_64.whl
4、前两步完成后,运行python3,在python shell里输入from rknn.api import RKNN
成功导入则安装完成。否则就是安装失败。
安装过程-可能遇到的问题
requirement.txt
1、如果不是python3.6.x版本的话,可能会出现numpy.1.13.3兼容问题,尽量使用python3.6.x版本,可以避免大量的问题。
2、pip3 install onnxoptimizer==0.1.0
报错:
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;file='/tmp/pip-build-0mfmov8a/onnx/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-fmzr5hzv-record/install-record.txt --single-version-externally-managed --compile --user --prefix=" failed with error code 1 in /tmp/pip-build-0mfmov8a/onnx/
解决方案:
尝试安装依赖解决=>sudo apt-get install -y libprotobuf-dev protobuf-compiler python3-scipy
sudo apt-get install libssl-dev libffi-dev python-dev build-essential libxml2-dev libxslt1-dev
安装完后,卸载(uninstall)之前安装的库。
然后再重新安装:sudo pip3 install onnxoptimizer==0.1.0
3、pip3安装库时报错没有对应版本,解决方案(能装,但不一定能兼容):去除版本限制。
4、安装opencv-python:
报错:
Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-build-ey0xc_0y/opencv-python/setup.py", line 9, in
import skbuild
ModuleNotFoundError: No module named 'skbuild'
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-ey0xc_0y/opencv-python/
解决:这里的skbuild全名为scikit_build,先安装这个库。
rknn_toolkit2-*-cp36-cp36m-linux_x86_64.whl
安装之前,检查pip版本,否则某些库可能找不到版本。
pip3 --version
如果过低(9或者10)
升级pip
pip3 install --upgrade pip
查看pip版本:pip 21.3.1
可以开始安装.whl文件了
安装完requirement.txt和rknn_toolkit2-*-cp36-cp36m-linux_x86_64.whl后,进入python shell测试
root@root:/$ python3
Python 3.6.9 (default, Dec 8 2021, 21:08:43)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
from rknn.api import RKNN
==>报错:
ModuleNotFoundError: No module named 'numpy.core._multiarray_umath'
ImportError: numpy.core.multiarray failed to import
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "", line 968, in _find_and_load
SystemError: <class '_frozen_importlib._ModuleLockManager'> returned a result with an error set
RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb
ImportError: numpy.core.multiarray failed to import
ImportError: numpy.core.umath failed to import
ImportError: numpy.core.umath failed to import
2021-12-17 09:13:32.275457: F tensorflow/python/lib/core/bfloat16.cc:675] Check failed: PyBfloat16_Type.tp_base != nullptr
已放弃 (核心已转储)
==>解决:这是由于当前numpy版本与rknn不兼容,检查numpy版本
pip3 freeze | grep numpy
如果不是1.16.6,则卸载重装
pip3 uninstall numpy
pip3 install numpy==1.16.6
再次尝试用python导入rknn库,应该就可以了。
测试 运行在与 PC 相连的 AIO-3568J NPU 平台上
1、首先部署 AIO-3568J 环境:更新librknnrt.so及运行
rknn_server
--Linux PC端:
adb push RKNN_SDK/Linux/rknn_server/aarch64/usr/bin/rknn_server /usr/bin/
adb push RKNN_SDK/Linux/librknn_api/aarch64/librknnrt.so /usr/lib/
adb push RKNN_SDK/Linux/librknn_api/aarch64/librknn_api.so /usr/lib/
在板子的串口终端运行rknn_server
chmod +x /usr/bin/rknn_server
/usr/bin/rknn_server
2、然后在 PC 上修改examples/tflite/mobilenet_v1/test.py文件,在其中添加目标平台
|+++++++++++++++++++++++++++++++++|
diff --git a/test.py b/test.py
index 61ad668..51a01e2 100644
--- a/test.py
+++ b/test.py
[url=home.php?mod=space&uid=1999721]@@[/url] -62,7 +62,7 @@ if name == 'main':
|+++++++++++++++++++++++++++++++++|
init runtime environment
print('--> Init runtime environment')
- ret = rknn.init_runtime()
- ret = rknn.init_runtime(target='rk3568')
if ret != 0:
print('Init runtime environment failed')
exit(ret)
3、PC端运行test.py (venv) firefly@T-chip:~/rknn-toolkit2-1.1.0b0/examples/tflite/mobilenet_v1$ python3 test.py
运行test.py会出现一些问题
1、
Q:E build: ImportError: libprotobuf.so.10: cannot open shared object file: No such file or directory
A:动态依赖库不存在,在/usr/lib/下没有找到对应的依赖文件(.so),如果文件实际存在/usr/local/lib/下,则为其添加软连接到/usr/lib/下即可,如果该文件实际不存在,那么可以自行安装:
一、下载最新版本
二、编译安装
解压、进入目录
开始编译
sudo apt install autoconf
./autogen.sh
./configure --prefix=/usr/local/protobuf #为了以后便于管理
make -j4 #多核编译加快速度
sudo make install
三、建立软连接
安装完之后,动态库的位置在/usr/local/protobuf/lib/
sudo ln -s /usr/local/protobuf/lib/libprotobuf.so.30.0.1 /usr/lib/libprotobuf.so.30
2、
Q:E build: ImportError: /home/raysees/anaconda3/envs/rktool/lib/python3.6/site-packages/rknn/api/lib/hardware/DOLPHIN/linux-x86_64/cp36/librknnc.so: undefined symbol: _ZNK6google8protobuf7Message9SpaceUsedEv
A:(Ubuntu 20)暂时无解
这篇好像可以解决问题
https://blog.csdn.net/qq_40821799/article/details/84330422
A:(Ubuntu 18)重装18系统后好像没出现这个问题,因为18系自带的python环境是与rknn-toolkit2兼容较好的python3.6。
部署RKNN模型到rk3568进行推演
编写自定义编译脚本
通过修改rknnSDK的示例程序编译脚本,可以实现任意模型的编译。以onnx下的YOLO为例
1、先修改这两个文件:
build-linux.sh:将GCC_COMPILER修改为合适的交叉编译器,这里rk3568为aarch64-linux-gnu
for aarch64
GCC_COMPILER=aarch64-linux-gnu
CMakeLists.txt:对cmake行为进行一些配置。
'rknn_yolov3_demo’可以替换为任意名称,这是编译后的可执行程序名称。如果修改,则下列所有的’rknn_yolov3_demo’都要更改,可以自己在文件里比对,这只是一个名称,不一定是这个字符串。
add_executable(rknn_yolov3_demo
src/main.cc
)
target_link_libraries(rknn_yolov3_demo "-Wl,--allow-shlib-undefined"
${RKNN_API_LIB}
${OpenCV_LIBS}
)
install target and libraries
set(CMAKE_INSTALL_PREFIX {CMAKE_SOURCE_DIR}/install/rknn_yolov3_demo_{CMAKE_SYSTEM_NAME})
install(TARGETS rknn_yolov3_demo DESTINATION ./)
install(DIRECTORY model DESTINATION ./)
install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib)
install(PROGRAMS ${RKNN_RT_LIB} DESTINATION lib)
2、编写主程序main.cc
这是运行模型推演程序的入口,我们依靠这个cpp文件来完成导入图片、导入模型、输入、输出、模型推演、以及推演结果数据处理等工作。
通用main.cc如下,如果提示opencv未找到。请将rknnSDK下的Linux文件夹放到build-linux.sh的…/…/路径下,即上两层父目录。
// includes
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include
#include
#include <sys/time.h>
#include <string.h>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "rknn_api.h"
#include
using namespace std;
using namespace cv;
using namespace chrono;
//Functions
//打印tensor信息
static void printRKNNTensor(rknn_tensor_attr *attr){
printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n",
attr->index,attr->name,attr->n_dims,attr->dims[0],attr->dims[1],attr->dims[2],attr->dims[3],
attr->n_elems,attr->size,0,attr->type,attr->qnt_type,attr->fl,attr->zp,attr->scale);
}
//加载模型rknn
static unsigned char* load_model(const charfilename,int model_size){
FILE* fp = fopen(filename,"rb");
if(fp==nullptr){
printf("foen %s fail \n",filename);
return NULL;
}
fseek(fp,0,SEEK_END);
int model_len = ftell(fp);
unsigned char * model = (unsigned char*)malloc(model_len);
fseek(fp,0,SEEK_SET);
if(model_len != fread(model,1,model_len,fp)){
printf("fread %s failed \n",filename);
free(model);
return NULL;
}
*model_size = model_len;
if(fp){
fclose(fp);
}
return model;
}
int main(int argc, char** argv){
printf("hello rknn");
const int MODEL_IN_WIDTH = 640;
const int MODEL_IN_HEIGHT = 640;
const int MODEL_IN_CHANNELS = 3;
rknn_context ctx;//rknn 上下文 结构体,可以用来接收rknn模型的运行输出
int ret; //用来记录API的运行结果,异常处理等
int model_len = 0;
unsigned char * model;
// 从外部传入rknn模型文件和需要处理的图片。
const char* model_path = argv[1];
const char * img_path = argv[2];
//载入图片文件
cv::Mat orig_img = imread(img_path , cv::IMREAD_COLOR);
if(orig_img.empty()){
printf("cv::imread %s failed\n",img_path);
return -1;
}
cv::Mat img = orig_img.clone();
if(orig_img.cols != MODEL_IN_WIDTH || orig_img.rows != MODEL_IN_HEIGHT){
printf("resize %d %d to %d %d\n",orig_img.cols,orig_img.rows,MODEL_IN_WIDTH,MODEL_IN_HEIGHT);
cv::resize(orig_img,img,cv::Size(MODEL_IN_WIDTH,MODEL_IN_HEIGHT),(0,0),(0,0),cv::INTER_LINEAR);
}
//载入 RKNN 模型
model = load_model(model_path,&model_len);
ret = rknn_init(&ctx,model,model_len,0&RKNN_FLAG_COLLECT_PERF_MASK,NULL);
if(ret < 0){
printf("rknn_init failed ! ret code:%d\n",ret);
return -1;
}
//获取输入、输出信息
rknn_input_output_num io_num;
ret = rknn_query(ctx,RKNN_QUERY_IN_OUT_NUM,&io_num,sizeof(io_num));
if(ret != RKNN_SUCC){
printf("rknn_query get_in_out_num failed, ret code=%d\n",ret);
return -1;
}
printf("model input num : %d, output num: %d \n",io_num.n_input,io_num.n_output);
// 获取输入tensor, >> 网络结构
printf("input tensors:\n");
rknn_tensor_attr input_attrs[io_num.n_input];
memset(input_attrs,0,sizeof(input_attrs));
for(int i = 0 ; i < io_num .n_input ; i++){
input_attrs[i].index = i;
ret = rknn_query(ctx,RKNN_QUERY_INPUT_ATTR,&(input_attrs[i]),sizeof(rknn_tensor_attr));
if(ret != RKNN_SUCC){
printf("rknn_query get_in failed ! ret code : %d\n",ret);
return -1;
}
printRKNNTensor(&(input_attrs[i]));
}
//获取输出tensor, >>网络结构
printf("output tensors:\n");
rknn_tensor_attr output_attrs[io_num.n_output];
memset(output_attrs,0,sizeof(output_attrs));
for(int i = 0 ; i < io_num .n_output ; i++){
output_attrs[i].index = i;
ret = rknn_query(ctx,RKNN_QUERY_OUTPUT_ATTR,&(output_attrs[i]),sizeof(rknn_tensor_attr));
if(ret != RKNN_SUCC){
printf("rknn_query get_in failed ! ret code : %d\n",ret);
return -1;
}
printRKNNTensor(&(output_attrs[i]));
}
//设置输入值
rknn_input inputs[1];
memset(inputs,0,sizeof(inputs));
inputs[0].index = 0;
inputs[0].type = RKNN_TENSOR_UINT8;
inputs[0].size = img.cols * img.rows * img.channels();
inputs[0].fmt = RKNN_TENSOR_NHWC;
inputs[0].buf = img.data;
ret = rknn_inputs_set(ctx,io_num.n_input,inputs);
if(ret < 0){
printf("rknn_input_set failed ! ret code:%d\n",ret);
return -1;
}
//运行模型,跑模型
printf("rknn run \n");
ret = rknn_run(ctx,nullptr);
if(ret < 0){
printf("rknn run failed ! ret code:%d\n",ret);
return -1;
}
//模型跑完后,(计算完之后)
//获取模型输出,tensor等
rknn_output outputs[1];
memset(outputs,0,sizeof(outputs));
outputs[0].want_float = 1;
ret = rknn_outputs_get(ctx,1,outputs,NULL);
if(ret <0 ){
printf("rknn_outputs_get failed! ret code=%d\n",ret);
return -1;
}
printf("######out : size:%d",outputs[0].size);
//统计模型运行时间
//释放rknn outputs
rknn_outputs_release(ctx,1,outputs);
//释放模型
if(ctx >= 0){
rknn_destroy(ctx);
}
if(model){
free(model);
}
return 0;
}
原作者:钱小钰io