如果您是一名開發者,正在尋找一種高效、靈活且易於使用的端側AI開發框架,那麼HarmonyOS SDKHiAI Foundation服務(HiAI Foundation Kit)就是您的理想選擇。
作為一款AI開發框架,HiAI Foundation不僅提供強大的NPU計算能力和豐富的開發工具,還提供完善的技術支援和社群資源,幫助您快速構建高質量的AI應用程式。以影像分類這種常見的AI應用為例,使用HiAI Foundation可以幫助開發者們快速實現高效的影像分類應用。HiAI Foundation面向自定義AI演算法的開發者們,可以靈活地支援自有的演算法,給應用帶來更好的效能功耗收益。
功能演示
如果開發者對實現方式感興趣,可以下載Demo體驗,基於具體的應用場景最佳化。Demo支援載入離線模型,對圖片中的物體進行分類。
影像分類開發步驟
1.建立專案
本章以Caffe SqueezeNet模型整合為例,說明App整合操作過程。
2.配置專案NAPI
編譯HAP時,NAPI層的so需要編譯依賴NDK中的libneural_network_core.so和libhiai_foundation.so。
3.標頭檔案引用
按需引用標頭檔案。
#include "neural_network_runtime/neural_network_core.h"
#include "hiai_foundation/hiai_options.h"
4.編寫CMakeLists.txt
CMakeLists.txt中的關鍵程式碼如下:
include_directories(${HMOS_SDK_NATIVE}/sysroot/usr/lib)
FIND_LIBRARY(hiai_foundation-lib hiai_foundation)
add_library(entry SHARED Classification.cpp HIAIModelManager.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so
libhilog_ndk.z.so
librawfile.z.so
${hiai_foundation-lib}
libneural_network_core.so
)
5.整合模型
模型的載入、編譯和推理主要是在native層實現,應用層主要作為資料傳遞和展示作用。
模型推理之前需要對輸入資料進行預處理以匹配模型的輸入,同樣對於模型的輸出也需要做處理獲取自己期望的結果。另外SDK中提供了設定模型編譯和執行時的配置介面,開發者可根據實際需求選擇使用介面。
本節闡述同步模式下單模型的使用,從流程上分別闡述每個步驟在應用層和Native層的實現和呼叫,介面請參見API參考。
6.預置模型
為了讓App執行時能夠讀取到模型檔案和處理推理結果,需要先把離線模型和模型對應的結果標籤檔案預置到工程的"entry/src/main/resources/rawfile"目錄中。
本示例所使用的離線模型轉換和生成可參考Caffe模型轉換,當前支援Caffe 1.0版本。
命令列中的引數說明請參見OMG引數,轉換命令:
./omg --model xxx.prototxt --weight yyy.caffemodel --framework 0 --
output ./modelname
轉換示例:
./omg --model deploy.prototxt --weight squeezenet_v1.1.caffemodel --framework
0 --output ./squeezenet
當看到OMG generate offline model success時,則說明轉換成功,會在當前目錄下生成squeezenet.om。
7.載入離線模型
在App應用建立時載入模型和讀取結果標籤檔案。
1)呼叫NAPI層的"LoadModel"函式,讀取模型的buffer。
2)把模型buffer傳遞給HIAIModelManager類的"HIAIModelManager::LoadModelFromBuffer"介面,該介面呼叫
OH_NNCompilation_ConstructWithOfflineModelBuffer建立模型的編譯例項。
3)獲取並設定模型的deviceID。
size_t deviceID = 0;
const size_t *allDevicesID = nullptr;
uint32_t deviceCount = 0;
OH_NN_ReturnCode ret = OH_NNDevice_GetAllDevicesID(&allDevicesID, &deviceCount);
if (ret != OH_NN_SUCCESS || allDevicesID == nullptr) {
OH_LOG_ERROR(LOG_APP, "OH_NNDevice_GetAllDevicesID failed");
return OH_NN_FAILED;
}
for (uint32_t i = 0; i < deviceCount; i++) {
const char *name = nullptr;
ret = OH_NNDevice_GetName(allDevicesID[i], &name);
if (ret != OH_NN_SUCCESS || name == nullptr) {
OH_LOG_ERROR(LOG_APP, "OH_NNDevice_GetName failed");
return OH_NN_FAILED;
}
if (std::string(name) == "HIAI_F") {
deviceID = allDevicesID[i];
break;
}
}
// modelData和modelSize為模型的記憶體地址和大小
OH_NNCompilation *compilation = OH_NNCompilation_ConstructWithOfflineModelBuffer(modelData, modelSize);
ret = OH_NNCompilation_SetDevice(compilation, deviceID);
if (ret != OH_NN_SUCCESS) {
OH_LOG_ERROR(LOG_APP, "OH_NNCompilation_SetDevice failed");
return OH_NN_FAILED;
}
4)呼叫OH_NNCompilation_Build,執行模型編譯。
5)呼叫OH_NNExecutor_Construct,建立模型執行器。
6)呼叫OH_NNCompilation_Destroy,釋放模型編譯例項。
上述流程可參見Demo中"entry/src/main/cpp/Classification.cpp"檔案中的"LoadModel"函式和"entry/src/main/cpp/HiAiModelManager.cpp"中的"HIAIModelManager::LoadModelFromBuffer"函式。
8.準備輸入輸出
1)準備輸入輸出
2)處理模型的輸入,例如示例中模型的輸入為13227*227格式Float型別的資料,需要把輸入的圖片轉成該格式後傳遞到NAPI層。
3)建立模型的輸入和輸出Tensor,並把應用層傳遞的資料填充到輸入的Tensor中。
// 建立輸入資料
size_t inputCount = 0;
std::vector<NN_Tensor*> inputTensors;
OH_NN_ReturnCode ret = OH_NNExecutor_GetInputCount(executor, &inputCount);
if (ret != OH_NN_SUCCESS || inputCount != inputData.size()) { // inputData為開發者構造的輸入資料
OH_LOG_ERROR(LOG_APP, "OH_NNExecutor_GetInputCount failed, size mismatch");
return OH_NN_FAILED;
}
for (size_t i = 0; i < inputCount; ++i) {
NN_TensorDesc *tensorDesc = OH_NNExecutor_CreateInputTensorDesc(executor, i);
NN_Tensor *tensor = OH_NNTensor_Create(deviceID, tensorDesc); // deviceID的獲取方式可參考"載入離線模型"的步驟3
if (tensor != nullptr) {
inputTensors.push_back(tensor);
}
OH_NNTensorDesc_Destroy(&tensorDesc);
}
if (inputTensors.size() != inputCount) {
OH_LOG_ERROR(LOG_APP, "input size mismatch");
DestroyTensors(inputTensors); // DestroyTensors為釋放tensor記憶體操作函式
return OH_NN_FAILED;
}
// 初始化輸入資料
for (size_t i = 0; i < inputTensors.size(); ++i) {
void *data = OH_NNTensor_GetDataBuffer(inputTensors[i]);
size_t dataSize = 0;
OH_NNTensor_GetSize(inputTensors[i], &dataSize);
if (data == nullptr || dataSize != inputData[i].size()) { // inputData為模型的輸入資料
OH_LOG_ERROR(LOG_APP, "invalid data or dataSize");
return OH_NN_FAILED;
}
memcpy(data, inputData[i].data(), inputData[i].size()); // inputData為模型的輸入資料
}
// 建立輸出資料,與輸入資料的建立方式類似
size_t outputCount = 0;
std::vector<NN_Tensor*> outputTensors;
ret = OH_NNExecutor_GetOutputCount(executor, &outputCount);
if (ret != OH_NN_SUCCESS) {
OH_LOG_ERROR(LOG_APP, "OH_NNExecutor_GetOutputCount failed");
DestroyTensors(inputTensors); // DestroyTensors為釋放tensor記憶體操作函式
return OH_NN_FAILED;
}
for (size_t i = 0; i < outputCount; i++) {
NN_TensorDesc *tensorDesc = OH_NNExecutor_CreateOutputTensorDesc(executor, i);
NN_Tensor *tensor = OH_NNTensor_Create(deviceID, tensorDesc); // deviceID的獲取方式可參考"載入離線模型"的步驟3
if (tensor != nullptr) {
outputTensors.push_back(tensor);
}
OH_NNTensorDesc_Destroy(&tensorDesc);
}
if (outputTensors.size() != outputCount) {
DestroyTensors(inputTensors); // DestroyTensors為釋放tensor記憶體操作函式
DestroyTensors(outputTensors); // DestroyTensors為釋放tensor記憶體操作函式
OH_LOG_ERROR(LOG_APP, "output size mismatch");
return OH_NN_FAILED;
}
上述流程可參見Demo中"entry/src/main/cpp/Classification.cpp"檔案中的"InitIOTensors"函式和"entry/src/main/cpp/HiAiModelManager.cpp"中的"HIAIModelManager::InitIOTensors"函式。
9.同步推理離線模型
呼叫OH_NNExecutor_RunSync,完成模型的同步推理。
可參見Demo中"entry/src/main/cpp/Classification.cpp"檔案中的"RunModel"函式和"entry/src/main/cpp/HiAiModelManager.cpp"中的"HIAIModelManager::RunModel"函式。
說明:如果不更換模型,則首次編譯載入完成後可多次推理,即一次編譯載入,多次推理。
10.模型輸出後處理
1)呼叫OH_NNTensor_GetDataBuffer,獲取輸出的Tensor,在輸出Tensor中會得到模型的輸出資料。
2)對輸出資料進行相應的處理可得到期望的結果。
3)例如本示例demo中模型的輸出是1000個label的機率,期望得到這1000個結果中機率最大的三個標籤。
4)銷燬例項。
呼叫OH_NNExecutor_Destroy,銷燬建立的模型執行器例項。
呼叫OH_NNTensor_Destroy,銷燬建立的輸入輸出Tensor。
上述流程可參見Demo中"entry/src/main/cpp/Classification.cpp"檔案中的"GetResult"、"UnloadModel"函式和"entry/src/main/cpp/HiAiModelManager.cpp"中的"HIAIModelManager::GetResult"、"HIAIModelManager::UnloadModel"函式。
瞭解更多詳情>>
訪問HiAI Foundation服務聯盟官網
獲取HiAI Foundation服務開發指導文件