commit 39e08c139e12f4700bda2cb69d80a3d07ad228c0 Author: Heiko Joerg Schick Date: Sat Oct 17 15:44:27 2020 +0200 Initial commit diff --git a/.project b/.project new file mode 100644 index 0000000..20a56fe --- /dev/null +++ b/.project @@ -0,0 +1,8 @@ +{ + "type": "Ascend ACL App", + "project_type": "Custom", + "project_desc": "", + "target": "", + "target_id": "", + "adk_version": "1.73.T5.0.B050" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f8f16fe --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) + +# project information +project(sample-objectdetection) + +add_subdirectory("./src") diff --git a/caffe_model/aipp_bgr.cfg b/caffe_model/aipp_bgr.cfg new file mode 100644 index 0000000..d6ec314 --- /dev/null +++ b/caffe_model/aipp_bgr.cfg @@ -0,0 +1,14 @@ +aipp_op{ +aipp_mode:static +input_format : RGB888_U8 +csc_switch : false +rbuv_swap_switch:true + +var_reci_chn_0 :0.003921568627451 +var_reci_chn_1 :0.003921568627451 +var_reci_chn_2 :0.003921568627451 + + +} + + diff --git a/data/bird.jpg b/data/bird.jpg new file mode 100644 index 0000000..8d0cbc9 Binary files /dev/null and b/data/bird.jpg differ diff --git a/data/boat.jpg b/data/boat.jpg new file mode 100644 index 0000000..67648d1 Binary files /dev/null and b/data/boat.jpg differ diff --git a/inc/model_process.h b/inc/model_process.h new file mode 100644 index 0000000..9fefe1d --- /dev/null +++ b/inc/model_process.h @@ -0,0 +1,109 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File model_process.h +* Description: handle model process +*/ +#pragma once +#include +#include "utils.h" +#include "acl/acl.h" + +/** +* ModelProcess +*/ +class ModelProcess { +public: + /** + * @brief Constructor + */ + ModelProcess(); + + /** + * @brief Destructor + */ + ~ModelProcess(); + + /** + * @brief load model from file with mem + * @param [in] modelPath: model path + * @return result + */ + Result LoadModelFromFileWithMem(const char *modelPath); + + /** + * @brief unload model + */ + void Unload(); + + /** + * @brief create model desc + * @return result + */ + Result CreateDesc(); + + /** + * @brief destroy desc + */ + void DestroyDesc(); + + /** + * @brief create model input + * @param [in] inputDataBuffer: input buffer + * @param [in] bufferSize: input buffer size + * @return result + */ + Result CreateInput(void *inputDataBuffer, size_t bufferSize); + + /** + * @brief destroy input resource + */ + void DestroyInput(); + + /** + * @brief create output buffer + * @return result + */ + Result CreateOutput(); + + /** + * @brief destroy output resource + */ + void DestroyOutput(); + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief get model output data + * @return output dataset + */ + aclmdlDataset *GetModelOutputData(); + +private: + bool loadFlag_; // model load flag + uint32_t modelId_; + void *modelMemPtr_; + size_t modelMemSize_; + void *modelWeightPtr_; + size_t modelWeightSize_; + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; + diff --git a/inc/sample_process.h b/inc/sample_process.h new file mode 100644 index 0000000..bb81f53 --- /dev/null +++ b/inc/sample_process.h @@ -0,0 +1,71 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File sample_process.h +* Description: handle acl resource +*/ +#pragma once +#include "utils.h" +#include "acl/acl.h" +#include + +template +std::shared_ptr MakeSharedNoThrow() { + try { + return std::make_shared(); + } catch (...) { + return nullptr; + } +} + +#define MAKE_SHARED_NO_THROW(memory, memory_type) \ + memory = MakeSharedNoThrow(); + +/** +* SampleProcess +*/ +class SampleProcess { +public: + /** + * @brief Constructor + */ + SampleProcess(); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(); + + /** + * @brief encode sample process + * @param [in] dvpptype: dvpp type + * @return result + */ + Result MainProcess(std::string input_path); + +private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + diff --git a/inc/utils.h b/inc/utils.h new file mode 100644 index 0000000..c8fae53 --- /dev/null +++ b/inc/utils.h @@ -0,0 +1,82 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File utils.h +* Description: handle file operations +*/ +#pragma once +#include +#include +#include "acl/acl.h" +#include +#include "opencv2/imgcodecs/legacy/constants_c.h" +#include "opencv2/imgproc/types_c.h" + +#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) +#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) +#define MODEL_INPUT_WIDTH 416 +#define MODEL_INPUT_HEIGHT 416 + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +struct ConsoleParams { + uint32_t img_width = 0; + uint32_t img_height = 0; + int32_t size = 0; + std::string input_path = ""; + std::shared_ptr data; +}; + +const std::string kImagePathSeparator = ","; +const int kStatSuccess = 0; +const std::string kFileSperator = "/"; +const std::string kPathSeparator = "/"; +// output image prefix +const std::string kOutputFilePrefix = "out_"; + +/** + * Utils + */ +class Utils { +public: + + /** + * @brief create device buffer of pic + * @param [in] picDesc: pic desc + * @param [in] PicBufferSize: aligned pic size + * @return device buffer of pic + */ + + static Result Postprocess(const std::string &path, aclmdlDataset *modelOutput); + + static bool IsDirectory(const std::string &path); + + static bool IsPathExist(const std::string &path); + + static void SplitPath(const std::string &path, std::vector &path_vec); + + static void GetAllFiles(const std::string &path, std::vector &file_vec); + + static void GetPathFiles(const std::string &path, std::vector &file_vec); + + static bool Preprocess(std::shared_ptr &image_path, + const std::string &path); + +}; + diff --git a/model/.keep b/model/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..a8bdd4b --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) + +# project information +project(objectdetection_pic) + +# Compile options +add_compile_options(-std=c++11) + +add_definitions(-DENABLE_DVPP_INTERFACE) + +# Specify target generation path +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../../out") +set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall") +set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall") + +set(INC_PATH $ENV{DDK_PATH}) + +if (NOT DEFINED ENV{DDK_PATH}) + set(INC_PATH "/usr/local/Ascend") + message(STATUS "set default INC_PATH: ${INC_PATH}") +else () + message(STATUS "env INC_PATH: ${INC_PATH}") +endif() + +set(LIB_PATH $ENV{NPU_HOST_LIB}) +set(OPENCV_PATH "/usr/local") + +if (NOT DEFINED ENV{NPU_HOST_LIB}) + set(LIB_PATH "/usr/local/Ascend/acllib/lib64/stub/") + message(STATUS "set default LIB_PATH: ${LIB_PATH}") +else () + message(STATUS "env LIB_PATH: ${LIB_PATH}") +endif() + +# Header path +include_directories( + $ENV{HOME}/ascend_ddk/include/ + $ENV{HOME}/ascend_ddk/include/ascenddk/ + ${INC_PATH}/acllib/include/ + ../inc/ + ${OPENCV_PATH}/include/opencv4 +) + + +# add host lib path +link_directories( + ${LIB_PATH} + $ENV{HOME}/ascend_ddk/host/lib/ + ${OPENCV_PATH}/lib + ${INC_PATH}/atc/lib64 +) + +add_executable(main + utils.cpp + model_process.cpp + sample_process.cpp + main.cpp) + +target_link_libraries(main + ascendcl acl_dvpp stdc++ opencv_highgui opencv_core opencv_imgproc opencv_imgcodecs opencv_calib3d opencv_features2d) + +install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/src/acl.json b/src/acl.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/acl.json @@ -0,0 +1 @@ +{} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..47de996 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,52 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File main.cpp +* Description: dvpp sample main func +*/ + +#include +#include +#include +#include "sample_process.h" +#include "utils.h" +using namespace std; + +int main(int argc, char *argv[]) +{ + + if(argc<2){ + ERROR_LOG("please input: ./main path"); + return FAILED; + } + + SampleProcess processSample; + Result ret = processSample.InitResource(); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + //input path + string input_path = string(argv[1]); + + ret = processSample.MainProcess(input_path); + if (ret != SUCCESS) { + ERROR_LOG("sample model process failed"); + return FAILED; + } + INFO_LOG("execute sample success"); + return SUCCESS; +} diff --git a/src/model_process.cpp b/src/model_process.cpp new file mode 100644 index 0000000..af3bf3f --- /dev/null +++ b/src/model_process.cpp @@ -0,0 +1,269 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File model_process.cpp +* Description: handle model process +*/ +#include "model_process.h" +#include +#include "utils.h" +using namespace std; + +ModelProcess::ModelProcess():loadFlag_(false), modelId_(0), modelMemPtr_(nullptr), modelMemSize_(0), +modelWeightPtr_(nullptr),modelWeightSize_(0), modelDesc_(nullptr), input_(nullptr), output_(nullptr) +{ +} + +ModelProcess::~ModelProcess() +{ + Unload(); + DestroyDesc(); + DestroyInput(); + DestroyOutput(); +} + +Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) +{ + if (loadFlag_) { + ERROR_LOG("has already loaded a model"); + return FAILED; + } + + aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("query model failed, model file is %s", modelPath); + return FAILED; + } + + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_); + return FAILED; + } + + ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_, + modelMemSize_, modelWeightPtr_, modelWeightSize_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("load model from file failed, model file is %s", modelPath); + return FAILED; + } + + loadFlag_ = true; + INFO_LOG("load model %s success", modelPath); + return SUCCESS; +} + +Result ModelProcess::CreateDesc() +{ + modelDesc_ = aclmdlCreateDesc(); + if (modelDesc_ == nullptr) { + ERROR_LOG("create model description failed"); + return FAILED; + } + + aclError ret = aclmdlGetDesc(modelDesc_, modelId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("get model description failed"); + return FAILED; + } + + INFO_LOG("create model description success"); + return SUCCESS; +} + +void ModelProcess::DestroyDesc() +{ + if (modelDesc_ != nullptr) { + (void)aclmdlDestroyDesc(modelDesc_); + modelDesc_ = nullptr; + } +} + +const float ModelInput2[4]={416,416,416,416}; + +Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) +{ + input_ = aclmdlCreateDataset(); + if (input_ == nullptr) { + ERROR_LOG("can't create dataset, create input failed"); + return FAILED; + } + + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + if (inputData == nullptr) { + ERROR_LOG("can't add data buffer, create input failed"); + aclDestroyDataBuffer(inputData); + inputData = nullptr; + return FAILED; + } + + void *dataDev; + uint32_t dataSize=sizeof(ModelInput2); + aclrtMalloc(&dataDev, dataSize,ACL_MEM_MALLOC_HUGE_FIRST); + aclrtMemcpy(dataDev, dataSize, ModelInput2, sizeof(ModelInput2), ACL_MEMCPY_DEVICE_TO_DEVICE); + aclDataBuffer* inputData2 = aclCreateDataBuffer(dataDev, dataSize); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + ret = aclmdlAddDatasetBuffer(input_, inputData2); + if (inputData == nullptr) { + ERROR_LOG("can't add data buffer, create input failed"); + aclDestroyDataBuffer(inputData2); + inputData = nullptr; + return FAILED; + } + + return SUCCESS; +} + +void ModelProcess::DestroyInput() +{ + if (input_ == nullptr) { + return; + } + + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i); + aclDestroyDataBuffer(dataBuffer); + } + aclmdlDestroyDataset(input_); + input_ = nullptr; +} + +Result ModelProcess::CreateOutput() +{ + if (modelDesc_ == nullptr) { + ERROR_LOG("no model description, create ouput failed"); + return FAILED; + } + + output_ = aclmdlCreateDataset(); + if (output_ == nullptr) { + ERROR_LOG("can't create dataset, create output failed"); + return FAILED; + } + + size_t outputSize = aclmdlGetNumOutputs(modelDesc_); + for (size_t i = 0; i < outputSize; ++i) { + size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i); + + void *outputBuffer = nullptr; + aclError ret = aclrtMalloc(&outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size); + return FAILED; + } + + aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't create data buffer, create output failed"); + aclrtFree(outputBuffer); + return FAILED; + } + + ret = aclmdlAddDatasetBuffer(output_, outputData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't add data buffer, create output failed"); + aclrtFree(outputBuffer); + aclDestroyDataBuffer(outputData); + return FAILED; + } + } + + INFO_LOG("create model output success"); + return SUCCESS; +} + +void ModelProcess::DestroyOutput() +{ + if (output_ == nullptr) { + return; + } + + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + (void)aclrtFree(data); + (void)aclDestroyDataBuffer(dataBuffer); + } + + (void)aclmdlDestroyDataset(output_); + output_ = nullptr; +} + +Result ModelProcess::Execute() +{ + aclError ret = aclmdlExecute(modelId_, input_, output_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("execute model failed, modelId is %u", modelId_); + return FAILED; + } + + INFO_LOG("model execute success"); + return SUCCESS; +} + +void ModelProcess::Unload() +{ + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError ret = aclmdlUnload(modelId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("unload model failed, modelId is %u", modelId_); + } + + if (modelDesc_ != nullptr) { + (void)aclmdlDestroyDesc(modelDesc_); + modelDesc_ = nullptr; + } + + if (modelMemPtr_ != nullptr) { + aclrtFree(modelMemPtr_); + modelMemPtr_ = nullptr; + modelMemSize_ = 0; + } + + if (modelWeightPtr_ != nullptr) { + aclrtFree(modelWeightPtr_); + modelWeightPtr_ = nullptr; + modelWeightSize_ = 0; + } + + loadFlag_ = false; + INFO_LOG("unload model success, modelId is %u", modelId_); +} + +aclmdlDataset *ModelProcess::GetModelOutputData() +{ + return output_; +} + + diff --git a/src/sample_process.cpp b/src/sample_process.cpp new file mode 100644 index 0000000..c5ab436 --- /dev/null +++ b/src/sample_process.cpp @@ -0,0 +1,178 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File sample_process.cpp +* Description: handle acl resource +*/ +#include "sample_process.h" +#include +#include "model_process.h" +#include "acl/acl.h" +#include "utils.h" + +using namespace std; + +SampleProcess::SampleProcess():deviceId_(0), context_(nullptr), stream_(nullptr) +{ +} + +SampleProcess::~SampleProcess() +{ + DestroyResource(); +} + +Result SampleProcess::InitResource() +{ + // ACL init + const char *aclConfigPath = "../src/acl.json"; + aclError ret = aclInit(aclConfigPath); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl init failed"); + return FAILED; + } + INFO_LOG("acl init success"); + + // open device + ret = aclrtSetDevice(deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl open device %d failed", deviceId_); + return FAILED; + } + INFO_LOG("open device %d success", deviceId_); + + // create context (set current) + ret = aclrtCreateContext(&context_, deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl create context failed"); + return FAILED; + } + INFO_LOG("create context success"); + + // create stream + ret = aclrtCreateStream(&stream_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl create stream failed"); + return FAILED; + } + INFO_LOG("create stream success"); + + return SUCCESS; +} + +Result SampleProcess::MainProcess(string input_path) +{ + const char* omModelPath = "../model/yolov3_BGR.om"; + + vector file_vec; + Utils::GetAllFiles(input_path, file_vec); + if (file_vec.empty()) { + ERROR_LOG("Failed to deal all empty path=%s.", input_path.c_str()); + return FAILED; + } + + // model init + ModelProcess processModel; + aclError ret = processModel.LoadModelFromFileWithMem(omModelPath); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModelFromFileWithMem failed"); + return FAILED; + } + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateDesc failed"); + return FAILED; + } + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateOutput failed"); + return FAILED; + } + + for (string path : file_vec) { + shared_ptr image_path = nullptr; + MAKE_SHARED_NO_THROW(image_path, ConsoleParams); + if (image_path == nullptr) { + ERROR_LOG("Failed to deal file=%s. Reason: new EngineTrans failed.", + path.c_str()); + continue; + } + // arrange image information, if failed, skip this image + if (!Utils::Preprocess(image_path, path)) { + continue; + } + + ret = processModel.CreateInput((void*) image_path->data.get(), image_path->size); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateInput failed"); + return FAILED; + } + + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("execute inference failed"); + return FAILED; + } + + // release model input buffer + processModel.DestroyInput(); + + aclmdlDataset *modelOutput = processModel.GetModelOutputData(); + if (modelOutput == nullptr) { + ERROR_LOG("get model output data failed"); + return FAILED; + } + + ret = Utils::Postprocess(path, modelOutput); + if (ret != SUCCESS) { + ERROR_LOG("pull model output data failed"); + return FAILED; + } + } + return SUCCESS; +} + +void SampleProcess::DestroyResource() +{ + aclError ret; + if (stream_ != nullptr) { + ret = aclrtDestroyStream(stream_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("destroy stream failed"); + } + stream_ = nullptr; + } + INFO_LOG("end to destroy stream"); + + if (context_ != nullptr) { + ret = aclrtDestroyContext(context_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("destroy context failed"); + } + context_ = nullptr; + } + INFO_LOG("end to destroy context"); + + ret = aclrtResetDevice(deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("reset device failed"); + } + INFO_LOG("end to reset device is %d", deviceId_); + + ret = aclFinalize(); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("finalize acl failed"); + } + INFO_LOG("end to finalize acl"); +} diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..a95adc4 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,237 @@ +/** +* Copyright 2020 Huawei Technologies 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. + +* File utils.cpp +* Description: handle file operations +*/ +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acl/acl.h" +#include "acl/ops/acl_dvpp.h" + +using namespace std; + +const static std::vector yolov3Label = {"person", "bicycle", "car", "motorbike", +"aeroplane","bus", "train", "truck", "boat", +"traffic light", "fire hydrant", "stop sign", "parking meter", +"bench", "bird", "cat", "dog", "horse", +"sheep", "cow", "elephant", "bear", "zebra", +"giraffe", "backpack", "umbrella", "handbag","tie", +"suitcase", "frisbee", "skis", "snowboard", "sports ball", +"kite", "baseball bat", "baseball glove", "skateboard", "surfboard", +"tennis racket", "bottle", "wine glass", "cup", +"fork", "knife", "spoon", "bowl", "banana", +"apple", "sandwich", "orange", "broccoli", "carrot", +"hot dog", "pizza", "donut", "cake", "chair", +"sofa", "potted plant", "bed", "dining table", "toilet", +"TV monitor", "laptop", "mouse", "remote", "keyboard", +"cell phone", "microwave", "oven", "toaster", "sink", +"refrigerator", "book", "clock", "vase","scissors", +"teddy bear", "hair drier", "toothbrush"}; + +enum BBoxIndex {TOPLEFTX=0,TOPLEFTY,BOTTOMRIGHTX,BOTTOMRIGHTY,SCORE,LABEL}; + +Result Utils::Postprocess(const string &path, aclmdlDataset *modelOutput) +{ + size_t outDatasetNum = aclmdlGetDatasetNumBuffers(modelOutput); + if (outDatasetNum != 2) { + return FAILED; + } + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(modelOutput, 1); + if (dataBuffer == nullptr) { + ERROR_LOG("get model output aclmdlGetDatasetBuffer failed"); + return FAILED; + } + void* data = aclGetDataBufferAddr(dataBuffer); + if (data == nullptr) { + ERROR_LOG("aclGetDataBufferAddr from dataBuffer failed."); + } + uint32_t count; + aclrtMemcpy(&count, sizeof(count), data, sizeof(count), ACL_MEMCPY_DEVICE_TO_DEVICE); + INFO_LOG("box count=%d",count); + dataBuffer = aclmdlGetDatasetBuffer(modelOutput, 0); + if (dataBuffer == nullptr) { + ERROR_LOG("get model output aclmdlGetDatasetBuffer failed"); + return FAILED; + } + data = aclGetDataBufferAddr(dataBuffer); + if (data == nullptr) { + ERROR_LOG("aclGetDataBufferAddr from dataBuffer failed."); + } + float outInfo[count*6]; + aclrtMemcpy(&outInfo, sizeof(outInfo), data, sizeof(outInfo), ACL_MEMCPY_DEVICE_TO_DEVICE); + cv::Rect rect; + int font_face = 0; + double font_scale = 1; + int thickness = 2; + int baseline; + cv::Mat resultImage = cv::imread(path, CV_LOAD_IMAGE_COLOR); + for(uint32_t b=0;b &path_vec) { + char *char_path = const_cast(path.c_str()); + const char *char_split = kImagePathSeparator.c_str(); + char *tmp_path = strtok(char_path, char_split); + while (tmp_path) { + path_vec.emplace_back(tmp_path); + tmp_path = strtok(nullptr, char_split); + } +} + +void Utils::GetAllFiles(const string &path, vector &file_vec) { + // split file path + vector path_vector; + SplitPath(path, path_vector); + + for (string every_path : path_vector) { + // check path exist or not + if (!IsPathExist(path)) { + ERROR_LOG("Failed to deal path=%s. Reason: not exist or can not access.", + every_path.c_str()); + continue; + } + // get files in path and sub-path + GetPathFiles(every_path, file_vec); + } +} + +void Utils::GetPathFiles(const string &path, vector &file_vec) { + struct dirent *dirent_ptr = nullptr; + DIR *dir = nullptr; + if (IsDirectory(path)) { + dir = opendir(path.c_str()); + while ((dirent_ptr = readdir(dir)) != nullptr) { + // skip . and .. + if (dirent_ptr->d_name[0] == '.') { + continue; + } + + // file path + string full_path = path + kPathSeparator + dirent_ptr->d_name; + // directory need recursion + if (IsDirectory(full_path)) { + GetPathFiles(full_path, file_vec); + } else { + // put file + file_vec.emplace_back(full_path); + } + } + } + else { + file_vec.emplace_back(path); + } +} + +bool Utils::Preprocess(shared_ptr &image_path, + const string &path) { + // read image using OPENCV + cv::Mat mat = cv::imread(path, CV_LOAD_IMAGE_COLOR); + //resize + cv::Mat mat_rs; + cv::resize(mat, mat_rs, cv::Size(MODEL_INPUT_WIDTH, MODEL_INPUT_HEIGHT)); + + if (mat.empty()) { + ERROR_LOG("read image failed."); + return false; + } + + // set property + image_path->input_path = path; + image_path->img_width = mat_rs.cols; + image_path->img_height = mat_rs.rows; + + // set image data + uint32_t size = mat_rs.rows * mat_rs.cols*3; + void *image_buf_ptr = nullptr; + aclrtMalloc(&image_buf_ptr, (size_t)(size), ACL_MEM_MALLOC_HUGE_FIRST); + + if (image_buf_ptr == nullptr) { + ERROR_LOG("new image buffer failed."); + return false; + } + aclError mem_ret = aclrtMemcpy(image_buf_ptr, size, mat_rs.ptr(), size, ACL_MEMCPY_DEVICE_TO_DEVICE); + + if (mem_ret != 0) { + aclrtFree(image_buf_ptr); + delete[] (u_int8_t *)image_buf_ptr; + ERROR_LOG("memcpy_s failed."); + image_buf_ptr = nullptr; + return false; + } + image_path->size = size; + image_path->data.reset((u_int8_t *)image_buf_ptr, + [](u_int8_t* p){ + aclrtFree(p);}); + return true; +}