当前位置: 首页 > news >正文

【RK3588开发】RKNN库的使用

RKNN库的使用

使用的RKNN库为librknnrt.so和librknn_api.so,两者均为 C 语言接口库

(1)头文件

#include "rknn_api.h"

(2)加载模型

将rknn模型加载至内存

static unsigned char *load_model(const char *filename, int *model_size)
{FILE *fp = fopen(filename, "rb");if (fp == nullptr){printf("fopen %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 fail!\n", filename);free(model);return NULL;}*model_size = model_len;if (fp){fclose(fp);}return model;
}

(3)模型初始化

函数原型:

int rknn_init(rknn_context* context, void* model, int model_len, int flags, rknn_init_extend* extend);
/*
ctx:上下文句柄指针,函数成功调用后,会在此写入已初始化的RKNN上下文句柄。后续所有RKNN操作(如设置输入、执行推理、获取输出)都依赖于这个句柄
model:模型数据指针,指向已加载到内存中的RKNN模型数据的指针
model_len:模型数据长度,指定model指针所指向数据的长度,单位是字节
flags:初始化标志,用于控制初始化行为的位掩码。通常设置为0以使用默认配置
extend:扩展参数指针,指向可选扩展参数的指针,通常设置为NULL
*/

使用示例:

int ret;
rknn_context ctx = 0;
ret = rknn_init(&ctx, model, model_len, 0, NULL);
if (ret < 0)
{printf("rknn_init fail! ret=%d\n", ret);return -1;
}

(4)获得模型输入和输出信息

函数原型:

int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size);
/*
ctx:已初始化的 RKNN 上下文句柄
cmd:查询命令,指定要查询的信息类型
info:指向接收查询结果缓冲区的指针
size:缓冲区的大小
*/
查询命令用途返回结构体
RKNN_QUERY_INPUT_ATTR查询输入属性rknn_input_attr
RKNN_QUERY_OUTPUT_ATTR查询输出属性rknn_output_attr
RKNN_QUERY_SDK_VERSION查询SDK版本rknn_sdk_version
RKNN_QUERY_PERF_DETAIL查询性能详情rknn_perf_detail
RKNN_QUERY_MEM_SIZE查询内存大小rknn_mem_size

使用示例:

信息补充

typedef struct {uint32_t n_input;   // 输入张量数量uint32_t n_output;  // 输出张量数量
} rknn_input_output_num;typedef struct {uint32_t index;           // 输出张量索引uint32_t n_dims;          // 维度数量 (通常是4)uint32_t dims[4];         // 维度值 [batch, height, width, channels]uint32_t size;            // 数据总大小(字节)rknn_type type;           // 数据类型 (FP32, FP16, INT8, UINT8等)rknn_qnt_type qnt_type;   // 量化类型 (NONE, AFFINE等)int32_t zp;               // 零点(量化参数)float scale;              // 缩放系数(量化参数)char name[256];           // 输出张量名称
} rknn_tensor_attr;/*打印输入属性信息*/
static void dump_tensor_attr(rknn_tensor_attr *attr)
{printf("  index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, ""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, get_format_string(attr->fmt), get_type_string(attr->type),get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
}

①获取模型的输入和输出数量

int ret;
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 fail! ret=%d\n", ret);return -1;
}

②获取模型的输入属性信息

int ret;
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 fail! ret=%d\n", ret);return -1;}dump_tensor_attr(&(input_attrs[i]));
}

③获取模型的输出属性信息

int ret;
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 fail! ret=%d\n", ret);return -1;}dump_tensor_attr(&(output_attrs[i]));
}

(5)设置输入数据

信息补充

/*输入数据结构体*/
typedef struct _rknn_input {uint32_t index;                                     //输入索引,对于哪个输入口,索引就是输入口的标识符void* buf;                                          //输入数据指针uint32_t size;                                      //输入数据大小uint8_t pass_through;                               //直通模式//若为TRUE(直通模式开启):缓冲区(buf)中的数据会直接传递到 rknn 模型的输入节点,不做任何转换。这种情况下,后续相关的变量无需设置。//若为FALSE(直通模式关闭):缓冲区数据会根据后续设置的类型(type)和格式(fmt)进行转换,以匹配模型的输入要求。这种情况下,需要设置后续相关变量。rknn_tensor_type type;                              //数据类型rknn_tensor_format fmt;                             //数据格式
//currently the internal input format of NPU is NCHW by default.
//so entering NCHW data can avoid the format conversion in the driver.
} rknn_input;

函数原型:

int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]);
/*
context:RKNN模型的上下文句柄,用于标识和管理加载的模型实例。
n_inputs:需要设置的输入数量。
inputs[]:输入结构体数组,包含了每个输入张量的具体信息,inputs[]表示指针
*/

使用示例:

