RKNPU2 从入门到实践(rk3588学习笔记)
链接:https://pan.baidu.com/s/1vJ5WFj6VDs45gA5ZIrROhQ提取码:fyvy。选择先前配置的解释器,选系统解释器,/home/topeet/miniconda3/envs/bin/python3。1.1 github搜索:rockchip-linux,选择用户,进主页找rknn-toolkit2,并下载。负基础教学,讯为科技家的网课。然后按照指令,拷贝进创建
负基础教学,讯为科技家的网课。目的是了解开发流程和技术要点,独立完成项目
一、RKNN Toolkit2 API环境搭载和模型构建前准备

Linux需基本指令操作以及对根文件的功能了解
python和c语言能看懂逻辑就行
深度学习需达到可以独立完成对轻量级yolo模型的训练和导出,对模型修改构建不作要求
架构组成:

1.1 github搜索:rockchip-linux,选择用户,进主页找rknn-toolkit2,并下载

工具对比:


1.2 Miniconda,并创建虚拟环境RKNN

安装Linux 64-bit版本

然后按照指令,拷贝进创建好的目录 softwate里,再 ./运行程序


等待安装,一直yes

打开终端,有(base)说明完成了


终端输入指令 vim .condarc
内容到文档中复制(
链接:https://pan.baidu.com/s/1vJ5WFj6VDs45gA5ZIrROhQ 提取码:fyvy
)
创建RNKK环境

输入指令 conda activate rknn

就能创建一个新的虚拟环境rknn
再重复前面的拷贝工作,把rknn-toolkit2工具放进环境中

然后是安装几个库


1.3 pycharm,配置中文插件和RKNN解释器

选择Linux版本进行下载,拷贝压缩包

使用tar -vxf命令解压压缩包

ls选择进入pycharm.sh,再./启动pycharm

创桌面快捷

安装中文插件(language那个,第二个),然后重启一下ide

选择新建项目,/home/topeet/rknn

选择先前配置的解释器,选系统解释器,/home/topeet/miniconda3/envs/bin/python3

打开终端,(rknn)确定环境为rknn中

二、RKNN模型构建和加载,精度分析和性能评估
2.1模型构建
API介绍


回到rknn项目中
右键新建目录01_export_rknn

第一步:创建export_rknn.py文件

第二步:输入并运行,调用config接口设置模型预处理、量化方法等参数
from rknn.api import RKNN
if __name__ == '__main__':
rknn = RKNN(verbose=True, verbose_file="log.txt")
rknn.config(
mean_values=[[123.675, 116.28, 103.53]], # mean_values 表示预处理减去的均值化参数
std_values=[[58.395, 57.12, 57.375]], # std_values 表示预处理要除的标准化参数
quantized_dtype='asymmetric_quantized-u8', # quantized_dtype 表示量化类型
quantized_algorithm='normal', # quantized_algorithm 表示量化算法
quantized_method='channel', # quantized_method 表示量化的方式
target_platform='RK3588', # target_platform 表示 RKNN 模型的运行平台
float_dtype='float16', # float_dtype 表示 RKNN 中的浮点运算数据类型,不进行模型量化情况下,一般默认float32转换为float16
optimization_level=3, # optimization_level 表示优化等级
stringization=True, # stringization 表示自定义字符串信息
remove_weight=False, # remove_weight 表示是否移除权重信息(生成小模型)
compress_weight=False, # compress_weight 表示是否压缩权重(减小模型体积)
inputs_yuv_fmt=None, # inputs_yuv_fmt 表示 RKNN 模型输入数据的 YUV 格式
single_core_mode=False # single_core_mode 表示模型是否运行在单核模式(仅适用于 RK3588)
)
rknn.release()
这里调用PyTorch模型加载接口

