rk3568 RKNN配置(部分异常情况)

rk3568 RKNN配置

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 "<string>", line 1, in <module>
      File "/tmp/pip-build-ey0xc_0y/opencv-python/setup.py", line 9, in <module>
        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 "<frozen importlib._bootstrap>", 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
@@ -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/下即可,如果该文件实际不存在,那么可以自行安装:
一、下载最新版本:
https://github.com/protocolbuffers/protobuf
二、编译安装
解压、进入目录
开始编译
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 <fstream>
#include <iostream>
#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 <chrono>


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 char*filename,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;
}


  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值