eIQ Toolkit上手指南(四)
来源:恩智浦MCU加油站 发布时间:2022-01-20 分享至微信

在上期文章的最后,我们又留下了一个悬念,即模型的部署,现在就让我们填上上期小编留下的坑,我们来看看怎么让我们的模型运行到目标板上。

首先,需要下载我们最新的SDK2.10.0,注意选择组件时,勾选eIQ选项。

下载完成后,找到并打开SDK_2_10_0_MIMXRT1170-EVK\boards\evkmimxrt1170\eiq_examples下的deepviewrt_labelimage例程。由于例程默认使用的是mobilenetv1模型,接下来我们需要将我们的模型添加到工程中,这里要注意,我们所导出的模型格式需要是*.rtm格式, 并将其放到SDK_2_10_0_MIMXRT1170-EVK\boards\evkmimxrt1170\eiq_examples\deepviewrt_labelimage\source\models文件夹下,当然也可以是其他位置。
添加模型的方式,是借助于汇编指令.incbin将模型文件直接导入到工程中并导出对应的符号,具体而言,我们打开model.S,这个就是我们添加模型文件的地方,加入下面几段话:
* 导出符号,以在C函数中使用 */
.global model_cifar10
.global model_cifar10_end

* 导入模型文件 */
model_cifar10:
.incbin “models/cifar10.rtm” /* 需要修改为模型具体路径 */
model_cifar10_end:
这样一来,我们就完成了模型的定义,需要在main.c中添加引用:
extern const unsigned char model_cifar10;
extern const unsigned char model_cifar10_end;
随后,将我们的模型首地址,以及模型尺寸传入下面的API,进行context的初始化以完成模型的正式导入:
const uint8_t *model_end = &model_cifar10_end;
const uint8_t *model = &model_cifar10;
int model_size = model_end - model;
NNError err = nn_context_model_load(context, (size_t) model_size, model);

当然,只有模型当然还是不行的,我们还需要提供测试图片,添加方法类似于添加模型文件,将图片放到SDK_2_10_0_MIMXRT1170-EVK\boards\evkmimxrt1170\eiq_examples\deepviewrt_labelimage\source\data文件夹下,这里我们选用一张可爱的小猫图片:

之后依旧是依靠我们的.incbin指令:

* 导出符号 */
.global sample_img_start
.global sample_img_end

* 导入图片 */
sample_img_start:
.incbin "data/sample.jpg"
sample_img_end:

在main.c中添加引用:

extern const unsigned char sample_img_start;
extern const unsigned char sample_img_end;

将图像数据加载到模型输入tensor中:

const uint8_t *image_end = &sample_img_end;
const uint8_t *sample_image = &sample_img_start;
int sample_image_size = image_end - sample_image;

nn_tensor_load_image_ex(input, sample_image, (size_t) sample_image_size, proc);

这里的input指代的就是我们的模型输入tensor,稍后小编会给大家介绍这个变量是怎么获取的。还有一个比较特殊的参数,叫做proc,这个参数代表了是否需要对图像进行预处理操作:

0:不进行图像的预处理
1:输入图像直接除以255
2:将对图形进行白化操作

有了模型以及模型的输入,我们来分析一下其他所用到的比较重要的API函数,有了他们才能完整的实现模型的推理操作:

函数

作用

NNContext*

nn_context_init(NNEngine* engine,

                size_t    memory_size,

                void*     memory,

                size_t    cache_size,

                void*     cache);

初始化NNContext,可以理解是模型运行的上下文信息
结构体,如果memory指针需要用户传入,存储模型运行
期间的中间结果,如果memory=NULL的话,底层会自动
调用malloc函数进行分配;cache指针被用于DeepView
内部优化,需要指向一块快速内存,如果需要的话。

const uint32_t* nn_model_inputs(
const NNModel* model,
size_t* n_inputs);

获取模型输入tensor编号列表,同时还有可选参数
n_inputs,可以存储输入tensor个数,即模型共有多少
维输入;

NNTensor *nn_context_tensor_index(
NNContext*  context,
size_t index);

根据tensor编号获取tensor

const uint32_t* nn_model_inputs(
const NNModel* model,
size_t* n_outputs);

获取模型输出tensor编号列表,同时还有可选参数
n_outputs,可以存储输出tensor个数,即模型共有
多少维;

NNError nn_context_run(NNContext* context);

运行模型

NNError nn_argmax(
NNTensor* input,
int* index,
 void* value,
size_t value_size);

获取模型运行结果最大值及其所在编号,
value_size指定数指所占字节数

const char* nn_model_label(
const NNModel* model,
int  index);

获取index对应的label值,这里要特殊说明的是,
NNModel中集成了模型的标签,用户无需再手动声明

这样一来,结合着上面我们的模型导入以及测试图片的导入函数,所有我们运行模型所需要的函数就全部凑齐了,亟待召唤神龙!那么详细的代码,还请大家自行翻阅我们的main.c。

到了最振奋人心的时刻了,分析完代码,终于来到了最终的模型部署部分。当然,具体流程就是熟悉的编译,下载过程,此处略去万字操作攻略,连好板子后,复位运行即可看到我们的程序运行结果打印到了控制台上。

那么,我们最后一期的eIQ Toolkit系列文章就到此结束了,小编终于填上了之前埋下的模型部署的坑,希望大家都能够构建自己的神经网络模型,跑出心仪的结果!


[ 新闻来源:恩智浦MCU加油站,更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj]
存入云盘 收藏
举报
全部评论

暂无评论哦,快来评论一下吧!