第三步:
①找到这个资料04_RNKK模型构建找到01_课程用到的资料的01_pytorch模型,把.pt拷到
前面创建的目录01_export_rknn中(resnet8.pt)
②找到这个资料04_RNKK模型构建找到01_课程用到的资料的02_dataset,把.txt和图片拷到
前面创建的目录01_export_rknn中(dataset.txt、图片)
③调用rknn.export_rknn导出的 RKNN 模型路径,然后命令行python运行一下,当目录下出现resnet18.rknn文件,说明转化成功
from rknn.api import RKNN
if __name__ == '__main__':
rknn = RKNN(verbose=True, verbose_file="log.txt")
rknn.config(
mean_values=[[123.675, 116.28, 103.53]], # mean_values 表示预处理减去的均值化参数
std_values=[[58.395, 57.12, 57.375]], # std_values 表示预处理要除的标准化参数
quantized_dtype='asymmetric_quantized-u8', # quantized_dtype 表示量化类型
quantized_algorithm='normal', # quantized_algorithm 表示量化算法
quantized_method='channel', # quantized_method 表示量化的方式
target_platform='RK3588', # target_platform 表示 RKNN 模型的运行平台
float_dtype='float16', # float_dtype 表示 RKNN 中的浮点运算数据类型,不进行模型量化情况下,一般默认float32转换为float16
optimization_level=3, # optimization_level 表示优化等级
stringization=True, # stringization 表示自定义字符串信息
remove_weight=False, # remove_weight 表示是否移除权重信息(生成小模型)
compress_weight=False, # compress_weight 表示是否压缩权重(减小模型体积)
inputs_yuv_fmt=None, # inputs_yuv_fmt 表示 RKNN 模型输入数据的 YUV 格式
single_core_mode=False # single_core_mode 表示模型是否运行在单核模式(仅适用于 RK3588,其他板块注意切换)
)
rknn.load_pytorch (
model="./resnet18.pt", # model 表示加载模型的地址
input_size_list=[[1, 3, 224, 224]], # input_size_list 表示模型输入节点对应图片的尺寸和通道数
)
rknn.build (
do_quantization=True, # do_quantization 表示是否对 RKNN 模型进行量化操作,
dataset="dataset.txt", # dataset 表示要量化的图片
rknn_batch_size=1 #
)
rknn.export_rknn (
export_path="resnet18.rknn" # export_path 表示导出的 RKNN 模型路径
)
rknn.release()
整体流程是固定的,结合文档第四章 RKNN-Toolkit2 API介绍了解熟悉流程

2.2推理测试
回到rknn项目中
右键新建目录02_inference,新建文件inference_pytorch.py
找到这个资料04_RNKK模型构建找到01_课程用到的资料的01_pytorch模型,把.pt拷到
前面创建的目录01_export_rknn中(resnet8.pt)
找到这个资料04_RNKK模型构建找到01_课程用到的资料的02_dataset,把.txt和图片拷到
前面创建的目录01_export_rknn中(dataset.txt、图片)
from rknn.api import RKNN
import cv2
if __name__ == "__main__":
rknn=RKNN(verbose=Ture)
rknn.config(
mean_values=[[123.675, 116.28, 103.53]],
std_values=[[58.395, 58.395, 58.395]],
target_platform="RK3588"
)
rknn.load_pytorch(
model="./resnet18.pt", input_size_list=[[1, 3, 224, 224]])
rknn.build(
do_quantization=True,
dataset="dataset.txt",
)
rknn.export_rknn(export_path="resnet18.rknn")
rknn.init_runtime(
target=None,
target_sub_class=None,
device_id=None,
perf_debug=False,
eval_mem=False,
async_mode=False,
core_mask=RKNN.NPU_CORE_AUTO,
)
img = cv2.imread(
filename="/space_shuttle_224.jpg",
flags=None
)
cv2.cvtColor(
src=img,
code=cv2.COLOR_BGR2RGB,
)
#调用inference接口进行推理
outputs = rknn.inference(
inputs=[img], # inputs表示要推理的数据
data_format="nhwc" # data_format表示要推理的数据格式
)
rknn.release()
找到文件地址:
\05_RKNN 模型评估-推理测试\01_课程用到的资料\03_后处理程序\demo.py
用于outputs的后处理,把代码拷贝到工程中
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 = '{:d}: {:.3f}\n'.format(index[j], value)
else:
topi = '-1: 0.000\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(verbose=Ture)
rknn.config(
mean_values=[[123.675, 116.28, 103.53]],
std_values=[[58.395, 58.395, 58.395]],
target_platform="RK3588"
)
rknn.load_pytorch(
model="./resnet18.pt", input_size_list=[[1, 3, 224, 224]])
rknn.build(
do_quantization=True,
dataset="dataset.txt",
)
rknn.export_rknn(export_path="resnet18.rknn")
#调试初始化接口环境
rknn.init_runtime(
target=None, #测试rk3588时,更改为"rk3588"
target_sub_class=None,
device_id=None,
perf_debug=False,
eval_mem=False,
async_mode=False,
core_mask=RKNN.NPU_CORE_AUTO,
)
img = cv2.imread(
filename="/space_shuttle_224.jpg",
flags=None
)
cv2.cvtColor(
src=img,
code=cv2.COLOR_BGR2RGB,
)
#调用inference接口进行推理
outputs = rknn.inference(
inputs=[img], # inputs表示要推理的数据
data_format="nhwc" # data_format表示要推理的数据格式
)
#对outputs进行后处理
show_outputs(solfmax(np.array([0][0])))
rknn.release()
完成以后python运行,得到该图片验证最高概率是[812],打开\01_课程用到的资料\04_标签,查看[812]是航天飞船,而我们导入作为验证的图片正是该标签图片,到这里就完成了
这里我们切换运行环境, 找到 target=None, 测试rk3588时,更改为 target="rk3588"
(如果没有提前配置adb环境,请输入以下指令进行安装:
请输入指令`sudo apt-get install adb`)
装载好远程环境,指路:https://blog.csdn.net/y8_7_16/article/details/147343334?fromshare=blogdetail&sharetype=blogdetail&sharerId=147343334&sharerefer=PC&sharesource=y8_7_16&sharefrom=from_link运行开发板,输入rknn_serve,确保rk3588的adb连接到Ubuntu虚拟机上,见图标

