!4533 【Sample】新增MindSporeLite C Demo
Merge pull request !4533 from 钱丹/master
7
OAT.xml
@ -271,6 +271,13 @@ Note:If the text contains special characters, please escape them according to th
|
|||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/AppScope/resources/base/media/app_icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/AppScope/resources/base/media/app_icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/screenshots/MindSporeLiteArkTSDemo.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/screenshots/MindSporeLiteArkTSDemo.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/ohosTest/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/startIcon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/background.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/foreground.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/AppScope/resources/base/media/app_icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/screenshots/MindSporeLiteCDemoPic.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/screenshots/newability.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/screenshots/newability.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
||||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/StageModelAbilityInteraction/screenshot/coldstartuppage.png" desc="Provided by code/DocsSample/ApplicationModels/StageModelAbilityInteraction"/>
|
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/StageModelAbilityInteraction/screenshot/coldstartuppage.png" desc="Provided by code/DocsSample/ApplicationModels/StageModelAbilityInteraction"/>
|
||||||
|
12
code/DocsSample/ApplicationModels/MindSporeLiteCDemo/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/node_modules
|
||||||
|
/oh_modules
|
||||||
|
/local.properties
|
||||||
|
/.idea
|
||||||
|
**/build
|
||||||
|
/.hvigor
|
||||||
|
.cxx
|
||||||
|
/.clangd
|
||||||
|
/.clang-format
|
||||||
|
/.clang-tidy
|
||||||
|
**/.test
|
||||||
|
/.appanalyzer
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"bundleName": "com.samples.mindsporelitecdemo",
|
||||||
|
"vendor": "samples",
|
||||||
|
"versionCode": 1000000,
|
||||||
|
"versionName": "1.0.0",
|
||||||
|
"icon": "$media:app_icon",
|
||||||
|
"label": "$string:app_name"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "app_name",
|
||||||
|
"value": "MindSporeLiteCDemo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,85 @@
|
|||||||
|
# **基于**Native**接口的MindSpore Lite应用开发**
|
||||||
|
|
||||||
|
### 介绍
|
||||||
|
|
||||||
|
本文基于MindSpore Lite提供的[Native API](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-mindspore-lite-kit/_mind_spore.md),实现“图像分类”示例程序,来演示端侧部署的流程。
|
||||||
|
|
||||||
|
1. 选择图像分类模型。
|
||||||
|
2. 将模型转换成MindSpore Lite模型格式。
|
||||||
|
3. 使用MindSpore Lite推理模型,显示出可能的分类结果。
|
||||||
|
|
||||||
|
### 效果预览
|
||||||
|
|
||||||
|
| 主页 |
|
||||||
|
| -------------------------------------------------- |
|
||||||
|
| <img src="screenshots/MindSporeLiteCDemoPic.png"/> |
|
||||||
|
|
||||||
|
#### 使用说明
|
||||||
|
|
||||||
|
1. 在主界面,可以点击photo按钮,进入相册选择图片界面;
|
||||||
|
2. 在相册界面,选择图片,点击确定按钮;
|
||||||
|
3. 自动进行选择图片的图像分类模型推理,部分推理结果显示在主界面。
|
||||||
|
|
||||||
|
### 工程目录
|
||||||
|
|
||||||
|
```
|
||||||
|
entry
|
||||||
|
├── src/main
|
||||||
|
│ ├── etc
|
||||||
|
| | └── pages
|
||||||
|
| | └── Index.ets // 首页,获取图片及预处理
|
||||||
|
│ ├── cpp
|
||||||
|
| | └── mslite_napi.cpp // 推理函数
|
||||||
|
| | └── CMakeLists.txt // 编译脚本
|
||||||
|
| | └── types
|
||||||
|
| | └── libentry
|
||||||
|
| | └── Index.t.ts // 将C++动态库封装成JS模块
|
||||||
|
│ ├── resources // 资源文件
|
||||||
|
| | └── rawfile
|
||||||
|
| | └── mobilenetv2.ms // 存放的模型文件
|
||||||
|
```
|
||||||
|
|
||||||
|
### 具体实现
|
||||||
|
|
||||||
|
* 本示例程序中使用的终端图像分类模型文件为mobilenetv2.ms,放置在entry\src\main\resources\rawfile工程目录下。
|
||||||
|
|
||||||
|
注:可手工下载模型文件[mobilenetv2.ms](https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/1.5/mobilenetv2.ms)。
|
||||||
|
|
||||||
|
* 调用[@ohos.file.picker](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-picker.md) (图片文件选择)、[@ohos.multimedia.image](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-image-kit/js-apis-image.md) (图片处理效果)、[@ohos.file.fs](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md) (基础文件操作) 等API实现相册图片获取及图片处理。完整代码请参见Index.ets。
|
||||||
|
|
||||||
|
* 调用[MindSpore Lite Native API](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-mindspore-lite-kit/_mind_spore.md)实现推理。完整代码请参见mslite_napi.cpp。
|
||||||
|
|
||||||
|
* 编写CMake脚本。链接MindSpore Lite动态库,完整代码请参见CMakeLists.txt。
|
||||||
|
|
||||||
|
* 使用N-API将C++动态库封装成JS模块。在 entry/src/main/cpp/types/libentry/index.d.ts,定义JS接口`runDemo()` 。
|
||||||
|
|
||||||
|
* 调用推理函数并处理结果。完整代码请参见Index.ets
|
||||||
|
|
||||||
|
### 相关权限
|
||||||
|
|
||||||
|
无。
|
||||||
|
|
||||||
|
### 依赖
|
||||||
|
|
||||||
|
无。
|
||||||
|
|
||||||
|
### 约束与限制
|
||||||
|
|
||||||
|
1.本示例仅支持标准系统上运行,测试设备:RK3568;
|
||||||
|
|
||||||
|
2.本示例为Stage模型,已适配API version 11版本SDK;
|
||||||
|
|
||||||
|
3.本示例需要使用DevEco Studio 4.1 Release及以上版本才可编译运行。
|
||||||
|
|
||||||
|
### 下载
|
||||||
|
|
||||||
|
如需单独下载本工程,执行如下命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
git init
|
||||||
|
git config core.sparsecheckout true
|
||||||
|
echo code/BasicFeature/ApplicationModels/MindSporeLiteCDemo/ > .git/info/sparse-checkout
|
||||||
|
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
|
||||||
|
git pull origin master
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"signingConfigs": [
|
||||||
|
],
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"signingConfig": "default",
|
||||||
|
"compatibleSdkVersion": 11,
|
||||||
|
"compileSdkVersion": 11,
|
||||||
|
"runtimeOS": "OpenHarmony"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buildModeSet": [
|
||||||
|
{
|
||||||
|
"name": "debug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "entry",
|
||||||
|
"srcPath": "./entry",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"applyToProducts": [
|
||||||
|
"default"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
6
code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/node_modules
|
||||||
|
/oh_modules
|
||||||
|
/.preview
|
||||||
|
/build
|
||||||
|
/.cxx
|
||||||
|
/.test
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"apiType": "stageMode",
|
||||||
|
"buildOption": {
|
||||||
|
"externalNativeOptions": {
|
||||||
|
"path": "./src/main/cpp/CMakeLists.txt",
|
||||||
|
"abiFilters": ['arm64-v8a', 'armeabi-v7a', 'x86_64'],
|
||||||
|
"arguments": "",
|
||||||
|
"cppFlags": "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buildOptionSet": [
|
||||||
|
{
|
||||||
|
"name": "release",
|
||||||
|
"arkOptions": {
|
||||||
|
"obfuscation": {
|
||||||
|
"ruleOptions": {
|
||||||
|
"enable": true,
|
||||||
|
"files": [
|
||||||
|
"./obfuscation-rules.txt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nativeLib": {
|
||||||
|
"debugSymbol": {
|
||||||
|
"strip": true,
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"name": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ohosTest",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||||
|
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
# Define project specific obfuscation rules here.
|
||||||
|
# You can include the obfuscation configuration files in the current module's build-profile.json5.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
|
||||||
|
|
||||||
|
# Obfuscation options:
|
||||||
|
# -disable-obfuscation: disable all obfuscations
|
||||||
|
# -enable-property-obfuscation: obfuscate the property names
|
||||||
|
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
|
||||||
|
# -compact: remove unnecessary blank spaces and all line feeds
|
||||||
|
# -remove-log: remove all console.* statements
|
||||||
|
# -print-namecache: print the name cache that contains the mapping from the old names to new names
|
||||||
|
# -apply-namecache: reuse the given cache file
|
||||||
|
|
||||||
|
# Keep options:
|
||||||
|
# -keep-property-name: specifies property names that you want to keep
|
||||||
|
# -keep-global-name: specifies names that you want to keep in the global scope
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "entry",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Please describe the basic information.",
|
||||||
|
"main": "",
|
||||||
|
"author": "",
|
||||||
|
"license": "",
|
||||||
|
"dependencies": {
|
||||||
|
"libentry.so": "file:./src/main/cpp/types/libentry"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
# the minimum version of CMake.
|
||||||
|
cmake_minimum_required(VERSION 3.4.1)
|
||||||
|
project(MindSporeLiteCDemo)
|
||||||
|
|
||||||
|
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if(DEFINED PACKAGE_FIND_FILE)
|
||||||
|
include(${PACKAGE_FIND_FILE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(${NATIVERENDER_ROOT_PATH}
|
||||||
|
${NATIVERENDER_ROOT_PATH}/include)
|
||||||
|
|
||||||
|
add_library(entry SHARED mslite_napi.cpp)
|
||||||
|
target_link_libraries(entry PUBLIC mindspore_lite_ndk)
|
||||||
|
target_link_libraries(entry PUBLIC hilog_ndk.z)
|
||||||
|
target_link_libraries(entry PUBLIC rawfile.z)
|
||||||
|
target_link_libraries(entry PUBLIC ace_napi.z)
|
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "napi/native_api.h"
|
||||||
|
#include <hilog/log.h>
|
||||||
|
#include <rawfile/raw_file_manager.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <mindspore/types.h>
|
||||||
|
#include <mindspore/model.h>
|
||||||
|
#include <mindspore/context.h>
|
||||||
|
#include <mindspore/status.h>
|
||||||
|
#include <mindspore/tensor.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#define LOGI(...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||||
|
#define LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||||
|
#define LOGW(...) ((void)OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||||
|
#define LOGE(...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||||
|
|
||||||
|
constexpr int K_NUM_PRINT_OF_OUT_DATA = 20;
|
||||||
|
|
||||||
|
int FillInputTensor(OH_AI_TensorHandle input, std::vector<float> input_data)
|
||||||
|
{
|
||||||
|
if (OH_AI_TensorGetDataType(input) == OH_AI_DATATYPE_NUMBERTYPE_FLOAT32) {
|
||||||
|
float *data = (float *)OH_AI_TensorGetMutableData(input);
|
||||||
|
for (size_t i = 0; i < OH_AI_TensorGetElementNum(input); i++) {
|
||||||
|
data[i] = input_data[i];
|
||||||
|
}
|
||||||
|
return OH_AI_STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
return OH_AI_STATUS_LITE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ReadModelFile(NativeResourceManager *nativeResourceManager, const std::string &modelName, size_t *modelSize)
|
||||||
|
{
|
||||||
|
auto rawFile = OH_ResourceManager_OpenRawFile(nativeResourceManager, modelName.c_str());
|
||||||
|
if (rawFile == nullptr) {
|
||||||
|
LOGE("MS_LITE_ERR: Open model file failed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
long fileSize = OH_ResourceManager_GetRawFileSize(rawFile);
|
||||||
|
if (fileSize <= 0) {
|
||||||
|
LOGE("MS_LITE_ERR: FileSize not correct");
|
||||||
|
}
|
||||||
|
void *modelBuffer = malloc(fileSize);
|
||||||
|
if (modelBuffer == nullptr) {
|
||||||
|
LOGE("MS_LITE_ERR: OH_ResourceManager_ReadRawFile failed");
|
||||||
|
}
|
||||||
|
int ret = OH_ResourceManager_ReadRawFile(rawFile, modelBuffer, fileSize);
|
||||||
|
if (ret == 0) {
|
||||||
|
LOGI("MS_LITE_LOG: OH_ResourceManager_ReadRawFile failed");
|
||||||
|
OH_ResourceManager_CloseRawFile(rawFile);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
OH_ResourceManager_CloseRawFile(rawFile);
|
||||||
|
*modelSize = fileSize;
|
||||||
|
return modelBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyModelBuffer(void **buffer)
|
||||||
|
{
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(*buffer);
|
||||||
|
*buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OH_AI_ModelHandle CreateMSLiteModel(void *modelBuffer, size_t modelSize)
|
||||||
|
{
|
||||||
|
// Set executing context for model.
|
||||||
|
auto context = OH_AI_ContextCreate();
|
||||||
|
if (context == nullptr) {
|
||||||
|
DestroyModelBuffer(&modelBuffer);
|
||||||
|
LOGE("MS_LITE_ERR: Create MSLite context failed.\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto cpu_device_info = OH_AI_DeviceInfoCreate(OH_AI_DEVICETYPE_CPU);
|
||||||
|
OH_AI_DeviceInfoSetEnableFP16(cpu_device_info, true);
|
||||||
|
OH_AI_ContextAddDeviceInfo(context, cpu_device_info);
|
||||||
|
|
||||||
|
// Create model
|
||||||
|
auto model = OH_AI_ModelCreate();
|
||||||
|
if (model == nullptr) {
|
||||||
|
DestroyModelBuffer(&modelBuffer);
|
||||||
|
LOGE("MS_LITE_ERR: Allocate MSLite Model failed.\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build model object
|
||||||
|
auto build_ret = OH_AI_ModelBuild(model, modelBuffer, modelSize, OH_AI_MODELTYPE_MINDIR, context);
|
||||||
|
DestroyModelBuffer(&modelBuffer);
|
||||||
|
if (build_ret != OH_AI_STATUS_SUCCESS) {
|
||||||
|
OH_AI_ModelDestroy(&model);
|
||||||
|
LOGE("MS_LITE_ERR: Build MSLite model failed.\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
LOGI("MS_LITE_LOG: Build MSLite model success.\n");
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunMSLiteModel(OH_AI_ModelHandle model, std::vector<float> input_data)
|
||||||
|
{
|
||||||
|
// Set input data for model.
|
||||||
|
auto inputs = OH_AI_ModelGetInputs(model);
|
||||||
|
auto ret = FillInputTensor(inputs.handle_list[0], input_data);
|
||||||
|
if (ret != OH_AI_STATUS_SUCCESS) {
|
||||||
|
LOGE("MS_LITE_ERR: RunMSLiteModel set input error.\n");
|
||||||
|
return OH_AI_STATUS_LITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get model output.
|
||||||
|
auto outputs = OH_AI_ModelGetOutputs(model);
|
||||||
|
|
||||||
|
// Predict model.
|
||||||
|
auto predict_ret = OH_AI_ModelPredict(model, inputs, &outputs, nullptr, nullptr);
|
||||||
|
if (predict_ret != OH_AI_STATUS_SUCCESS) {
|
||||||
|
OH_AI_ModelDestroy(&model);
|
||||||
|
LOGE("MS_LITE_ERR: MSLite Predict error.\n");
|
||||||
|
return OH_AI_STATUS_LITE_ERROR;
|
||||||
|
}
|
||||||
|
LOGI("MS_LITE_LOG: Run MSLite model Predict success.\n");
|
||||||
|
|
||||||
|
// Print output tensor data.
|
||||||
|
LOGI("MS_LITE_LOG: Get model outputs:\n");
|
||||||
|
for (size_t i = 0; i < outputs.handle_num; i++) {
|
||||||
|
auto tensor = outputs.handle_list[i];
|
||||||
|
LOGI("MS_LITE_LOG: - Tensor %{public}d name is: %{public}s.\n", static_cast<int>(i),
|
||||||
|
OH_AI_TensorGetName(tensor));
|
||||||
|
LOGI("MS_LITE_LOG: - Tensor %{public}d size is: %{public}d.\n", static_cast<int>(i),
|
||||||
|
(int)OH_AI_TensorGetDataSize(tensor));
|
||||||
|
LOGI("MS_LITE_LOG: - Tensor data is:\n");
|
||||||
|
auto out_data = reinterpret_cast<const float *>(OH_AI_TensorGetData(tensor));
|
||||||
|
std::stringstream outStr;
|
||||||
|
for (int i = 0; (i < OH_AI_TensorGetElementNum(tensor)) && (i <= K_NUM_PRINT_OF_OUT_DATA); i++) {
|
||||||
|
outStr << out_data[i] << " ";
|
||||||
|
}
|
||||||
|
LOGI("MS_LITE_LOG: %{public}s", outStr.str().c_str());
|
||||||
|
}
|
||||||
|
return OH_AI_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value RunDemo(napi_env env, napi_callback_info info)
|
||||||
|
{
|
||||||
|
// run demo
|
||||||
|
napi_value error_ret;
|
||||||
|
napi_create_int32(env, -1, &error_ret);
|
||||||
|
// 传入数据处理
|
||||||
|
size_t argc = 2;
|
||||||
|
napi_value argv[2] = {nullptr};
|
||||||
|
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
|
||||||
|
bool isArray = false;
|
||||||
|
napi_is_array(env, argv[0], &isArray);
|
||||||
|
uint32_t length = 0;
|
||||||
|
// 获取数组的长度
|
||||||
|
napi_get_array_length(env, argv[0], &length);
|
||||||
|
std::vector<float> input_data;
|
||||||
|
double param = 0;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
napi_value value;
|
||||||
|
napi_get_element(env, argv[0], i, &value);
|
||||||
|
napi_get_value_double(env, value, ¶m);
|
||||||
|
input_data.push_back(static_cast<float>(param));
|
||||||
|
}
|
||||||
|
std::stringstream outstr;
|
||||||
|
for (int i = 0; i < K_NUM_PRINT_OF_OUT_DATA; i++) {
|
||||||
|
outstr << input_data[i] << " ";
|
||||||
|
}
|
||||||
|
// Read model file
|
||||||
|
const std::string modelName = "mobilenetv2.ms";
|
||||||
|
size_t modelSize;
|
||||||
|
auto resourcesManager = OH_ResourceManager_InitNativeResourceManager(env, argv[1]);
|
||||||
|
auto modelBuffer = ReadModelFile(resourcesManager, modelName, &modelSize);
|
||||||
|
if (modelBuffer == nullptr) {
|
||||||
|
return error_ret;
|
||||||
|
}
|
||||||
|
auto model = CreateMSLiteModel(modelBuffer, modelSize);
|
||||||
|
int ret = RunMSLiteModel(model, input_data);
|
||||||
|
if (ret != OH_AI_STATUS_SUCCESS) {
|
||||||
|
OH_AI_ModelDestroy(&model);
|
||||||
|
return error_ret;
|
||||||
|
}
|
||||||
|
napi_value out_data;
|
||||||
|
napi_create_array(env, &out_data);
|
||||||
|
auto outputs = OH_AI_ModelGetOutputs(model);
|
||||||
|
OH_AI_TensorHandle output_0 = outputs.handle_list[0];
|
||||||
|
float *output0Data = reinterpret_cast<float *>(OH_AI_TensorGetMutableData(output_0));
|
||||||
|
for (size_t i = 0; i < OH_AI_TensorGetElementNum(output_0); i++) {
|
||||||
|
napi_value element;
|
||||||
|
napi_create_double(env, static_cast<double>(output0Data[i]), &element);
|
||||||
|
napi_set_element(env, out_data, i, element);
|
||||||
|
}
|
||||||
|
OH_AI_ModelDestroy(&model);
|
||||||
|
return out_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C_START
|
||||||
|
static napi_value Init(napi_env env, napi_value exports)
|
||||||
|
{
|
||||||
|
napi_property_descriptor desc[] = {{"runDemo", nullptr, RunDemo, nullptr, nullptr, nullptr, napi_default, nullptr}};
|
||||||
|
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
|
||||||
|
return exports;
|
||||||
|
}
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
static napi_module demoModule = {
|
||||||
|
.nm_version = 1,
|
||||||
|
.nm_flags = 0,
|
||||||
|
.nm_filename = nullptr,
|
||||||
|
.nm_register_func = Init,
|
||||||
|
.nm_modname = "entry",
|
||||||
|
.nm_priv = ((void *)0),
|
||||||
|
.reserved = {0},
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const runDemo: (a: number[], b:Object) => Array<number>;
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "libentry.so",
|
||||||
|
"types": "./index.d.ts",
|
||||||
|
"version": "",
|
||||||
|
"description": "MindSpore Lite inference module"
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||||
|
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
|
import { window } from '@kit.ArkUI';
|
||||||
|
|
||||||
|
export default class EntryAbility extends UIAbility {
|
||||||
|
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy(): void {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||||
|
}
|
||||||
|
|
||||||
|
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||||
|
// Main window is created, set main page for this ability
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||||
|
|
||||||
|
windowStage.loadContent('pages/Index', (err) => {
|
||||||
|
if (err.code) {
|
||||||
|
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onWindowStageDestroy(): void {
|
||||||
|
// Main window is destroyed, release UI related resources
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||||
|
}
|
||||||
|
|
||||||
|
onForeground(): void {
|
||||||
|
// Ability has brought to foreground
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackground(): void {
|
||||||
|
// Ability has back to background
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,264 @@
|
|||||||
|
import resourceManager from '@ohos.resourceManager'
|
||||||
|
import fileIo from '@ohos.file.fs';
|
||||||
|
import msliteNapi from 'libentry.so'
|
||||||
|
import picker from '@ohos.file.picker';
|
||||||
|
import { BusinessError } from '@ohos.base';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
|
||||||
|
const TAG = 'MindSporeLite';
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct Index {
|
||||||
|
@State message: string = 'MindSporeLite C Demo';
|
||||||
|
@State modelName: string = 'mobilenetv2.ms';
|
||||||
|
@State modelInputHeight: number = 224;
|
||||||
|
@State modelInputWidth: number = 224;
|
||||||
|
@State uris: Array<string> = [];
|
||||||
|
@State max: number = 0;
|
||||||
|
@State maxIndex: number = 0;
|
||||||
|
@State maxArray: Array<number> = [];
|
||||||
|
@State maxIndexArray: Array<number> = [];
|
||||||
|
@State labelsNameMap: string[] = [
|
||||||
|
'Herd', 'Safari', 'Bangle', 'Cushion', 'Countertop',
|
||||||
|
'Prom', 'Branch', 'Sports', 'Sky', 'Community',
|
||||||
|
'Wheel', 'Cola', 'Tuxedo', 'Flowerpot', 'Team',
|
||||||
|
'Computer', 'Unicycle', 'Brig', 'Aerospace engineering', 'Scuba diving',
|
||||||
|
'Goggles', 'Fruit', 'Badminton', 'Horse', 'Sunglasses',
|
||||||
|
'Fun', 'Prairie', 'Poster', 'Flag', 'Speedboat',
|
||||||
|
'Eyelash', 'Veil', 'Mobile phone', 'Wheelbarrow', 'Saucer',
|
||||||
|
'Leather', 'Drawer', 'Paper', 'Pier', 'Waterfowl',
|
||||||
|
'Tights', 'Rickshaw', 'Vegetable', 'Handrail', 'Ice',
|
||||||
|
'Metal', 'Flower', 'Wing', 'Silverware', 'Event',
|
||||||
|
'Skyline', 'Money', 'Comics', 'Handbag', 'Porcelain',
|
||||||
|
'Rodeo', 'Curtain', 'Tile', 'Human mouth', 'Army',
|
||||||
|
'Menu', 'Boat', 'Snowboarding', 'Cairn terrier', 'Net',
|
||||||
|
'Pasteles', 'Cup', 'Rugby', 'Pho', 'Cap',
|
||||||
|
'Human hair', 'Surfing', 'Loveseat', 'Museum', 'Shipwreck',
|
||||||
|
'Trunk (Tree)', 'Plush', 'Monochrome', 'Volcano', 'Rock',
|
||||||
|
'Pillow', 'Presentation', 'Nebula', 'Subwoofer', 'Lake',
|
||||||
|
'Sledding', 'Bangs', 'Tablecloth', 'Necklace', 'Swimwear',
|
||||||
|
'Standing', 'Jeans', 'Carnival', 'Softball', 'Centrepiece',
|
||||||
|
'Skateboarder', 'Cake', 'Dragon', 'Aurora', 'Skiing',
|
||||||
|
'Bathroom', 'Dog', 'Needlework', 'Umbrella', 'Church',
|
||||||
|
'Fire', 'Piano', 'Denim', 'Bridle', 'Cabinetry',
|
||||||
|
'Lipstick', 'Ring', 'Television', 'Roller', 'Seal',
|
||||||
|
'Concert', 'Product', 'News', 'Fast food', 'Horn (Animal)',
|
||||||
|
'Tattoo', 'Bird', 'Bridegroom', 'Love', 'Helmet',
|
||||||
|
'Dinosaur', 'Icing', 'Miniature', 'Tire', 'Toy',
|
||||||
|
'Icicle', 'Jacket', 'Coffee', 'Mosque', 'Rowing',
|
||||||
|
'Wetsuit', 'Camping', 'Underwater', 'Christmas', 'Gelato',
|
||||||
|
'Whiteboard', 'Field', 'Ragdoll', 'Construction', 'Lampshade',
|
||||||
|
'Palace', 'Meal', 'Factory', 'Cage', 'Clipper (Boat)',
|
||||||
|
'Gymnastics', 'Turtle', 'Human foot', 'Marriage', 'Web page',
|
||||||
|
'Human beard', 'Fog', 'Wool', 'Cappuccino', 'Lighthouse',
|
||||||
|
'Lego', 'Sparkler', 'Sari', 'Model', 'Temple',
|
||||||
|
'Beanie', 'Building', 'Waterfall', 'Penguin', 'Cave',
|
||||||
|
'Stadium', 'Smile', 'Human hand', 'Park', 'Desk',
|
||||||
|
'Shetland sheepdog', 'Bar', 'Eating', 'Neon', 'Dalmatian',
|
||||||
|
'Crocodile', 'Wakeboarding', 'Longboard', 'Road', 'Race',
|
||||||
|
'Kitchen', 'Odometer', 'Cliff', 'Fiction', 'School',
|
||||||
|
'Interaction', 'Bullfighting', 'Boxer', 'Gown', 'Aquarium',
|
||||||
|
'Superhero', 'Pie', 'Asphalt', 'Surfboard', 'Cheeseburger',
|
||||||
|
'Screenshot', 'Supper', 'Laugh', 'Lunch', 'Party ',
|
||||||
|
'Glacier', 'Bench', 'Grandparent', 'Sink', 'Pomacentridae',
|
||||||
|
'Blazer', 'Brick', 'Space', 'Backpacking', 'Stuffed toy',
|
||||||
|
'Sushi', 'Glitter', 'Bonfire', 'Castle', 'Marathon',
|
||||||
|
'Pizza', 'Beach', 'Human ear', 'Racing', 'Sitting',
|
||||||
|
'Iceberg', 'Shelf', 'Vehicle', 'Pop music', 'Playground',
|
||||||
|
'Clown', 'Car', 'Rein', 'Fur', 'Musician',
|
||||||
|
'Casino', 'Baby', 'Alcohol', 'Strap', 'Reef',
|
||||||
|
'Balloon', 'Outerwear', 'Cathedral', 'Competition', 'Joker',
|
||||||
|
'Blackboard', 'Bunk bed', 'Bear', 'Moon', 'Archery',
|
||||||
|
'Polo', 'River', 'Fishing', 'Ferris wheel', 'Mortarboard',
|
||||||
|
'Bracelet', 'Flesh', 'Statue', 'Farm', 'Desert',
|
||||||
|
'Chain', 'Aircraft', 'Textile', 'Hot dog', 'Knitting',
|
||||||
|
'Singer', 'Juice', 'Circus', 'Chair', 'Musical instrument',
|
||||||
|
'Room', 'Crochet', 'Sailboat', 'Newspaper', 'Santa claus',
|
||||||
|
'Swamp', 'Skyscraper', 'Skin', 'Rocket', 'Aviation',
|
||||||
|
'Airliner', 'Garden', 'Ruins', 'Storm', 'Glasses',
|
||||||
|
'Balance', 'Nail (Body part)', 'Rainbow', 'Soil ', 'Vacation ',
|
||||||
|
'Moustache', 'Doily', 'Food', 'Bride ', 'Cattle',
|
||||||
|
'Pocket', 'Infrastructure', 'Train', 'Gerbil', 'Fireworks',
|
||||||
|
'Pet', 'Dam', 'Crew', 'Couch', 'Bathing',
|
||||||
|
'Quilting', 'Motorcycle', 'Butterfly', 'Sled', 'Watercolor paint',
|
||||||
|
'Rafting', 'Monument', 'Lightning', 'Sunset', 'Bumper',
|
||||||
|
'Shoe', 'Waterskiing', 'Sneakers', 'Tower', 'Insect',
|
||||||
|
'Pool', 'Placemat', 'Airplane', 'Plant', 'Jungle',
|
||||||
|
'Armrest', 'Duck', 'Dress', 'Tableware', 'Petal',
|
||||||
|
'Bus', 'Hanukkah', 'Forest', 'Hat', 'Barn',
|
||||||
|
'Tubing', 'Snorkeling', 'Cool', 'Cookware and bakeware', 'Cycling',
|
||||||
|
'Swing (Seat)', 'Muscle', 'Cat', 'Skateboard', 'Star',
|
||||||
|
'Toe', 'Junk', 'Bicycle', 'Bedroom', 'Person',
|
||||||
|
'Sand', 'Canyon', 'Tie', 'Twig', 'Sphynx',
|
||||||
|
'Supervillain', 'Nightclub', 'Ranch', 'Pattern', 'Shorts',
|
||||||
|
'Himalayan', 'Wall', 'Leggings', 'Windsurfing', 'Deejay',
|
||||||
|
'Dance', 'Van', 'Bento', 'Sleep', 'Wine',
|
||||||
|
'Picnic', 'Leisure', 'Dune', 'Crowd', 'Kayak',
|
||||||
|
'Ballroom', 'Selfie', 'Graduation', 'Frigate', 'Mountain',
|
||||||
|
'Dude', 'Windshield', 'Skiff', 'Class', 'Scarf',
|
||||||
|
'Bull', 'Soccer', 'Bag', 'Basset hound', 'Tractor',
|
||||||
|
'Swimming', 'Running', 'Track', 'Helicopter', 'Pitch',
|
||||||
|
'Clock', 'Song', 'Jersey', 'Stairs', 'Flap',
|
||||||
|
'Jewellery', 'Bridge', 'Cuisine', 'Bread', 'Caving',
|
||||||
|
'Shell', 'Wreath', 'Roof', 'Cookie', 'Canoe'
|
||||||
|
];
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Row() {
|
||||||
|
Column() {
|
||||||
|
Text(this.message)
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold);
|
||||||
|
//图片显示
|
||||||
|
Image(this.uris[0]).width(320).height(540).margin(15)
|
||||||
|
//显示分类最大值
|
||||||
|
if (this.max) {
|
||||||
|
Text(this.labelsNameMap[this.maxIndexArray[0]] +
|
||||||
|
': ' +
|
||||||
|
(this.maxArray[0] / 100).toString() +
|
||||||
|
'%\n' +
|
||||||
|
this.labelsNameMap[this.maxIndexArray[1]] +
|
||||||
|
': ' +
|
||||||
|
(this.maxArray[1] / 100).toString() +
|
||||||
|
'%\n' +
|
||||||
|
this.labelsNameMap[this.maxIndexArray[2]] +
|
||||||
|
': ' +
|
||||||
|
(this.maxArray[2] / 100).toString() +
|
||||||
|
'%\n' +
|
||||||
|
this.labelsNameMap[this.maxIndexArray[3]] +
|
||||||
|
': ' +
|
||||||
|
(this.maxArray[3] / 100).toString() +
|
||||||
|
'%').focusable(true).fontSize(20)
|
||||||
|
}
|
||||||
|
Button() {
|
||||||
|
Text('photo')
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
}
|
||||||
|
.type(ButtonType.Capsule)
|
||||||
|
.margin({
|
||||||
|
top: 20
|
||||||
|
})
|
||||||
|
.backgroundColor('#0D9FFB')
|
||||||
|
.width('40%')
|
||||||
|
.height('5%')
|
||||||
|
.onClick(() => {
|
||||||
|
let resMgr: resourceManager.ResourceManager = getContext().getApplicationContext().resourceManager;
|
||||||
|
|
||||||
|
//获取相册图片
|
||||||
|
//1.创建图片-视频类型文件选择选项实例
|
||||||
|
let PhotoSelectOptions = new picker.PhotoSelectOptions();
|
||||||
|
|
||||||
|
//2.选择媒体文件类型和选择媒体文件的最大数目
|
||||||
|
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
|
||||||
|
PhotoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目
|
||||||
|
|
||||||
|
//3.创建图库选择器实例,调用select()接口拉起图库界面进行文件选择。文件选择成功后,返回 photoSelectResult 结果集。
|
||||||
|
let photoPicker = new picker.PhotoViewPicker();
|
||||||
|
photoPicker.select(PhotoSelectOptions,
|
||||||
|
async (err: BusinessError, photoSelectResult: picker.PhotoSelectResult) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('MS_LITE_ERR: PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.info('MS_LITE_LOG: PhotoViewPicker.select successfully, photoSelectResult uri: ' +
|
||||||
|
JSON.stringify(photoSelectResult));
|
||||||
|
this.uris = photoSelectResult.photoUris;
|
||||||
|
console.info('MS_LITE_LOG: uri: ' + this.uris);
|
||||||
|
try {
|
||||||
|
// 预处理图片数据
|
||||||
|
// 1.使用fs.openSync接口,通过uri打开这个文件得到fd
|
||||||
|
let file = fileIo.openSync(this.uris[0], fileIo.OpenMode.READ_ONLY);
|
||||||
|
console.info('MS_LITE_LOG: file fd: ' + file.fd);
|
||||||
|
|
||||||
|
// 2.通过fd使用fs.readSync接口读取这个文件内的数据
|
||||||
|
let inputBuffer = new ArrayBuffer(4096000);
|
||||||
|
let readLen = fileIo.readSync(file.fd, inputBuffer);
|
||||||
|
console.info('MS_LITE_LOG: readSync data to file succeed and inputBuffer size is:' + readLen);
|
||||||
|
|
||||||
|
// 3.通过 PixelMap 预处理
|
||||||
|
let imageSource = image.createImageSource(file.fd);
|
||||||
|
let pixelMap = await imageSource.createPixelMap({ editable: true });
|
||||||
|
let info = await pixelMap.getImageInfo();
|
||||||
|
console.info('MS_LITE_LOG: info.width = ' + info.size.width);
|
||||||
|
console.info('MS_LITE_LOG: info.height = ' + info.size.height);
|
||||||
|
|
||||||
|
// 4. 获取图片buffer数据readBuffer,并进行处理
|
||||||
|
pixelMap.scale(256.0 / info.size.width, 256.0 / info.size.height).then(() => {
|
||||||
|
pixelMap.crop({
|
||||||
|
x: 16,
|
||||||
|
y: 16,
|
||||||
|
size: { height: this.modelInputHeight, width: this.modelInputWidth }
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
let info = await pixelMap.getImageInfo();
|
||||||
|
console.info('MS_LITE_LOG: crop info.width = ' + info.size.width);
|
||||||
|
console.info('MS_LITE_LOG: crop info.height = ' + info.size.height);
|
||||||
|
// 需要创建的像素buffer大小
|
||||||
|
let readBuffer = new ArrayBuffer(this.modelInputHeight * this.modelInputWidth * 4);
|
||||||
|
await pixelMap.readPixelsToBuffer(readBuffer);
|
||||||
|
console.info('MS_LITE_LOG: Succeeded in reading image pixel data, buffer: ' + readBuffer.byteLength);
|
||||||
|
|
||||||
|
// 处理readBuffer
|
||||||
|
const imageArr =
|
||||||
|
new Uint8Array(readBuffer.slice(0, this.modelInputHeight * this.modelInputWidth * 4));
|
||||||
|
console.info('MS_LITE_LOG: imageArr length: ' + imageArr.length);
|
||||||
|
let means = [0.485, 0.456, 0.406];
|
||||||
|
let stds = [0.229, 0.224, 0.225];
|
||||||
|
let float32View = new Float32Array(this.modelInputHeight * this.modelInputWidth * 3);
|
||||||
|
let index = 0;
|
||||||
|
for (let i = 0; i < imageArr.length; i++) {
|
||||||
|
if ((i + 1) % 4 == 0) {
|
||||||
|
float32View[index] = (imageArr[i - 3] / 255.0 - means[0]) / stds[0]; // B
|
||||||
|
float32View[index+1] = (imageArr[i - 2] / 255.0 - means[1]) / stds[1]; // G
|
||||||
|
float32View[index+2] = (imageArr[i - 1] / 255.0 - means[2]) / stds[2]; // R
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.info('MS_LITE_LOG: float32View length: ' + float32View.length);
|
||||||
|
let printStr = 'float32View data:';
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
printStr += ' ' + float32View[i];
|
||||||
|
}
|
||||||
|
console.info('MS_LITE_LOG: float32View data: ' + printStr);
|
||||||
|
|
||||||
|
// 调用c++的runDemo
|
||||||
|
console.info('MS_LITE_LOG: *** Start MSLite Demo ***');
|
||||||
|
let output: Array<number> = msliteNapi.runDemo(Array.from(float32View), resMgr);
|
||||||
|
console.warn('MS_LITE_WARN: output length = ', output.length, ';value = ', output.slice(0, 20));
|
||||||
|
|
||||||
|
// 取分类最大值top5
|
||||||
|
let newArray = output.filter(value => value !== this.max);
|
||||||
|
for (let n = 0; n < 5; n++) {
|
||||||
|
this.max = output[0];
|
||||||
|
this.maxIndex = 0;
|
||||||
|
// 取最大值
|
||||||
|
for (let m = 0; m < newArray.length; m++) {
|
||||||
|
if (newArray[m] > this.max) {
|
||||||
|
this.max = newArray[m];
|
||||||
|
this.maxIndex = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.maxArray.push(Math.round(this.max * 10000));
|
||||||
|
this.maxIndexArray.push(this.maxIndex);
|
||||||
|
// filter函数 数组过滤函数
|
||||||
|
newArray = newArray.filter(value => value !== this.max);
|
||||||
|
}
|
||||||
|
console.info('MS_LITE_LOG: max:' + this.maxArray);
|
||||||
|
console.info('MS_LITE_LOG: maxIndex:' + this.maxIndexArray);
|
||||||
|
console.info('MS_LITE_LOG: *** Finished MSLite Demo ***');
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// 5.关闭文件
|
||||||
|
fileIo.closeSync(file);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('MS_LITE_LOG: uri: open file fd failed.' + err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}.width('100%')
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"module": {
|
||||||
|
"name": "entry",
|
||||||
|
"type": "entry",
|
||||||
|
"description": "$string:module_desc",
|
||||||
|
"mainElement": "EntryAbility",
|
||||||
|
"deviceTypes": [
|
||||||
|
"default",
|
||||||
|
"tablet"
|
||||||
|
],
|
||||||
|
"deliveryWithInstall": true,
|
||||||
|
"installationFree": false,
|
||||||
|
"pages": "$profile:main_pages",
|
||||||
|
"abilities": [
|
||||||
|
{
|
||||||
|
"name": "EntryAbility",
|
||||||
|
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||||
|
"description": "$string:EntryAbility_desc",
|
||||||
|
"icon": "$media:icon",
|
||||||
|
"label": "$string:EntryAbility_label",
|
||||||
|
"startWindowIcon": "$media:startIcon",
|
||||||
|
"startWindowBackground": "$color:start_window_background",
|
||||||
|
"exported": true,
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"entities": [
|
||||||
|
"entity.system.home"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"action.system.home"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"color": [
|
||||||
|
{
|
||||||
|
"name": "start_window_background",
|
||||||
|
"value": "#FFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "module_desc",
|
||||||
|
"value": "module description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_desc",
|
||||||
|
"value": "description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_label",
|
||||||
|
"value": "MindSporeLiteC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "completed",
|
||||||
|
"value": "完成"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"layered-image": {
|
||||||
|
"background": "$media:background",
|
||||||
|
"foreground": "$media:foreground"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"src": [
|
||||||
|
"pages/Index"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "module_desc",
|
||||||
|
"value": "module description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_desc",
|
||||||
|
"value": "description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_label",
|
||||||
|
"value": "MindSporeLiteC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "completed",
|
||||||
|
"value": "completed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "module_desc",
|
||||||
|
"value": "模块描述"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_desc",
|
||||||
|
"value": "description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EntryAbility_label",
|
||||||
|
"value": "MindSporeLiteC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "completed",
|
||||||
|
"value": "完成"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
|
import { describe, it, expect } from '@ohos/hypium';
|
||||||
|
import Want from '@ohos.app.ability.Want';
|
||||||
|
import Base from '@ohos.base';
|
||||||
|
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||||
|
import { Driver, ON } from '@ohos.UiTest';
|
||||||
|
import { getString } from '../utils/ResourceUtil';
|
||||||
|
|
||||||
|
const BUNDLE = 'MindSporeLiteCDemo_';
|
||||||
|
const TAG = 'abilityTest';
|
||||||
|
const DOMAIN: number = 0xF811;
|
||||||
|
|
||||||
|
export default function abilityTest() {
|
||||||
|
let driver: Driver = Driver.create();
|
||||||
|
describe('MindSporeLiteCDemoTest', () => {
|
||||||
|
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||||
|
/*
|
||||||
|
* @tc.number: MindSporeLiteCDemoTest_000
|
||||||
|
* @tc.name: Start Ability
|
||||||
|
* @tc.desc: Start Ability
|
||||||
|
* @tc.size: MediumTest
|
||||||
|
* @tc.type: Function
|
||||||
|
* @tc.level Level 1
|
||||||
|
*/
|
||||||
|
it('EntryAbility', 0, async (done: Function) => {
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'EntryAbility_001 begin');
|
||||||
|
// Start Ability
|
||||||
|
let want: Want = {
|
||||||
|
bundleName: 'com.samples.mindsporelitecdemo',
|
||||||
|
abilityName: 'EntryAbility'
|
||||||
|
};
|
||||||
|
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||||
|
abilityDelegator.startAbility(want, (err: Base.BusinessError) => {
|
||||||
|
hilog.info(DOMAIN, TAG, 'StartAbility get err ' + JSON.stringify(err));
|
||||||
|
expect(err).assertNull();
|
||||||
|
})
|
||||||
|
await driver.delayMs(3000);
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'EntryAbility_001 end');
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* @tc.number : MindSporeLiteCDemoTest_001
|
||||||
|
* @tc.name : open photo
|
||||||
|
* @tc.desc : open photo
|
||||||
|
* @tc.size : MEDIUM
|
||||||
|
* @tc.type : Function
|
||||||
|
* @tc.level : Level 1
|
||||||
|
*/
|
||||||
|
it('IfExists', 0, async (done: Function) => {
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'IfExists_001 begin');
|
||||||
|
await driver.delayMs(1000);
|
||||||
|
await driver.assertComponentExist(ON.text('MindSporeLite C Demo'));
|
||||||
|
await driver.assertComponentExist(ON.text('photo'));
|
||||||
|
expect(true).assertTrue();
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'IfExists_001 end');
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @tc.number : MindSporeLiteCDemoTest_002
|
||||||
|
* @tc.name : open photo and predict
|
||||||
|
* @tc.desc : open photo and predict
|
||||||
|
* @tc.size : MEDIUM
|
||||||
|
* @tc.type : Function
|
||||||
|
* @tc.level : Level 1
|
||||||
|
*/
|
||||||
|
it('PhotoPredict', 0, async (done: Function) => {
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 begin');
|
||||||
|
await driver.delayMs(1000);
|
||||||
|
// click MindSporeLite C Demo
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 click photo button');
|
||||||
|
await driver.assertComponentExist(ON.text('photo'));
|
||||||
|
let msPhoto = await driver.findComponent(ON.text('photo'));
|
||||||
|
await msPhoto.click();
|
||||||
|
await driver.delayMs(1000);
|
||||||
|
// chose a photo
|
||||||
|
let gridItems = await driver.findComponents(ON.type('GridItem'));
|
||||||
|
await gridItems[1].click();
|
||||||
|
await driver.delayMs(5000);
|
||||||
|
// click complete
|
||||||
|
let tipCompleted: string = getString($r('app.string.completed'));
|
||||||
|
await driver.assertComponentExist(ON.text(tipCompleted));
|
||||||
|
let finish = await driver.findComponent(ON.text(tipCompleted));
|
||||||
|
await driver.delayMs(5000);
|
||||||
|
await finish.click();
|
||||||
|
await driver.delayMs(5000);
|
||||||
|
// predict
|
||||||
|
await driver.assertComponentExist(ON.text('MindSporeLite C Demo'));
|
||||||
|
await driver.assertComponentExist(ON.text('%', 1));
|
||||||
|
await driver.delayMs(5000);
|
||||||
|
expect(true).assertTrue();
|
||||||
|
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 end');
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import abilityTest from './Ability.test';
|
||||||
|
|
||||||
|
export default function testsuite() {
|
||||||
|
abilityTest();
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||||
|
import { abilityDelegatorRegistry } from '@kit.TestKit';
|
||||||
|
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
|
import { window } from '@kit.ArkUI';
|
||||||
|
import { Hypium } from '@ohos/hypium';
|
||||||
|
import testsuite from '../test/List.test';
|
||||||
|
|
||||||
|
export default class TestAbility extends UIAbility {
|
||||||
|
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
|
||||||
|
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||||
|
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator();
|
||||||
|
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||||
|
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments();
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
|
||||||
|
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy() {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
|
||||||
|
}
|
||||||
|
|
||||||
|
onWindowStageCreate(windowStage: window.WindowStage) {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
|
||||||
|
windowStage.loadContent('testability/pages/Index', (err) => {
|
||||||
|
if (err.code) {
|
||||||
|
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onWindowStageDestroy() {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
|
||||||
|
}
|
||||||
|
|
||||||
|
onForeground() {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackground() {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct Index {
|
||||||
|
@State message: string = 'Hello World';
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Row() {
|
||||||
|
Column() {
|
||||||
|
Text(this.message)
|
||||||
|
.fontSize(50)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
import { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit';
|
||||||
|
import { UIAbility, Want } from '@kit.AbilityKit';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
|
import { resourceManager } from '@kit.LocalizationKit';
|
||||||
|
import { util } from '@kit.ArkTS';
|
||||||
|
|
||||||
|
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||||
|
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||||
|
let jsonPath: string = 'mock/mock-config.json';
|
||||||
|
let tag: string = 'testTag';
|
||||||
|
|
||||||
|
async function onAbilityCreateCallback(data: UIAbility) {
|
||||||
|
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addAbilityMonitorCallback(err: BusinessError) {
|
||||||
|
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class OpenHarmonyTestRunner implements TestRunner {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
onPrepare() {
|
||||||
|
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare');
|
||||||
|
}
|
||||||
|
|
||||||
|
async onRun() {
|
||||||
|
let tag = 'testTag';
|
||||||
|
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run');
|
||||||
|
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments()
|
||||||
|
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
|
||||||
|
let moduleName = abilityDelegatorArguments.parameters['-m'];
|
||||||
|
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName);
|
||||||
|
let mResourceManager = context.resourceManager;
|
||||||
|
await checkMock(abilityDelegator, mResourceManager);
|
||||||
|
const bundleName = abilityDelegatorArguments.bundleName;
|
||||||
|
const testAbilityName: string = 'TestAbility';
|
||||||
|
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = {
|
||||||
|
abilityName: testAbilityName,
|
||||||
|
onAbilityCreate: onAbilityCreateCallback,
|
||||||
|
moduleName: moduleName
|
||||||
|
};
|
||||||
|
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
|
||||||
|
const want: Want = {
|
||||||
|
bundleName: bundleName,
|
||||||
|
abilityName: testAbilityName,
|
||||||
|
moduleName: moduleName
|
||||||
|
};
|
||||||
|
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => {
|
||||||
|
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
|
||||||
|
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? '');
|
||||||
|
})
|
||||||
|
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator,
|
||||||
|
resourceManager: resourceManager.ResourceManager) {
|
||||||
|
let rawFile: Uint8Array;
|
||||||
|
try {
|
||||||
|
rawFile = resourceManager.getRawFileContentSync(jsonPath);
|
||||||
|
hilog.info(0x0000, tag, 'MockList file exists');
|
||||||
|
let mockStr: string = util.TextDecoder.create('utf-8', { ignoreBOM: true }).decodeWithStream(rawFile);
|
||||||
|
let mockMap: Record<string, string> = getMockList(mockStr);
|
||||||
|
try {
|
||||||
|
abilityDelegator.setMockList(mockMap)
|
||||||
|
} catch (error) {
|
||||||
|
let code = (error as BusinessError).code;
|
||||||
|
let message = (error as BusinessError).message;
|
||||||
|
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let code = (error as BusinessError).code;
|
||||||
|
let message = (error as BusinessError).message;
|
||||||
|
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMockList(jsonStr: string) {
|
||||||
|
let jsonObj: Record<string, Object> = JSON.parse(jsonStr);
|
||||||
|
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
|
||||||
|
let mockList: Record<string, string> = {};
|
||||||
|
map.forEach((value: object, key: string) => {
|
||||||
|
let realValue: string = value['source'].toString();
|
||||||
|
mockList[key] = realValue;
|
||||||
|
});
|
||||||
|
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? '');
|
||||||
|
return mockList;
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||||
|
|
||||||
|
const delegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||||
|
|
||||||
|
export function getString(resourceData: Resource): string {
|
||||||
|
let manage = delegator.getAppContext().resourceManager;
|
||||||
|
return manage.getStringSync(resourceData);
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"module": {
|
||||||
|
"name": "entry_test",
|
||||||
|
"type": "feature",
|
||||||
|
"description": "$string:module_test_desc",
|
||||||
|
"mainElement": "TestAbility",
|
||||||
|
"deviceTypes": [
|
||||||
|
"default",
|
||||||
|
"tablet"
|
||||||
|
],
|
||||||
|
"deliveryWithInstall": true,
|
||||||
|
"installationFree": false,
|
||||||
|
"pages": "$profile:test_pages",
|
||||||
|
"abilities": [
|
||||||
|
{
|
||||||
|
"name": "TestAbility",
|
||||||
|
"srcEntry": "./ets/testability/TestAbility.ets",
|
||||||
|
"description": "$string:TestAbility_desc",
|
||||||
|
"icon": "$media:icon",
|
||||||
|
"label": "$string:TestAbility_label",
|
||||||
|
"exported": true,
|
||||||
|
"startWindowIcon": "$media:icon",
|
||||||
|
"startWindowBackground": "$color:start_window_background",
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"action.system.home"
|
||||||
|
],
|
||||||
|
"entities": [
|
||||||
|
"entity.system.home"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"color": [
|
||||||
|
{
|
||||||
|
"name": "start_window_background",
|
||||||
|
"value": "#FFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "module_test_desc",
|
||||||
|
"value": "test ability description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TestAbility_desc",
|
||||||
|
"value": "the test ability"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TestAbility_label",
|
||||||
|
"value": "test label"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "completed",
|
||||||
|
"value": "完成"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 2.7 KiB |
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"src": [
|
||||||
|
"testability/pages/Index"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import localUnitTest from './LocalUnit.test';
|
||||||
|
|
||||||
|
export default function testsuite() {
|
||||||
|
localUnitTest();
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||||
|
|
||||||
|
export default function localUnitTest() {
|
||||||
|
describe('localUnitTest',() => {
|
||||||
|
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||||
|
beforeAll(() => {
|
||||||
|
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||||
|
// This API supports only one parameter: preset action function.
|
||||||
|
});
|
||||||
|
beforeEach(() => {
|
||||||
|
// Presets an action, which is performed before each unit test case starts.
|
||||||
|
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||||
|
// This API supports only one parameter: preset action function.
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
// Presets a clear action, which is performed after each unit test case ends.
|
||||||
|
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||||
|
// This API supports only one parameter: clear action function.
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||||
|
// This API supports only one parameter: clear action function.
|
||||||
|
});
|
||||||
|
it('assertContain', 0, () => {
|
||||||
|
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||||
|
let a = 'abc';
|
||||||
|
let b = 'b';
|
||||||
|
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||||
|
expect(a).assertContain(b);
|
||||||
|
expect(a).assertEqual(a);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"hvigorVersion": "4.1.2",
|
||||||
|
"dependencies": {
|
||||||
|
"@ohos/hvigor-ohos-plugin": "4.1.2"
|
||||||
|
},
|
||||||
|
"execution": {
|
||||||
|
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
|
||||||
|
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||||
|
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||||
|
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||||
|
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||||
|
},
|
||||||
|
"debugging": {
|
||||||
|
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||||
|
},
|
||||||
|
"nodeOptions": {
|
||||||
|
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||||
|
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "mindsporelitecdemo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Please describe the basic information.",
|
||||||
|
"main": "",
|
||||||
|
"author": "",
|
||||||
|
"license": "",
|
||||||
|
"dependencies": {
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ohos/hypium": "1.0.16",
|
||||||
|
"@ohos/hamock": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
# MindSporeLiteCDemo 测试用例归档
|
||||||
|
|
||||||
|
## 用例表
|
||||||
|
|
||||||
|
|测试功能|预置条件|输入|预期输出|是否自动|测试结果|
|
||||||
|
|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|
|
||||||
|
|拉起应用| 设备正常运行| |成功拉起应用|是|Pass|
|
||||||
|
|查看预览界面Text和Button| 进入预览界面 | |预览界面存在Text和Button|是|Pass|
|
||||||
|
|选取图片推理功能测试| 进入预览界面 | 点击photo按钮 |选取图片后进行推理|是|Pass|
|
After Width: | Height: | Size: 383 KiB |