diff --git a/example/deep_learning_framework/Flowchart.png b/example/deep_learning_framework/Flowchart.png
index d6018c17a9116b72f2ebc10e38e39764d2ec0058..259edc2ea89ea40b6ae6fbe9c2b55686086bcc05 100644
Binary files a/example/deep_learning_framework/Flowchart.png and b/example/deep_learning_framework/Flowchart.png differ
diff --git a/example/deep_learning_framework/Principle.png b/example/deep_learning_framework/Principle.png
index 0ef12d2b71f31949258eed17f55dd852f8307586..47efe5ed1e0e396225b66bc1897b5062b973c990 100644
Binary files a/example/deep_learning_framework/Principle.png and b/example/deep_learning_framework/Principle.png differ
diff --git a/example/deep_learning_framework/README_zh.md b/example/deep_learning_framework/README_zh.md
index ef8e58e655f3e6d25ef4f8aa871850551eca3007..7ab304c04fde523a1bb460d09f38dd4b08505c72 100644
--- a/example/deep_learning_framework/README_zh.md
+++ b/example/deep_learning_framework/README_zh.md
@@ -1,49 +1,64 @@
-# Tensorflow Lite 接入NNRt Delegate Demo开发指南
+# TensorFlow Lite接入NNRt Delegate开发指南
## 概述
+神经网络运行时部件(NNRt)是跨设备的AI运行时框架,作为端侧推理框架和专用加速芯片的中间桥梁,为端侧推理框架提供了统一的Native接口。
-### 功能简介
-- 神经网络运行时部件(NNRt)是跨设备的AI运行时框架,作为端侧推理框架和专用加速芯片的中间桥梁,为端侧推理框架提供了统一的Native接口;
-- 本demo旨在介绍上层AI业务如何利用NNRt在专有芯片上加速推理,使能OpenHarmony社区生态;
-- 本demo根据用户输入参数(模型、标签、模型输入shape、循环浮点推理次数、是否允许动态尺寸推理、以及是否打印结果等)完成标签分类模型推理,用户可通过打印信息观察在不同条件下的模型推理性能、精度等KIP。
-
-### 基本概念
-在开发前,开发者需要先了解以下概念,以便更好地理解全文内容:
-- NNRt: Neural Network Runtime,神经网络运行时,是本指导主要介绍的部件。
-- OHOS:OpenHarmony Operating System,开源鸿蒙操作系统。
-
-### 约束与限制
-- 系统版本:OpenHarmonyOS 3.2及以上
-- 开发环境:Ubuntu 18.04及以上
-- 接入设备:OpenHarmony定义的标准设备
-- 其他开发依赖:
- - tensorflow-lite.so及其依赖库,目前完成在tensorflow lite 2.6版本上的测试;
- - NNRt库libneural_network_runtime.z.so;
- - TensorFlow Lite头文件:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite;
- - mobilenetv2.tflite模型(https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.4_224.tgz);
- - 标签文件labels.txt;
- - 测试图片grace_hopper.bmp;
-
-### 运作机制
-