重新运行该程序,得到运行结果,推理完成。
右键文件inference_pytorch.py复制,粘贴在目录02_inference更改命名为inference_rknn.py
就可以实现直接调用,不需要构建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 = '{:d}: {:.3f}\n'.format(index[j], value)
else:
topi = '-1: 0.000\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(verbose=Ture)
#调用load_rknn接口直接调用RKNN模型
rknn.load_rknn(data="./resnet18.rknn")
rknn.export_rknn(export_path="resnet18.rknn")
#调试初始化接口环境
rknn.init_runtime(
target="rk3588" ,
target_sub_class=None,
device_id=None,
perf_debug=False,
eval_mem=False,
async_mode=False,
core_mask=RKNN.NPU_CORE_AUTO,
)
img = cv2.imread(
filename="/space_shuttle_224.jpg",
flags=None
)
cv2.cvtColor(
src=img,
code=cv2.COLOR_BGR2RGB,
)
#调用inference接口进行推理
outputs = rknn.inference(
inputs=[img], # inputs表示要推理的数据
data_format="nhwc" # data_format表示要推理的数据格式
)
#对outputs进行后处理
show_outputs(solfmax(np.array([0][0])))
rknn.release()
2.3精度分析
流程

2.3.1普通量化
右键新建目录03_accuracy_analysis,新建文件accuracy_analysis.py
找到这个资料04_RNKK模型构建找到01_课程用到的资料的01_pytorch模型,把.pt拷到
前面创建的目录01_export_rknn中(resnet8.pt)
找到这个资料04_RNKK模型构建找到01_课程用到的资料的02_dataset,把.txt和图片拷到
前面创建的目录01_export_rknn中(dataset.txt、图片)
复制粘贴构建模型代码,运行
from rknn.api import RKNN
if __name__ == "__main__":
rknn=RKNN(verbose=Ture)
rknn.config(
mean_values=[[123.675, 116.28, 103.53]],
std_values=[[58.395, 58.395, 58.395]],
target_platform="RK3588"
)
rknn.load_pytorch(
model="./resnet18.pt", input_size_list=[[1, 3, 224, 224]])
rknn.build(
do_quantization=True,
dataset="dataset.txt",
)
rknn.export_rknn(export_path="resnet18.rknn")
# 使用accuracy_analysis接口进行模型量化精度分析
rknn.accuracy_analysis(
inputs=["space_shuttle_224.jpg"], # inputs用来表示进行推理的图像
output_dir="./accuracy_output", # output_dir表示精度分析的输出目录
target=None, # target表示目标硬件平台
device_id=None, # device_id表示设备的编号
)
rknn.release()
得到的日志中:
layer_name:表示模型中各网络层的名称,即当前行对应的是模型里哪一个层。entire(属于quant_error分类下):表示该层在整体量化流程中的量化误差(从整体角度体现该层量化后的误差情况)。per layer(属于quant_error分类下):表示该层自身(针对单个层)的量化误差(仅衡量当前层单独量化时的误差)。
再使用rknn3588自带的模型推理,找到 target=None, 测试rk3588时,更改为 target="rk3588"
运行开发板,输入rknn_serve,确保rk3588的adb连接到Ubuntu虚拟机上,重新运行程序
得到的日志中:
layer_name:模型中各网络层的名称,用于标识当前行对应的是模型里的哪一层。quant_error:量化误差分类,下分两个子项:entire:该层在整体量化流程(从输入到该层等整体链路下)产生的量化误差。per_layer:该层自身单独量化时产生的量化误差。
runtime_error:运行时误差分类,下分两个子项:simu_err:(通常指在模拟环境中运行时)产生的误差。golden_err:作为 “黄金基准” 的误差(一般是高精度计算下的参考误差,用于对比衡量实际运行误差与理想情况的差距)。
这些标题从「层标识」「量化阶段误差」「运行阶段误差」三个维度,细分统计模型各层的精度表现,辅助分析量化和运行过程中误差的分布与来源。
2.3.2混合量化
观察得到量化效果后精度下降明显,故采用混合量化功能,减少精度损失