int ret;
rknn_input inputs[1];
memset(inputs, 0, sizeof(inputs));inputs[0].index = 0;
inputs[0].type = input_attr.type;
inputs[0].size = input_attr.size;
inputs[0].fmt = input_attr.fmt;
inputs[0].buf = data_buf;
ret = rknn_inputs_set(ctx, io_num.n_input, inputs);
if (ret < 0)
{printf("rknn_input_set fail! ret=%d\n", ret);return -1;
}

(6)运行模型

函数原型:

int rknn_run(rknn_context context, rknn_run_extend* extend);/*
context:RKNN模型的上下文句柄,用于标识和管理加载的模型实例
extend:扩展参数指针,用于设置推理时的额外选项,在大多数情况下可以设置为NULL
*/

使用示例:

int ret;
ret = rknn_run(ctx, NULL);
if (ret < 0)
{printf("rknn_run fail! ret=%d\n", ret);return -1;
}

(7)获取输出信息

信息补充

/*数据数据结构*/
typedef struct _rknn_output {uint8_t want_float;                                 /*作用: 指定是否将输出数据转换为浮点数格式,1: 希望将输出数据转换为浮点数0: 保持原始数据类型(通常是量化后的int8/int16)*/uint8_t is_prealloc;                                //指定输出缓冲区是否由用户预分配,默认不分配uint32_t index;                                     //输出张量的索引编号void* buf;                                          //输出缓冲区的指针uint32_t size;                                      //输出缓冲区的大小} rknn_output;

函数原型:

int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend);
/*
context:RKNN模型的上下文句柄,用于标识和管理加载的模型实例。
n_inputs:输出数量。
outputs[]:输出结构体数组,包含了每个输出张量的具体信息
extend:扩展参数指针,在大多数情况下可以设置为NULL
*/

使用示例:

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 fail! ret=%d\n", ret);return -1;
}

(8)释放输出缓冲区

因为每一次获取数据,都会自动分配的输出缓冲区内存,rknn_outputs_release函数释放由 RKNN 运行时自动分配的输出缓冲区内存,避免内存泄漏

函数原型:

int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]);
/*
context:RKNN模型的上下文句柄,用于标识和管理加载的模型实例。
n_ouputs:要释放的输出数量。
outputs[]:输出结构体数组,
*/

使用示例:

rknn_outputs_release(ctx, 1, outputs);

(9)资源清理函数

函数原型:

int rknn_destroy(rknn_context context);
//context:RKNN模型的上下文句柄,用于标识和管理加载的模型实例。

使用示例:

rknn_destroy(ctx);
http://www.dtcms.com/a/495237.html

相关文章:

  • 使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 18--测试框架Pytest基础 2--插件和参数化
  • 玩具 网站模板成立一个网站
  • 阿里网站注册阿里云网站怎么建设
  • 【排查实录】Web 页面能打开,服务器能通接口,客户端却访问失败?原因全在这!
  • 【Linux】系统性能排查:解决卡顿问题
  • 建网站要注意的细节建免费的网站
  • 手机网站建设收费网站建设 合肥
  • Qwen3-0.6模型开关思考模式测试
  • FT62FC3X 8位MCU单片机选型表,详细解析FT62FC31A/32A/33A/35A/3FA
  • 鸿蒙NEXT Sensor Service Kit开发指南:解锁传感器数据的无限潜能
  • 开源项目:FlyCut Caption智能视频字幕裁剪工具
  • Fedora 16上源码建立pydev + eclipse的OpenStack开发环境笔记草稿
  • 便携式榨汁机方案开发,榨汁机果汁机MCU控制方案设计
  • 杭州如何做百度的网站网页是什么
  • 【软考备考】软件架构设计需要考虑系统性能 如何使用缓存提高系统性能知识点七
  • 南京做网站dmooo学校自己做的网站需要买服务器吗
  • 鸿蒙实现可以上下左右滑动的表格-摆脱大量ListScroller
  • 笔试强训:Week -2
  • webpack - 单独打包指定JS文件(因为不确定打出的前端包所访问的后端IP,需要对项目中IP配置文件单独拿出来,方便运维部署的时候对IP做修改)
  • 有的网站打开的是html结尾的路径有的不是wordpress放在二级目录
  • 展示型企业网站设计方案2016年做网站能赚钱
  • 【论文精读】RD-Agent-Quant:基于多智能体框架的量化因子与模型研发自动化系统
  • 网站开发大概价格建设电子商务网站流程
  • Python 练习脚本(从基础到高级150个练习)
  • GDDR6总结(1)-背景及优劣
  • Redis 中文学习手册
  • 网站改版 程序变了 原来的文章内容链接地址 打不开怎么办以百度云做网站空间
  • iOS 混淆工具链实战,多工具组合完成 IPA 混淆与加固(iOS混淆|IPA加固|无源码混淆|App 防反编译)
  • 莞城做网站wordpress 插件数据
  • YouTube 视频评论,并插入 MySQL