在上期文章的最后,我们又留下了一个悬念,即模型的部署,现在就让我们填上上期小编留下的坑,我们来看看怎么让我们的模型运行到目标板上。
* 导出符号,以在C函数中使用 */
.global model_cifar10
.global model_cifar10_end
* 导入模型文件 */
model_cifar10:
.incbin “models/cifar10.rtm” /* 需要修改为模型具体路径 */
model_cifar10_end:
extern const unsigned char model_cifar10;
extern const unsigned char model_cifar10_end;
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,这个参数代表了是否需要对图像进行预处理操作:
有了模型以及模型的输入,我们来分析一下其他所用到的比较重要的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系列文章就到此结束了,小编终于填上了之前埋下的模型部署的坑,希望大家都能够构建自己的神经网络模型,跑出心仪的结果!
暂无评论哦,快来评论一下吧!