前言
注:本次实验所使用的平台是x86机器上的Ubuntu 20.04虚拟系统,开发板为瑞芯微RK3588,开发板上面的系统为Ubuntu22.04。
在进行本博文的实验前,你需要确保你的虚拟系统上已经搭建好了rknntoolkit2的环境。
任务:
【1】
1. 将非RKNN模型转换为RKNN模型,即构建RKNN模型,进而进行模型在rknntoolkit2模拟器上的推理测试,最终完成图像的分类工作。
2. 连板推理,将模型加载到RKNPU上进行推理测试。
本次所用到的模型为resnet18.pt(pytorch)。
【2】
1. 将RKNN模型加载到RKNPU上进行推理测试,RKNN模型连板推理测试。
模型运行方式如下图所示:
在pycharm中新建一个名为inference_learning文件夹,在该文件夹中创建一个名为inference_pytorch.py 的python文件,如下图所示:
将所需要的资料复制到inference_learning文件夹中,如下图所示:
模型文件:
dataset.txt是RKNN模型量化矫正数据集。
我们将会按照 加载非RKNN模型进行模型推理流程图 进行逐步编写代码,最终模型能够成功推理图片。
一、非RKNN模型推理步骤
1.1 RKNN模型构建步骤
前五步和最后一步代码请参考博主的这篇博文:RKNPU2从入门到实践 --- 【4】RKNN 模型构建【使用pycharm一步一步搭建RKNN模型】-CSDN博客
前五步和最后一步的代码如下:
from rknn.api import RKNN
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1,3,224,224]])
# 第四步:调用build接口构建RKNN模型
rknn.build(
do_quantization=True, # 表示开启rknn模型量化
dataset='dataset.txt', # 量化所用到的数据集
)
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 最后一步:释放RKNN对象
rknn.release()
以上代码完成了以下流程:
创建RKNN对象 -> 调用config接口配置RKNN对象的相关参数 -> 调用 load_pytorch 接口导入pt模型 -> 调用build接口构建RKNN模型 -> 调用 export_rknn 接口导出RKNN模型->......【省略步骤将会在下面介绍】-> 调用release方法释放RKNN对象。
导出RKNN模型步骤在模型推理阶段不是很需要,该步骤可要可不要。
接下来我们会学习上述步骤中省略步骤的内容,请看1.2小节。
1.2 省略的步骤
1.2.1 初始化运行时环境
1.2.1.1概念介绍
在模型推理或性能评估之前,必须先初始化运行时环境,明确模型的运行平台(具体的目 标硬件平台或软件模拟器)。
1.2.1.2 实际演示
第六步所需代码如下所示:
整体代码如下所示:
from rknn.api import RKNN
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1,3,224,224]])
# 第四步:调用build接口构建RKNN模型
rknn.build(
do_quantization=True, # 表示开启rknn模型量化
dataset='dataset.txt', # 量化所用到的数据集
)
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 第六步:调用 init_runtime 接口初始化运行时环境
rknn.init_runtime(
target=None ,# target 表示rknn模型运行平台,默认为None,表示运行在模拟器上
device_id=None,
)
# 最后一步:释放RKNN对象
rknn.release()
1.2.2 opencv 导入RKNN模型推理的图片
在进行调用inference接口进行模型推理之前,我们需要用opencv来获取要推理的图片。图片为 前言 部分的飞船,如下图所示。
该部分代码如下所示:
在上述代码中,使用cv2.cvtColor进行数据格式的转化的原因是,使用opencv(cv2)打开的图片格式为BGR格式,而我们此次的模型为resnet18模型,该模型喂入的图片格式为RGB格式的,因此需要转换一下。
接下来便进入到模型推理部分,请看1.2.3小节。
1.2.3 模型推理
1.2.3.1 概念介绍
在进行模型推理前,必须先构建或加载一个 RKNN 模型。
1.2.3.2 实际演示
该部分代码如下:
该部分代码添入后整体代码如下:
from rknn.api import RKNN
import cv2
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1,3,224,224]])
# 第四步:调用build接口构建RKNN模型
rknn.build(
do_quantization=True, # 表示开启rknn模型量化
dataset='dataset.txt', # 量化所用到的数据集
)
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 第六步:调用 init_runtime 接口初始化运行时环境
rknn.init_runtime(
target=None ,# target 表示rknn模型运行平台,默认为None,表示运行在模拟器上
device_id=None,
)
# 使用opencv获取要推理的图片数据
img = cv2.imread(
filename='./space_shuttle_224.jpg', #filename 表示要读取的图片路径
)
# cvtColor 数据格式化转化
cv2.cvtColor(
src=img, # 表示要转换的数据
code=cv2.COLOR_BGR2RGB, # code表示转换码
)
# 第七步:调用 inference 接口进行推理测试
outputs = rknn.inference(
inputs=[img], # 表示要推理的数据
data_format='nhwc', # 表示要推理的数据模式
)
# 最后一步:释放RKNN对象
rknn.release()
至此,我们完成了RKNN模型的推理阶段,但最终步骤还没有结束,因为outputs还不是我们一般看到的分类概率值。需要将outputs进行处理。
因此,接下来请看1.3小节。
1.3 后处理部分
后处理的代码如下所示:
import numpy as np
def show_outputs(output):
output_sorted = sorted(output, reverse=True)
top5_str = '\n-----TOP 5-----\n'
for i in range(5):
value = output_sorted[i]
index = np.where(output == value)
for j in range(len(index)):
if (i + j) >= 5:
break
if value > 0:
topi = '{}: {}\n'.format(index[j], value)
else:
topi = '-1: 0.0\n'
top5_str += topi
print(top5_str)
def show_perfs(perfs):
perfs = 'perfs: {}\n'.format(perfs)
print(perfs)
def softmax(x):
return np.exp(x)/sum(np.exp(x))
show_outputs(softmax(np.array(outputs[0][0])))
添入后整体代码如下:
from rknn.api import RKNN
import cv2
import numpy as np
def show_outputs(output):
output_sorted = sorted(output, reverse=True)
top5_str = '\n-----TOP 5-----\n'
for i in range(5):
value = output_sorted[i]
index = np.where(output == value)
for j in range(len(index)):
if (i + j) >= 5:
break
if value > 0:
topi = '{}: {}\n'.format(index[j], value)
else:
topi = '-1: 0.0\n'
top5_str += topi
print(top5_str)
def show_perfs(perfs):
perfs = 'perfs: {}\n'.format(perfs)
print(perfs)
def softmax(x):
return np.exp(x)/sum(np.exp(x))
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1,3,224,224]])
# 第四步:调用build接口构建RKNN模型
rknn.build(
do_quantization=True, # 表示开启rknn模型量化
dataset='dataset.txt', # 量化所用到的数据集
)
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 第六步:调用 init_runtime 接口初始化运行时环境
rknn.init_runtime(
target=None ,# target 表示rknn模型运行平台,默认为None,表示运行在模拟器上
device_id=None,
)
# 使用opencv获取要推理的图片数据
img = cv2.imread(
filename='./space_shuttle_224.jpg', #filename 表示要读取的图片路径
)
# cvtColor 数据格式化转化
cv2.cvtColor(
src=img, # 表示要转换的数据
code=cv2.COLOR_BGR2RGB, # code表示转换码
)
# 第七步:调用 inference 接口进行推理测试
outputs = rknn.inference(
inputs=[img], # 表示要推理的数据
data_format='nhwc', # 表示要推理的数据模式
)
# 对outputs进行后处理
show_outputs(softmax(np.array(outputs[0][0])))
# 最后一步:释放RKNN对象
rknn.release()
至此,一个完整的推理程序就编写完成了。
我们来运行上述代码:
导出rknn模型。
运行结束后给出概率前五名排列如下图所示:
可以看到概率最大的为812号,概率值为0.9995219....
那么我们来检查以下812号到底是什么?
我们查看标签,得知812号正是航天飞船,模型推理成功。
二、非RKNN模型连板推理
修改上述代码,只需将 init_runtime接口中的target参数由None取值改为rk3588取值,表示将模型加载到RKNPU上进行推理测试。修改后的总体代码如下:
from rknn.api import RKNN
import cv2
import numpy as np
def show_outputs(output):
output_sorted = sorted(output, reverse=True)
top5_str = '\n-----TOP 5-----\n'
for i in range(5):
value = output_sorted[i]
index = np.where(output == value)
for j in range(len(index)):
if (i + j) >= 5:
break
if value > 0:
topi = '{}: {}\n'.format(index[j], value)
else:
topi = '-1: 0.0\n'
top5_str += topi
print(top5_str)
def show_perfs(perfs):
perfs = 'perfs: {}\n'.format(perfs)
print(perfs)
def softmax(x):
return np.exp(x)/sum(np.exp(x))
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1,3,224,224]])
# 第四步:调用build接口构建RKNN模型
rknn.build(
do_quantization=True, # 表示开启rknn模型量化
dataset='dataset.txt', # 量化所用到的数据集
)
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 第六步:调用 init_runtime 接口初始化运行时环境
rknn.init_runtime(
target='rk3588' ,# target 表示rknn模型运行平台,默认为None,表示运行在模拟器上
device_id=None,
)
# 使用opencv获取要推理的图片数据
img = cv2.imread(
filename='./space_shuttle_224.jpg', #filename 表示要读取的图片路径
)
# cvtColor 数据格式化转化
cv2.cvtColor(
src=img, # 表示要转换的数据
code=cv2.COLOR_BGR2RGB, # code表示转换码
)
# 第七步:调用 inference 接口进行推理测试
outputs = rknn.inference(
inputs=[img], # 表示要推理的数据
data_format='nhwc', # 表示要推理的数据模式
)
# 对outputs进行后处理
show_outputs(softmax(np.array(outputs[0][0])))
# 最后一步:释放RKNN对象
rknn.release()
开发板系统启动之后,我们将开发板连接到虚拟机 Ubuntu20.04 上。 如下图所示:
点击确定后,则会进行连接。连接成功后,会在Ubuntu虚拟系统任务栏中出现一个手机的标识,如下图所示:
在程序运行前,需要保证Ubuntu虚拟机安装了adb,若没有安装,则使用指令 sudo apt-get install adb 进行安装。
如下图所示:
确保开发板的adb已经成功连接到Ubuntu虚拟系统上。
在终端输入 adb devices 指令也能查看开发板的id号。
接下来使用MobaXterm软件通过串口进行调试。如下所示:
开发板启动之后运行rknn_server服务,如下所示:
若发现运行rknn_server服务失败,请参考博主的博文:更新RK3588开发板的rknn_server和librknnrt.so【这篇文章是RKNPU2从入门到实践 --- 【5】的配套文章】-CSDN博客然后回到Ubuntu20.04虚拟系统中重新运行修改后的程序,如下图所示:
得到结果,发现连板推理得到的结果与在rknntoolkit2模拟器上运行的结果相似。
至此,连板推理成功。
三、RKNN模型推理测试
RKNN模型只能进行连板推理,步骤非常简单,如下:
将 inference_pytorch.py 文件复制一份并重新命名,得到 inference_rknn.py ,代码目前保持一致。
由于是直接加载的RKNN模型,所以就不需要RKNN模型的参数配置、加载非RKNN模型、构建RKNN模型,即不需要如下代码:
然后添加 load_rknn 接口直接加载RKNN 模型,如下所示:
其余地方均不需修改。得到的最终代码为:
from rknn.api import RKNN
import cv2
import numpy as np
def show_outputs(output):
output_sorted = sorted(output, reverse=True)
top5_str = '\n-----TOP 5-----\n'
for i in range(5):
value = output_sorted[i]
index = np.where(output == value)
for j in range(len(index)):
if (i + j) >= 5:
break
if value > 0:
topi = '{}: {}\n'.format(index[j], value)
else:
topi = '-1: 0.0\n'
top5_str += topi
print(top5_str)
def show_perfs(perfs):
perfs = 'perfs: {}\n'.format(perfs)
print(perfs)
def softmax(x):
return np.exp(x)/sum(np.exp(x))
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN(verbose=True)
# 调用 load_rknn 接口直接加载RKNN模型
rknn.load_rknn(path='./resnet.rknn') # path 表示加载的RKNN模型路径
# 第五步:导出rknn模型
rknn.export_rknn(export_path='./resnet.rknn')
# 第六步:调用 init_runtime 接口初始化运行时环境
rknn.init_runtime(
target='rk3588' ,# target 表示rknn模型运行平台,默认为None,表示运行在模拟器上
device_id=None,
)
# 使用opencv获取要推理的图片数据
img = cv2.imread(
filename='./space_shuttle_224.jpg', #filename 表示要读取的图片路径
)
# cvtColor 数据格式化转化
cv2.cvtColor(
src=img, # 表示要转换的数据
code=cv2.COLOR_BGR2RGB, # code表示转换码
)
# 第七步:调用 inference 接口进行推理测试
outputs = rknn.inference(
inputs=[img], # 表示要推理的数据
data_format='nhwc', # 表示要推理的数据模式
)
# 对outputs进行后处理
show_outputs(softmax(np.array(outputs[0][0])))
# 最后一步:释放RKNN对象
rknn.release()
然后运行程序,得到:
至此,RKNN模型连板推理成功。