嵌入式AI部署---基于RK3588运行yolov5(1)
前言
今天主要记录关于yolov5在rk3588上运行的流程,在这之前,你需要将yolov5经过模型训练后的*.pt文件,导出为.onnx, 然后使用RKNN Toolkit 将.onnx 转换成 * . rknn文件。那么什么是RKNN Toolkit?
RKNN Toolkit
瑞芯微(Rockchip)为其NPU提供了一套专用的模型转换和部署工具,叫做 RKNN Toolkit
- 作用: 将各大主流AI框架(如 PyTorch, TensorFlow, ONNX, Caffe, Darknet, Keras 等)训练好的模型,转换为瑞芯微NPU认识的 *.rknn 格式文件
现在我们得到了 * . rknn文件之后如何做呢?
我们参考: 瑞芯微出的Rockchip_RKNPU_User_Guide_RKNN_API_V1.2.0_CN.pdf 这个文档, 这是 RKNPU(神经网络处理单元)的 C 语言 API 指南。当你把模型转换好之后,需要在板端(RK3588)上编写 C/C++ 代码加载模型并运行推理,就要参考这份文档。
1. 部署的流程
根据这个文档,我们只需要调用这些api就能完成对图片的推理
1.1.rknn_init(初始化模型)
流程图含义:加载模型文件,并初始化rknn_context上下文。
- model_data: 导入之前的 *.rknn 的模型文件
ret=rknn_init(&ctx,model_data,model_data_size,RKNN_FLAG_PRIOR_HIGH,NULL);注:还需要额外调用了rknn_set_core_mask来指定使用哪一颗 NPU 核心,这是对流程的补充。
1.2.rknn_query(查询信息)
流程图含义:查询模型的相关属性,如 SDK 版本、输入输出节点数量、张量属性(维度、格式、量化参数等)。
- 输入输出节点数量, 例如输入张量为1个,输出为3个
- 在此处使用的经典 YOLOv5 确实对应三个特征层输出,但很多 RKNN 转换工程为了加速,在模型导出时会将这三个输出合并拼接成一个大的 Tensor(例如形状为
[1, 25200, 85])。因此,输出未必是 3 个,严谨的做法是依赖rknn_query查询到的io_num.n_output动态获得。
- 在此处使用的经典 YOLOv5 确实对应三个特征层输出,但很多 RKNN 转换工程为了加速,在模型导出时会将这三个输出合并拼接成一个大的 Tensor(例如形状为
- 输入张量的维度信息, 例如CHW、HWC等
- 张量格式,也就是数据排布的格式,例如NCHW、NHWC等
- 量化参数:包括量化零点、量化缩放因子,这个用于后续cpu进行后处理反量化
rknn_query(ctx,RKNN_QUERY_SDK_VERSION,...);rknn_query(ctx,RKNN_QUERY_IN_OUT_NUM,...);rknn_query(ctx,RKNN_QUERY_INPUT_ATTR,...);rknn_query(ctx,RKNN_QUERY_OUTPUT_ATTR,...);对于张量:
- 理解:多维数组或数据的容器
- 标量(0维张量):单个数字,如
3.0- 向量(1维张量):一维数组,如
[1, 2, 3]- 矩阵(2维张量):二维表格,如
[[1, 2], [3, 4]]- 更高维张量:如3维(时间序列)、4维(图像数据)、5维(视频数据)等
- 深度学习中的常见形式
- 输入数据:图像通常表示为4维张量
(样本数, 高度, 宽度, 通道数)- 权重参数:神经网络层的权重是2维张量
(输入维度, 输出维度)- 批量处理:一次处理多个样本时,数据总是以批量维度作为第一维
1.3.rknn_inputs_set(设置输入)
流程图含义:将预处理后的图像数据(虚拟地址)传递给 NPU。
- 传递参数之前需要对图像进行颜色转换(BGR—> RGB),BRG是OpenCV的图像读取格式
- 图像放缩到640*640 这个是传参的要求,这个一般是这个数值,但是实际该缩放成多大,完全取决于你导出 ONNX 时设定的输入尺寸,正确的做法是去读取
rknn_query查询到的model_width和model_height。 - 上面这些参数从上面的查询中得到验证
inputs[0].buf=dst_buf;inputs[0].fmt=RKNN_TENSOR_NHWC;inputs[0].type=RKNN_TENSOR_UINT8;rknn_inputs_set(ctx,inputs_num,inputs);1.4.rknn_run(执行推理)
流程图含义:NPU 进行模型前向计算。
ret=rknn_run(ctx,NULL);1.5.rknn_outputs_get(获取输出)
流程图含义:从 NPU 获取推理完成后的输出张量数据。
- 获取输出的张量有三个
rknn_output outputs[outputs_num];rknn_outputs_get(ctx,outputs_num,outputs,NULL);1.6.postprocess_cpu(后处理)
流程图含义:在 CPU 上对模型的裸输出数据进行解码(例如:非极大值抑制 NMS、坐标转换、置信度过滤)。
post_process((int8_t*)outputs[0].buf,...);1.7.rknn_outputs_release(释放输出)
流程图含义:释放rknn_outputs_get分配的缓存资源,防止内存泄漏。
rknn_outputs_release(ctx,outputs_num,outputs);1.8.rknn_destroy(销毁模型)
流程图含义:彻底销毁rknn_context,释放所有资源。
rknn_destroy(ctx);总结
本文主要帮助打造一个rk3588它是如何完成推理的,先有一个大概帮助理解。