右键新建目录04_hybrid_quantizaton,新建文件step1.py
找到这个资料04_RNKK模型构建找到01_课程用到的资料的01_pytorch模型,把.pt拷到
前面创建的目录01_export_rknn中(resnet8.pt)
找到这个资料04_RNKK模型构建找到01_课程用到的资料的02_dataset,把.txt和图片拷到
前面创建的目录01_export_rknn中(dataset.txt、图片)
from rknn.api import RKNN
if __name__ == "__main__":
rknn=RKNN(verbose=Ture)
rknn.config(
mean_values=[[123.675, 116.28, 103.53]],
std_values=[[58.395, 58.395, 58.395]],
target_platform="RK3588"
)
rknn.load_pytorch(
model="./resnet18.pt", input_size_list=[[1, 3, 224, 224]])
# 使用hybrid_quantization_step1接口进行混合量化的第一步
rknn.hybrid_quantization_step1(
dataset="dataset.txt", # dataset表示模型量化所需要的数据集
rknn_batch_size=-1, # 表示自动调整模型输入batch数量
proposal=False, # 设置为True,可以自动产生适合量化的配置建议值
proposal_dataset_size=1 # 第三步需要用的图片
)
rknn.release()
运行程序之后生成了以下文件

我们需修改的是后缀为.cfg文件,把某些量化层改为非量化层,因为input.25层精度下降(由日志可得),找到custom_quantize_layers做出以下修改,注意冒号:后面有空格
custom_quantize_layers: {
// 自定义量化层的配置区域,用于指定特定层的量化方式
input.25: float16, // 将名为input.25的网络层,设置为使用float16类型进行量化
'142': float16
接下来创建step2.py

from rknn.api import RKNN
if __name__ == '__main__':
rknn = RKNN()
# 调用hybrid_quantization_step2接口进行混合量化的第二个步骤
rknn.hybrid_quantization_step2(
model_input="resnet18.model", # model_input表示第一步生成的模型文件
data_input="resnet18.data", # data_input表示第一步生成的配置文件
model_quantization_cfg="resnet18.quantization.cfg", # model_quantization_cfg表示第一步生成的量化配置文件
)
# 调用量化精度分析接口 评估RKNN模型
rknn.accuracy_analysis(
inputs=["space_shuttle_224.jpg"],
output_dir="./snapshot",
target="RK3588"
)
# 调用RKNN模型导出接口导出RKNN模型
rknn.export_rknn(export_path="./resnet18.rknn")
rknn.release()
最后运行可知,该层精度得到提升
从哪获取需要更改网络层为非量化效果,通过该网站,打开.rknn模型导入查看网络层结构Netron
https://netron.app/
重新打开step1.py,把 proposal=False, 设置为proposal=True,可以自动产生适合量化的配置建议值,再重新运行
再打开.cfg文件,则能看见自动添加好需混合量化的层

再运行step2.py
完成最终的混合量化结果
2.4模型评估

右键新建目录05_eval,新建文件eval.py
找到这个资料04_RNKK模型构建找到01_课程用到的资料的01_pytorch模型,把.pt拷到
前面创建的目录01_export_rknn中(resnet8.pt)
找到这个资料04_RNKK模型构建找到01_课程用到的资料的02_dataset,把.txt和图片拷到
前面创建的目录01_export_rknn中(dataset.txt、图片)
from rknn.api import RKNN
if __name__ == '__main__':
rknn = RKNN()
# 使用load_rknn接口导入rknn模型
rknn.load_rknn(path="./resnet18.rknn")
# 使用init_runtime接口初始化运行时环境
rknn.init_runtime(
target="RK3588", #只能在板上运行
perf_debug=None, # perf_debug表示是否开启性能评估的debug模式
eval_mem=None, # eval_mem表示是否使能内存评估
)
# 使用eval_perf接口进行性能评估
rknn.eval_perf(
inputs=["space_shuttle_224.jpg"], # inputs表示要测试的图片
data_format=None, # data_format表示要推理的数据模式
is_print=True, # is_print表示使能打印性能信息
)
rknn.release()
启动板子adb服务成功连接到虚拟机,点击运行
日志显示对应的运行时间,和FPS
再将 perf_debug=None, eval_mem=None修改为 perf_debug=True, eval_mem=False就能把各个性能评估参数显示出来了。
对于 内存评估 代码
from rknn.api import RKNN
if __name__ == '__main__':
rknn = RKNN()
# 使用load_rknn接口导入rknn模型
rknn.load_rknn(path="./resnet18.rknn")
# 使用init_runtime接口初始化运行时环境
rknn.init_runtime(
target="RK3588",
perf_debug=True, # perf_debug表示是否开启性能评估的debug模式
eval_mem=True, # eval_mem表示是否使能内存评估
)
# 使用eval_perf接口进行性能评估(当前为注释状态)
# rknn.eval_perf(
# inputs=["space_shuttle_224.jpg"], # inputs表示要测试的图片
# data_format=None, # data_format表示要推理的数据模式
# is_print=True, # is_print 表示使能打印性能信息
# )
# 使用eval_memory接口进行内存评估
rknn.eval_memory(
is_print=True, # 表示使能打印内存评估信息
)
rknn.release()
三、RKNN Toolkit lite2使用
吧
右键新建目录06_rknnToolkitlite2,新建文件rknnToolkitlite2.py
将05_eval的文件.rknn和图片拷到新目录中
①使用rknn.api
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 = '{:d}: {:.3f}\n'.format(index[j], value)
else:
topi = '-1: 0.000\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()
# 使用load_rknn接口直接加载RKNN模型
rknn.load_rknn(path="./resnet18.rknn")
# 调用init_runtime接口初始化运行时环境
rknn.init_runtime(
core_mask=0, # 表示NPU的调度模式
target="RK3588"
)
# 使用opencv获取推理的图片数据
img = cv2.imread(filename="./space_shuttle_224.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 调用Inference接口进行推理测试
outputs = rknn.inference(
inputs=[img],
data_format=None
)
show_outputs(softmax(np.array(outputs[0][0])))
rknn.release()
②使用rknnlite.api,可以拷贝到开发板上运行的程序
from rknnlite.api import RKNNLITE
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 = '{:d}: {:.3f}\n'.format(index[j], value)
else:
topi = '-1: 0.000\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 = RKNNLITE()
# 使用load_rknn接口直接加载RKNN模型
rknn.load_rknn(path="./resnet18.rknn")
# 调用init_runtime接口初始化运行时环境
rknn.init_runtime(
core_mask=0, # 表示NPU的调度模式
)
# 使用opencv获取推理的图片数据
img = cv2.imread(filename="./space_shuttle_224.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 调用Inference接口进行推理测试
outputs = rknn.inference(
inputs=[img],
data_format=None
)
show_outputs(softmax(np.array(outputs[0][0])))
rknn.release()
此前开发板上我们已经配置好rknnToolkitlite2工具使用环境,大致过程如下:
进入(base)

这里需使用python命令创建python3.9的环境和rknn环境
conda create -n rknn python=3.9
conda activate rknn
进入(rknn)
然后是拷rknnToolkitlite2软件包并安装好,pip安装opencv包
。。。
最后直接找到我们拷过来的使用rknnlite.api工具的rknnToolkitlite2.py,python运行,可直接得到推理结果
四、RKNPU2 各个api讲解
先创建新文档,打开终端,把CMAKE拷进文件夹里(\09_RKNN2通API讲解\01_课程用到的资料\01_Cmake工程示例)
mkdir work
cd work
./
文件内指定了编译器路径

现在使用指令删除该文件,把\09_RKNN2 通用 API 讲解 \01_课程用到的资料 \02_交叉编译器 文件内编译器重新拷进去,再把第三方库的\09_RKNN2 通用 API 讲解 \01_课程用到的资料 \03_第三方库的3rdparty拷到work目录下
然后右键运行build.sh,
五、RKNPU2 C例程框架讲解
项目1:yolov5实时目标分类
项目2:sort目标追踪
项目3:车牌识别
更多推荐


所有评论(0)