-
- - 用户调用TFLite的BuildFromFile接口完成初始构图;
- - 用户设置自定义的参数options,应用于创建NnrtDelegate;
- - 用户创建DelegateProviders,并调用DelegateProviders的CreateAllRankedDelegates接口创建NnrtDelegate,创建NnrtDelegate过程中dlopen打开NNRt的动态库,并加载API,返回delegate;
- - 用户调用ModifyGraphWithDelegate接口完成Node替换,其中该步分四个步骤;
- - Initalize初始化NnrtDelegate;
- - 判断图中各node是否支持NnrtDelegate,返回支持的node集合;
- - 调用TFLiteRegistration注册NnrtDelegate,并初始化init, prepare, invoke成员函数指针,指向delegateKernel的Init, Prepare和run函数方法;
- - 替换TensorFlow Delegate的node为已注册的NNrt delegate kernel, 并调用Init完成构图步骤;
- - 用户调用AllocateTensors,完成内存分配和图编译,其中支持delegate的node会转到delegateKernel的prepare完成编译,不支持delegate的会调用原有tflite node的prepare编译;
- - 用户调用Invoke完成图执行;
-
-### 开发流程
-
-
-### 开发步骤
+本demo旨在介绍TensorFlow Lite推理框架如何接入NNRt,并在专有芯片上加速推理,接入OpenHarmony社区生态。
+
+本demo根据用户输入参数(模型、标签、模型输入shape、循环浮点推理次数、是否允许动态尺寸推理、以及是否打印结果等)完成标签分类模型推理,用户可通过打印信息观察在不同条件下的模型推理性能、精度和预测类别。
+
+## 基本概念
+在开发前,开发者需要先了解以下概念,以便更好地理解全文内容:
+- NNRt:Neural Network Runtime,神经网络运行时,是本指导主要介绍的部件。
+- OHOS:OpenHarmony Operating System,OpenHarmony操作系统。
+
+## 约束与限制
+1. 系统版本:OpenHarmonyOS 3.2 Beta5及以上版本。
+2. 开发环境:Ubuntu 18.04及以上。
+3. 接入设备:OpenHarmony定义的标准设备。
+4. 其他开发依赖:
+获取TensorFlow Lite头文件,[获取链接](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite)。
+ - tensorflow-lite.so及其依赖库(参考[编译指导](#调测命令)编译生成),目前完成在tensorflow lite 2.6版本上的测试。
+ - NNRt动态库libneural_network_runtime.z.so,参考[编译指导](https://gitee.com/openharmony-sig/neural_network_runtime/blob/master/README_zh.md)编译生成。
+ - mobilenetv2的Tensorflow lite模型,[获取链接](https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.4_224.tgz)。
+ - 标签文件labels.txt,可从[压缩包](https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz)中解压得到。
+ - 测试图片grace_hopper.bmp,[获取链接](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp)。
+
+## 运作机制
+
+**图1** 运作机制
+
+
+
+以TensorFlow lite的MobileNetv2模型进行标签分类任务为例,实现调用NNRt API在指定芯片上加速推理,主要有以下三个部分:
+1. 通过TFLite delegate机制,创建NNRt Delegate,并接入TFLite的Hardware Accelerator中。
+2. 将TensorFlow lite模型中能在NNRt上运行的op kernels,替换成NNRt Delegate kernels。
+3. 推理过程中,被替换成NNRt Delegate Kernel的op kernel会调用Neural Network Runtime中的API在指定芯片上完成模型的构图、编译和执行。
+
+## 开发流程
+
+**图2** 开发流程
+
+
+
+主要开发步骤包括命令行参数解析、创建NNRt Delegate、TFLite nodes的替换、tensors的内存分配、执行推理、结果查看等,具体如下:
+1. 解析运行demoe的命令,初始化模型推理所需参数和创建NNRt Delegate的options。
+2. 调用Tensorflow lite的BuildFromFile接口完成Tensorflow lite模型的构建。
+3. 根据demo的运行命令解析模型是否需要动态输入,如果需要,则调用ResizeInputTensor接口更改模型输入大小。
+4. 创建DelegateProviders,并调用DelegateProviders的CreateAllRankedDelegates接口创建NnrtDelegate;创建NnrtDelegate过程中,通过dlopen打开NNRt的动态库来加载NNRt API。
+5. 调用ModifyGraphWithDelegate接口完成Node替换,其中该步分四个步骤:
+ - 初始化NnrtDelegate。
+ - 判断TFLite图中各node是否支持在NnrtDelegate上运行,返回支持的node集合。
+ - 调用TFLiteRegistration注册NnrtDelegate,并初始化init,prepare,invoke成员函数指针,指向NnrtDelegateKernel的Init,Prepare和run函数方法。
+ - 替换TensorFlow Delegate的node为已注册的NNrt delegate kernel,并调用Init完成构图过程。
+6. 用户调用AllocateTensors,完成tensors内存分配和图编译。其中,支持在NNRtDelegate上运行的node会调用NnrtDelegateKernel的prepare接口完成编译,不支持的会调用tflite operation kernels的prepare编译。
+7. 导入输入数据并调用Invoke完成图执行。
+8. 结果输出。
+
+
+## 开发步骤
本节主要描述NNRt接入TFLite的TFLite-delegate代理机制,重点对TFLite调用delegate的流程和delegate对接NNRt的方式进行了介绍。
-TensorFlow Lite Delegate有两个基类DelegateProvider、TfLiteDelegate, 本节主要描述继承这两个基类得到子类NnrtDelegate和NnrtDelegateProvider。
+TensorFlow Lite Delegate有两个基类DelegateProvider、TfLiteDelegate,本节主要描述继承这两个基类得到子类NnrtDelegate和NnrtDelegateProvider。
本demo主要文件目录结构如下图:
```text
@@ -51,41 +66,101 @@ TensorFlow Lite Delegate有两个基类DelegateProvider、TfLiteDelegate, 本节
├── CMakeLists.txt
├── delegates
│ └── nnrt_delegate
-│ ├── CMakeLists.txt
-│ ├── nnrt_delegate.cpp
-│ ├── nnrt_delegate.h
-│ ├── nnrt_delegate_kernel.cpp
-│ ├── nnrt_delegate_kernel.h
-│ ├── nnrt_delegate_provider.cpp
-│ ├── nnrt_op_builder.cpp
-│ ├── nnrt_op_builder.h
-│ ├── nnrt_utils.cpp
-│ ├── nnrt_utils.h
-│ └── tensor_mapping.h
+│ ├── CMakeLists.txt # 生成libnnrt_delegate.so的交叉编译规则文件
+│ ├── nnrt_delegate.cpp # NnrtDelegate源文件,对接到NNRt上,使TensorFlow Lite模型能运行在加速芯片上
+│ ├── nnrt_delegate.h # NnrtDelegate头文件
+│ ├── nnrt_delegate_kernel.cpp # NnrtDelegateKernel源文件,将TensorFlow Lite模型中的operators替换成Nnrt中的operators
+│ ├── nnrt_delegate_kernel.h # NnrtDelegateKernel头文件
+│ ├── nnrt_delegate_provider.cpp # 用于创建NNrtDelegate
+│ ├── nnrt_op_builder.cpp # NnrtOpBuilder源文件,给每个operators设置输入输出tensor和operation属性
+│ ├── nnrt_op_builder.h # NnrtOpBuilder头文件
+│ ├── nnrt_utils.cpp # 用于辅助创建NnrtDelegate工具方法的源文件
+│ ├── nnrt_utils.h # 用于辅助创建NnrtDelegate工具方法的头文件
+│ └── tensor_mapping.h # TensorFlow Lite Tensor到Nnrt tensor的转换头文件
├── label_classify
-│ ├── CMakeLists.txt
-│ ├── label_classify.cpp
-│ └── label_classify.h
+│ ├── CMakeLists.txt # 生成可执行文件label_classify的交叉编译规则文件
+│ ├── label_classify.cpp # 生成可执行文件label_classify的源文件
+│ └── label_classify.h # 生成可执行文件label_classify的头文件
├── nnrt
-│ ├── CMakeLists.txt
-│ ├── nnrt_implementation.cpp
-│ └── nnrt_implementation.h
+│ ├── CMakeLists.txt # 生成libnnrt_implementation.so的交叉编译规则文件
+│ ├── nnrt_implementation.cpp # 生成libnnrt_implementation.so的源文件,用于加载NNRt Api
+│ └── nnrt_implementation.h # 生成libnnrt_implementation.so的头文件
└── tools
- ├── bitmap_helpers.cpp
- ├── bitmap_helpers.h
- ├── get_topn.h
- ├── log.h
- ├── utils.cpp
- └── utils.h
+ ├── bitmap_helpers.cpp # 用于读取输入的bmp格式图片源文件
+ ├── bitmap_helpers.h # 用于读取输入的bmp格式图片头文件
+ ├── get_topn.h # 用于返回推理的top N结果
+ ├── log.h # 日志模块文件
+ ├── utils.cpp # 用于辅助模型推理输入和输出工具方法的源文件
+ └── utils.h # 用于辅助模型推理输入和输出工具方法的头文件
```
-1. 创建Tensorflow Lite NnrtDelegate类
- - Tensorflow Lite NNRt Delegate 使TensorFlow Lite模型能够运行在NNRt框架(https://gitee.com/openharmony/neural_network_runtime)上,这导致了在OHOS设备上更快的模型推理
- - nnrt_delegate依赖nnrt_delegate_kernel, nnrt_delegate_kernel(将支持替换的TensorFlow Lite模型中的operators替换成Nnrt中的operators)依赖nnrt_op_builder(给每个operators设置输入输出tensor和operation属性),完成nnrt_delegate的自定义。
+1. 创建NnrtDelegate类。
+
+ NnrtDelegate类定义在nnrt_delegate文件中,用于对接NNRt,使TensorFlow Lite模型能运行在加速芯片上。用户需要实现DoPrepare接口、GetSupportedNodes接口、GetDelegateKernelRegistration接口,详细代码参考[链接](https://gitee.com/openharmony-sig/neural_network_runtime/blob/master/example/deep_learning_framework/tflite/delegates/nnrt_delegate/nnrt_delegate.cpp)。主要步骤有以下两点:
+ - 获取TensorFlow Lite中能替换的nodes。
+ ```cpp
+ TfLiteNode* node = nullptr;
+ TfLiteRegistration* registration = nullptr;
+ for (auto nodeIndex : TfLiteIntArrayView(executionPlan)) {
+ node = nullptr;
+ registration = nullptr;
+ TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration(context, nodeIndex, &node, ®istration));
+ if (NnrtDelegateKernel::Validate(registration->builtin_code)) {
+ supportedNodes.emplace_back(nodeIndex);
+ } else {
+ TFLITE_LOG_PROD(TFLITE_LOG_WARNING,
+ "[NNRT-DELEGATE] Get unsupportted node: %d.", registration->builtin_code);
+ }
+ }
+ ```
+
+ - 注册的Delegate kernel,初始化TfLiteRegistration的init,prepare,invoke成员函数指针,指向NnrtDelegateKernel的Init,Prepare和run函数方法。
+ ```cpp
+ nnrtDelegateKernel.init = [](TfLiteContext* context, const char* buffer, size_t length) -> void* {
+ if (buffer == nullptr) {
+ return nullptr;
+ }
+ const TfLiteDelegateParams* params = reinterpret_cast(buffer);
+ auto* delegateData = static_cast(params->delegate->data_);
+ NnrtDelegateKernel* state = new (std::nothrow) NnrtDelegateKernel(delegateData->nnrt);
+ if (state == nullptr) {
+ TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to create NnrtDelegateKernel instance.");
+ return state;
+ }
-2. 创建NnrtDelegateProvider
- - NnrtDelegateProvider依赖nnrt_implementation(用于加载libneural_network_runtime.z.so中的Api)和nnrt_delegate(用于创建子类NnrtDelegate对象),完成与TFLite的对接;
+ TfLiteStatus status = state->Init(context, params);
+ if (status != kTfLiteOk) {
+ TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to init NnrtDelegateKernel.");
+ delete state;
+ state = nullptr;
+ }
+ return state;
+ };
+ nnrtDelegateKernel.prepare = [](TfLiteContext* context, TfLiteNode* node) -> TfLiteStatus {
+ if (node == nullptr) {
+ TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to prepare delegate kernels, the node is nullptr.");
+ return kTfLiteError;
+ }
+
+ NnrtDelegateKernel* state = reinterpret_cast(node->user_data);
+ return state->Prepare(context, node);
+ };
+
+ nnrtDelegateKernel.invoke = [](TfLiteContext* context, TfLiteNode* node) -> TfLiteStatus {
+ if (node == nullptr) {
+ TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to invoke delegate kernels, the node is nullptr.");
+ return kTfLiteError;
+ }
+
+ NnrtDelegateKernel* state = reinterpret_cast(node->user_data);
+ return state->Invoke(context, node);
+ };
+ ```
+
+2. 创建NnrtDelegateProvider。
+
+ NnrtDelegateProvider定义在nnrt_delegate_provider文件中,用于创建NNrtDelegate,完成与TFLite的对接。主要步骤有以下两点:
- 注册NnrtDelegateProvider
```cpp
REGISTER_DELEGATE_PROVIDER(NnrtDelegateProvider);
@@ -105,16 +180,17 @@ TensorFlow Lite Delegate有两个基类DelegateProvider、TfLiteDelegate, 本节
[](TfLiteDelegate* delegate) { delete reinterpret_cast(delegate); });
```
-3. label_classify.cpp中加载Nnrt_Delegate
+3. label_classify.cpp中加载NnrtDelegate,并完成node的替换。
```cpp
interpreter->ModifyGraphWithDelegate(std::move(delegate.delegate))
```
-### 调测命令
-1. 编译生成Tensorflow Lite库及其依赖库
- 请参考Tensorflow Lite交叉编译指南(https://www.tensorflow.org/lite/guide/build_cmake_arm), 同时在```tensorflow/lite/CMakeLists.txt```中增加以下内容:
+
+## 调测命令
+1. 编译生成Tensorflow Lite库及其依赖库。
+
+ 请参考[Tensorflow Lite交叉编译指南](https://www.tensorflow.org/lite/guide/build_cmake_arm),同时在```tensorflow/lite/CMakeLists.txt```中增加以下内容:
```text
- # TODO: TFLite External Delegate
list(APPEND TFLITE_EXTERNAL_DELEGATE_SRC
${TFLITE_SOURCE_DIR}/tools/delegates/delegate_provider.cc
# ${TFLITE_SOURCE_DIR}/tools/delegates/external_delegate_provider.cc
@@ -142,77 +218,121 @@ TensorFlow Lite Delegate有两个基类DelegateProvider、TfLiteDelegate, 本节
${TFLITE_TARGET_DEPENDENCIES}
)
```
-2. 编译生成NNRt库libneural_network_runtime.z.so
- 请参考编译指导(https://gitee.com/openharmony/build),编译命令如下
+
+2. 编译生成NNRt库libneural_network_runtime.z.so。
+
+ 请参考[编译指导](https://gitee.com/openharmony-sig/neural_network_runtime/blob/master/README_zh.md),编译命令如下:
```shell
- ./build.sh --product-name rk3568 –ccache --jobs=16 --build-target=neural_network_runtime
+ ./build.sh --product-name rk3568 –ccache --jobs=16 --build-target=neural_network_runtime
```
-3. 用cmake编译北向demo
- - 将TensorFlow Lite头文件(https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite)和编译生成的TensorFlow Lite库,分别放在```deep_learning_framework/lib_3rd_nnrt_tflite/include/tensorflow/lite/```和```deep_learning_framework/lib_3rd_nnrt_tflite/com/arm64-v8a/lib/```下;
- - 指定ohos的cmake, ohos.toolchain.cmake路径,在```foundation/ai/neural_network_runtime/example/cmake_build/build_ohos_tflite.sh```中替换以下两行;
- ```shell
- ./tool_chain/native/build-tools/cmake/bin/cmake \
- -DCMAKE_TOOLCHAIN_FILE=./tool_chain/native/cmake_build/cmake/ohos.toolchain.cmake \
- ```
- - 进入```foundation/ai/neural_network_runtime/example/cmake_build```:
- - 如果需要在arm32架构的CPU上运行:
- - 修改```tflite/CMakeLists.txt```
+
+3. 用cmake编译北向demo。
+
+ - TensorFlow Lite头文件和依赖库配置。
+
+ 将[TensorFlow Lite头文件](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite)和编译生成的TensorFlow Lite库,分别放在```deep_learning_framework/lib_3rd_nnrt_tflite/include/tensorflow/lite/```和```deep_learning_framework/lib_3rd_nnrt_tflite/com/arm64-v8a/lib/```下。
+
+ - 交叉编译工具配置。
+
+ 在社区的[每日构建](http://ci.openharmony.cn/dailys/dailybuilds)下载对应系统版本的ohos-sdk压缩包,从压缩包中提取对应平台的Native开发套件;指定ohos的cmake, ohos.toolchain.cmake路径,在```foundation/ai/neural_network_runtime/example/cmake_build/build_ohos_tflite.sh```中替换以下两行:
+ ```shell
+ ./tool_chain/native/build-tools/cmake/bin/cmake \
+ -DCMAKE_TOOLCHAIN_FILE=./tool_chain/native/cmake_build/cmake/ohos.toolchain.cmake \
+ ```
+
+ - 修改交叉编译文件。
+
+ 进入```foundation/ai/neural_network_runtime/example/cmake_build```,执行以下修改:
+
+ 如果需要在arm32架构的CPU上运行:
+
+ # 修改```tflite/CMakeLists.txt```
```text
set(CMAKE_CXX_FLAGS "-pthread -fstack-protector-all -fPIC -D_FORTIFY_SOURCE=2 -march=armv7-a")
```
- - 执行编译命令
+ # 执行编译命令
```shell
bash build_ohos_tflite.sh armeabi-v7a
```
- - 如果需要在arm64架构的CPU上运行:
- - 修改```tflite/CMakeLists.txt```
+
+ 如果需要在arm64架构的CPU上运行:
+
+ # 修改```tflite/CMakeLists.txt```
```text
set(CMAKE_CXX_FLAGS "-pthread -fstack-protector-all -fPIC -D_FORTIFY_SOURCE=2 -march=armv8-a")
```
- - 执行编译命令
+
+ # 执行编译命令
```shell
bash build_ohos_tflite.sh arm64-v8a
```
- - 在```example/deep_learning_framework/```目录下创建lib和output两个文件夹:
+
+ - 创建目录
+
+ 在```example/deep_learning_framework/```目录下创建lib和output两个文件夹:
```shell
mkdir lib output
```
- - 进入```foundation/ai/neural_network_runtime/example/cmake_build```, 执行链接命令:
+
+ - 执行链接命令
+
+ 进入```foundation/ai/neural_network_runtime/example/cmake_build```,执行链接命令:
```shell
make
```
- - 北向demo成功编译完成后会在```deep_learning_framework/lib```生成libnnrt_delegate.so和libnnrt_implementation.so, 在```deep_learning_framework/output```下生成label_classify可执行文件,目录结构体如下所示。
-
- ```text
- deep_learning_framework
- ├── lib
- │ ├── libnnrt_delegate.so # 生成的TensorFlow Lite nnrt delegate库
- │ └── libnnrt_implementation.so # 生成的nnrt在TensorFlow Lite中接口实现库
- └── output
- └── label_classify # 生成的可执行文件
- ```
-4. 在开发板上运行北向demo
- - 将步骤1生成的libnnrt_implementation.so, libnnrt_delegate.so和可执行文件label_classify, libneural_network_runtime.z.so, tensorflow-lite.so及其依赖的库, mobilenetv2.tflite模型, 标签labels.txt, 测试图片grace_hopper.bmp推送到开发板上:
- ```shell
- # 假设上述待推送文件均放在push_files/文件夹下
- hdc_std file send push_files/ /data/demo/
- ```
- - 进入开发板,执行demo前需要添加环境变量,文件执行权限等:
- ```shell
- # 进入开发板
- hdc_std shell
+ - 结果查看
- # 进入推送文件目录,并增加可执行文件权限
- cd /data/demo
- chmod +x ./label_classify
+ 北向demo成功编译完成后会在```deep_learning_framework/lib```生成libnnrt_delegate.so和libnnrt_implementation.so,在```deep_learning_framework/output```下生成label_classify可执行文件,目录结构体如下所示:
- # 添加环境变量
- export LD_LIBRARY_PATH=/data/demo:$LD_LIBRARY_PATH
+ ```text
+ deep_learning_framework
+ ├── lib
+ │ ├── libnnrt_delegate.so # 生成的TensorFlow Lite nnrt delegate库
+ │ └── libnnrt_implementation.so # 生成的nnrt在TensorFlow Lite中接口实现库
+ └── output
+ └── label_classify # 生成的可执行文件
+ ```
- # 执行demo,-m tflite模型, -i 测试图片, -l 数据标签, -a 1表示使用nnrt, 0表示不使用nnrt推理,-z 1 表示打印输出张量大小的结果
- ./label_classify -m mobilenetv2.tflite -i grace_hopper.bmp -l labels.txt -a 1 -z 1
- ```
+4. 在开发板上运行北向demo。
+
+ - 推送文件至开发板
+
+ 将步骤1生成的libnnrt_implementation.so、libnnrt_delegate.so和可执行文件label_classify,libneural_network_runtime.z.so、tensorflow-lite.so及其依赖的库、mobilenetv2.tflite模型、标签labels.txt、测试图片grace_hopper.bmp推送到开发板上:
+ ```shell
+ # 假设上述待推送文件均放在push_files/文件夹下
+ hdc_std file send push_files/ /data/demo/
+ ```
+
+ - 执行demo
+
+ 进入开发板,执行demo前需要添加环境变量,文件执行权限等:
+ ```shell
+ # 进入开发板
+ hdc_std shell
+
+ # 进入推送文件目录,并增加可执行文件权限
+ cd /data/demo
+ chmod +x ./label_classify
+
+ # 添加环境变量
+ export LD_LIBRARY_PATH=/data/demo:$LD_LIBRARY_PATH
+
+ # 执行demo,-m tflite模型, -i 测试图片, -l 数据标签, -a 1表示使用nnrt, 0表示不使用nnrt推理,-z 1 表示打印输出张量大小的结果
+ ./label_classify -m mobilenetv2.tflite -i grace_hopper.bmp -l labels.txt -a 1 -z 1
+ ```
+
+ - 结果查看
+
+ demo成功执行后,可以看到以下运行结果:
+ ```text
+ INFO: invoked, average time: 194.972 ms
+ INFO: 0.536433: 653 653:military uniform
+ INFO: 0.102077: 835 835:suit, suit of clothes
+ INFO: 0.0398081: 466 466:bulletproof vest
+ INFO: 0.0251576: 907 907:Windsor tie
+ INFO: 0.0150422: 440 440:bearskin, busby, shako
+ ```
-### 开发实例
-完整[Demo实例](xxx, Demo暂时还在黄区代码仓,超链接需等Demo开源后补充)可以参考社区实现。
+## 开发实例
+完整demo可以参考社区实现[Demo实例](https://gitee.com/openharmony-sig/neural_network_runtime/tree/master/example/deep_learning_framework)。
diff --git a/example/deep_learning_framework/tflite/delegates/nnrt_delegate/nnrt_delegate_kernel.cpp b/example/deep_learning_framework/tflite/delegates/nnrt_delegate/nnrt_delegate_kernel.cpp
index 05933aeea2daba081ed6a9af0266a3967d32abc3..98b7ac11f5b866144e286b1252f64085ae484e0e 100644
--- a/example/deep_learning_framework/tflite/delegates/nnrt_delegate/nnrt_delegate_kernel.cpp
+++ b/example/deep_learning_framework/tflite/delegates/nnrt_delegate/nnrt_delegate_kernel.cpp
@@ -1,4 +1,5 @@
-/*
+ "neural_network_runtime.h",
+ "neural_network_runtime_type.h",/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,13 +42,13 @@ namespace delegate {
namespace nnrt {
constexpr int32_t SCALAR_RANK = 1;
-#define RETURN_TFLITE_ERROR_IF_NN_ERROR_FOR_COMPILE(code, callDesc) \
+#define RETURN_TFLITE_ERROR_IF_NN_ERROR_FOR_COMPILE(code, callDesc) \
do { \
if ( (code) != OH_NN_SUCCESS) { \
- const auto errorDesc = NnrtErrorDescription((code)); \
- TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "NN API returned error %s at line %d while %s.\n", errorDesc.c_str(), \
+ const auto errorDesc = NnrtErrorDescription((code)); \
+ TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "NN API returned error %s at line %d while %s.\n", errorDesc.c_str(), \
__LINE__, (callDesc)); \
- m_nnrt->OH_NNCompilation_Destroy(&m_pNnCompilation); \
+ m_nnrt->OH_NNCompilation_Destroy(&m_pNnCompilation); \
return kTfLiteError; \
} \
} while (0)
@@ -417,4 +418,4 @@ TfLiteStatus NnrtDelegateKernel::SetNnOptions(TfLiteContext* context, const Nnrt
}
} // namespace nnrt
} // namespace delegate
-} // tflite
\ No newline at end of file
+} // tflite
diff --git a/example/deep_learning_framework/tflite/label_classify/label_classify.cpp b/example/deep_learning_framework/tflite/label_classify/label_classify.cpp
index 18b8506db90b05d0e65282d1a056b93283010999..0d2852c5ce064be6301077b0244117c522f064af 100644
--- a/example/deep_learning_framework/tflite/label_classify/label_classify.cpp
+++ b/example/deep_learning_framework/tflite/label_classify/label_classify.cpp
@@ -250,9 +250,9 @@ void InferenceModel(Settings& settings, DelegateProviders& delegateProviders)
void DisplayUsage()
{
- LOG(INFO) << "label_classify\n"
+ LOG(INFO) << "label_classify -m xxx.tflite -i xxx.bmp -l xxx.txt -c 1 -a 1\n"
<< "\t--help, -h: show the usage of the demo\n"
- << "\t--use_nnrt, -a: [0|1], use NNRT or not\n"
+ << "\t--use_nnrt, -a: [0|1], use NNRT or not\n"
<< "\t--input_mean, -b: input mean\n"
<< "\t--count, -c: loop interpreter->Invoke() for certain times\n"
<< "\t--image, -i: image_name.bmp\n"
@@ -266,8 +266,13 @@ void DisplayUsage()
<< "\t--input_shape, -p: Indicates the specified dynamic input node and the corresponding shape.\n";
}
-void InitSettings(int32_t argc, char** argv, Settings& settings)
+int32_t InitSettings(int32_t argc, char** argv, Settings& settings)
{
+ if (argc <= 1) {
+ DisplayUsage();
+ return -1;
+ }
+
// getopt_long stores the option index here.
int32_t optionIndex = 0;
while ((optionIndex = getopt_long(argc, argv, "a:b:c:h:i:l:m:n:p:s:v:w:z:", LONG_OPTIONS, nullptr)) != -1) {
@@ -312,11 +317,13 @@ void InitSettings(int32_t argc, char** argv, Settings& settings)
case '?':
// getopt_long already printed an error message.
DisplayUsage();
- return;
+ return -1;
default:
- return;
+ return -1;
}
}
+
+ return 0;
}
int32_t Main(int32_t argc, char** argv)
@@ -328,7 +335,10 @@ int32_t Main(int32_t argc, char** argv)
}
Settings settings;
- InitSettings(argc, argv, settings);
+ if (InitSettings(argc, argv, settings) == -1) {
+ return EXIT_FAILURE;
+ };
+
InferenceModel(settings, delegateProviders);
return 0;
}