5.6 KiB
5.6 KiB
示例程序使用说明
概述
本项目提供了一个通用的模型部署框架,支持多种模型(例如 YOLO 系列:yolov4_tiny、yolov5s、yolov8s 等)。 通过本示例,用户可以了解如何根据所选模型部署相应的推理代码,只需修改前后处理函数,其他部分的代码和函数接口保持一致。
文件简介
example 目录结构及其主要功能如下所示:
examples
├── yolov5s
│ ├── postprocess # yolov5s 后处理相关函数接口
│ ├── resource # 相关模型、图片等资源
│ └── yolov5s_demo.c # yolov5s 推理流程示例代码
├── resnet18
│ ├── postprocess # resnet18 后处理相关函数接口
│ ├── resource # 相关模型、图片等资源
│ └── resnet18_demo.c # resnet18 推理流程示例代码
...
└── README.md # 示例说明文档
yolov5s_demo.c
使用 V2.1 接口,推荐使用;yolov4_tiny_demo.c
和yolov8s_demo.c
使用 V1.0 接口(已废弃),保留做兼容性参考。
接口说明
打开与关闭设备
int pnna_open(); // 初始化 Pnna 硬件和驱动资源
int pnna_close(); // 释放硬件资源,关闭驱动
创建模型上下文
app_ctx_t *create_app_ctx(buffer *nbg_buffer,
void *norm_param,
preprocess_cb preprocess,
postprocess_cb postprocess);
- 加载模型并创建推理上下文;
- 可指定预处理与后处理函数;
- 支持从内存读取 NBG 模型数据。
执行推理
int app(app_ctx_t *model, void **output, nn_tensor *input);
- 输入 tensor 将通过预处理函数处理后送入网络;
- 输出结果将调用用户提供的后处理函数;
- 若未设置处理函数,将直接使用原始数据。
销毁模型上下文
void destroy_app_ctx(app_ctx_t *model);
- 自动释放上下文中由分配的所有资源(模型、buffer、quant 参数等)。
示例流程
以 yolov5s 为例
推理主流程
如 yolov5s_demo.c
中所示:
// 1. 打开设备
pnna_open();
// 2. 加载模型
buffer_t *nbg_buffer = read_nbg("yolov5s.nb");
// 3. 创建模型上下文
app_ctx_t *model = create_app_ctx(&nbg_buffer,
&norm_params,
preprocess_normalize_quantize, // 前处理
yolov5s_postprocess_dq); // 后处理
// 如果不需要前后处理
// app_ctx_t *model = create_app_ctx(&nbg_buffer, NULL, NULL, NULL);
// 4. 读取输入数据
nn_tensor input_data = load_image("car.jpg");
// 5. 推理
app(model, output, &input_data);
// 6. 清理资源
destroy_tensor(input_data);
free_nbg_buffer(nbg_buffer);
destroy_app_ctx(model);
// 7. 关闭设备
pnna_close();
多输入模型参数说明
如果模型有多个输入,则需要多次获取输入数据,输入的个数在函数 create_app_ctx() 完成后可获取
int input_count = yolov5s_model->ctx->input_count;
nn_tensor *input = (nn_tensor *)malloc(input_count * sizeof(nn_tensor));
for (int i = 0; i < input_count; ++i) {
input[i] = load_image(image_path);
}
app(model, output, input);
推理结果说明
带后处理
输出结果为最终结果,如 yolov5s_demo.c
中所示,最终结果类型为
detection *output = (detection *)malloc(10 * sizeof(detection));
app(model, (void **)output, input);
请勿使用 detection output[10];
,这种类型在传入 app()
函数时会有类型不匹配的问题
不带后处理
输出结果为 nn_tensor *
类型,使用方法如下:
create_app_ctx(); // 需要先初始化网络后,才能获取网络中的参数
int output_count = yolov5s_model->ctx->output_count;
nn_tensor *output = (nn_tensor *)malloc(output_count * sizeof(nn_tensor));
app(model, (void **)output, input);
请勿使用 nn_tensor output[10];
,这种类型在传入 app()
函数时会有类型不匹配的问题
前后处理说明
- 前处理:由
preprocess_cb
指针注入(如preprocess_normalize_quantize
),实现归一化、量化、图像通道排列等; - 后处理:如
yolov5s_postprocess_dq
,负责输出结果解析(如目标框解码、阈值过滤、NMS等); - 可自由替换以适配不同模型结构。
- 如果不需要前处理,create_app_ctx() 函数中,归一化参数和前处理回调函数均填
NULL
- 如果不需要后处理,create_app_ctx() 函数中,后处理回调函数填
NULL
详细介绍如 nn_api.h
中的函数说明所示。
编译与部署说明
ARM 平台部署
- 使用交叉编译工具链(如
arm-linux-gnueabihf-gcc
)编译示例; - 将可执行文件、模型
.nb
文件、输入图片传至开发板; - 执行部署程序:
./yolov5s_demo
DSP / RT-Thread 平台部署
- 在裸机或 RTOS 下,链接
rtt_dsp/
提供的库文件; - 使用
yolov5s_demo.c
中的#ifdef _TMS320C6X
代码块; - 模型和输入数据地址需事先固定于内存中。
V1.0 接口(不推荐使用,仅保留说明)
以下函数为历史接口,已被 V2.1 封装取代。建议新项目统一使用 V2.1 接口。
int nn_init(nn_context **context, const char *nbg_name, unsigned int timeout); // 初始化模型 @deprecated
int nn_infer(nn_context *context, void **input_buffer, void **output_buffer); // 推理入口 @deprecated
int nn_destroy(nn_context *context); // 释放资源 @deprecated
作者 {{xunyingya}}