diff --git a/AMEXEC/amexec测试用例.xlsx b/AMEXEC/amexec测试用例.xlsx new file mode 100755 index 0000000..9d8c90e Binary files /dev/null and b/AMEXEC/amexec测试用例.xlsx differ diff --git a/AMEXEC/build.sh b/AMEXEC/build.sh new file mode 100755 index 0000000..d6052fd --- /dev/null +++ b/AMEXEC/build.sh @@ -0,0 +1,8 @@ +rm -rf build +mkdir -p build/intermediates/host +cd build/intermediates/host +cmake ../../../src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE +make +cd ../../../out +mv main amexec + diff --git a/AMEXEC/inc/model_process.h b/AMEXEC/inc/model_process.h new file mode 100755 index 0000000..de2bc48 --- /dev/null +++ b/AMEXEC/inc/model_process.h @@ -0,0 +1,106 @@ +//Model_process.h + +/** +* @file model_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include "utils.h" +#include "acl/acl.h" + +using namespace std; +/** +* 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 dump model output result to file + */ + void DumpModelOutputResult(); + + /** + * @brief get model output result + */ + void OutputModelResult(std::string& s,std::string& modelName,size_t index); + + +private: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; \ No newline at end of file diff --git a/AMEXEC/inc/sample_process.h b/AMEXEC/inc/sample_process.h new file mode 100755 index 0000000..ee988ff --- /dev/null +++ b/AMEXEC/inc/sample_process.h @@ -0,0 +1,50 @@ +//Sample_process.h + +/** +* @file sample_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include "utils.h" +#include "acl/acl.h" + +using namespace std; +/** +* SampleProcess +*/ +class SampleProcess { +public: + /** + * @brief Constructor + */ + SampleProcess(); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(); + + /** + * @brief sample process + * @return result + */ + Result Process(vector& params, vector& inputs, size_t idx); + +private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; diff --git a/AMEXEC/inc/utils.h b/AMEXEC/inc/utils.h new file mode 100755 index 0000000..ead38c0 --- /dev/null +++ b/AMEXEC/inc/utils.h @@ -0,0 +1,71 @@ +//Util.h + +/** +* @file utils.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) + +using namespace std; +static size_t loop = 1; +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + + +/** +* Utils +*/ +class Utils { +public: + /** + * @brief create device buffer of file + * @param [in] fileName: file name + * @param [out] fileSize: size of file + * @return device buffer of file + */ + static void *GetDeviceBufferOfFile(std::string fileName, uint32_t &fileSize); + + /** + * @brief create buffer of file + * @param [in] fileName: file name + * @param [out] fileSize: size of file + * @return buffer of pic + */ + static void* ReadBinFile(std::string fileName, uint32_t& fileSize); + + static void SplitString(std::string& s, std::vector& v, char c); + + static int str2num(char *str); + + static std::string modelName(string& s); + + static std::string TimeLine(); + + static void printCurrentTime(); + + static void printHelpLetter(); + +}; + +#pragma once diff --git a/AMEXEC/out/amexec b/AMEXEC/out/amexec new file mode 100755 index 0000000..9e91619 Binary files /dev/null and b/AMEXEC/out/amexec differ diff --git a/AMEXEC/readMe.md b/AMEXEC/readMe.md new file mode 100755 index 0000000..b795d3e --- /dev/null +++ b/AMEXEC/readMe.md @@ -0,0 +1,25 @@ +**此工具为模型推理工具** + + + + + +功能:输入.om模型和模型所需要的输入bin文件,输出模型的输出数据文件 + + + +模型必须是通过c7x版本的atc工具转换的om模型,输入bin文件需要符合模型的输入要求 + + + +工具为命令行的运行方式,例如 + +*./amexec --model /home/HwHiAiUser/ljj/colorization.om --input /home/HwHiAiUser/ljj/colorization_input.bin --output /home/HwHiAiUser/ljj/AMEXEC/out/output1 --outfmt TXT --loop 2* + +需要注意的是这几个参数的顺序不能颠倒,outfmt与loop为可选参数,默认值分别有BIN、1。其他参数详情可使用--help查询。 + + + +运行工具的用户在当前目录需要有创建目录以及执行工具的权限,使用前请自行检查。 + +dump、profiling以及动态多batch功能暂不支持。 \ No newline at end of file diff --git a/AMEXEC/src/CMakeLists.txt b/AMEXEC/src/CMakeLists.txt new file mode 100755 index 0000000..a272d89 --- /dev/null +++ b/AMEXEC/src/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) + +# project information +project(AME) + +# 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}) + +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( + ${INC_PATH}/acllib/include/ + ../inc/ +) + +# add host lib path +link_directories( + ${LIB_PATH} +) + +add_executable(main + utils.cpp + # dvpp_process.cpp + model_process.cpp + # singleOp_process.cpp + sample_process.cpp + main.cpp) + +target_link_libraries(main + ascendcl acl_cblas acl_dvpp stdc++) + +install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/AMEXEC/src/main.cpp b/AMEXEC/src/main.cpp new file mode 100755 index 0000000..f88d44a --- /dev/null +++ b/AMEXEC/src/main.cpp @@ -0,0 +1,136 @@ +//main.cpp +/** +* @file main.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "sample_process.h" +#include "utils.h" +#include +using namespace std; + + +bool f_isTXT = false; +bool g_isDevice = false; +string input_Ftype = ".bin"; +string model_Ftype = ".om"; +string check = ""; + + +void InitAndCheckParams(int argc, char* argv[], vector& params, vector& inputs) +{ + + const char *optstring="m::i::o::f::hd::p::l::y::"; + int c,deb,index; + struct option opts[]={{"model",required_argument,NULL,'m'}, + {"input",required_argument,NULL,'i'}, + {"output",required_argument,NULL,'o'}, + {"outfmt",required_argument,NULL,'f'}, + {"help",no_argument,NULL,1}, + {"dumpConf",required_argument,NULL,'d'}, + {"profConf",required_argument,NULL,'p'}, + {"loop",required_argument,NULL,'l'}, + {"dymBatch",required_argument,NULL,'y'}, + {0,0,0,0}}; + while((c=getopt_long(argc,argv,optstring,opts,&index))!=-1) + { + + switch(c) + { + case 'm': + check = optarg; + if (check.find(model_Ftype) != string::npos){ + params.push_back(optarg); + break; + } + else { + printf("input model file type is not .om , please check your model type!\n"); + exit(0); + } + case 'i': + check = optarg; + if (check.find(input_Ftype) == string::npos){ + printf("input data file type is not .bin , please check your input file type!\n"); + exit(0); + } + params.push_back(optarg); + Utils::SplitString(params[1], inputs, ','); + break; + case 'o': + params.push_back(optarg); + break; + case 'f': + params.push_back(optarg); + break; + case '?': + printf("unknown paramenter\n"); + printf("Execute sample failed.\n"); + exit(0); + case 'd': + params.push_back(optarg); + break; + case 'p': + params.push_back(optarg); + break; + case 'l': + loop = Utils::str2num(optarg); + if (loop > 100 || loop < 1) + { + printf("loop must in 1 to 100\n"); + exit(0); + } + break; + case 'y': + params.push_back(optarg); + break; + case 1: + Utils::printHelpLetter(); + exit(0); + default: + printf("unknown paramenter\n"); + printf("Execute sample failed.\n"); + exit(0); + } + } +} + +int main(int argc, char* argv[]) +{ + vector params; + vector inputs; + InitAndCheckParams(argc, argv, params, inputs); + printf("******************************\n"); + printf("Test Start!\n"); + + + if (params.empty() || inputs.empty()) { + printf("Invalid params.\n"); + printf("Execute sample failed.\n"); + return FAILED; + } + + SampleProcess processSample; + + Result ret = processSample.InitResource(); + if (ret != SUCCESS) { + ERROR_LOG("Sample init resource failed."); + return FAILED; + } + for (size_t i = 0;i < loop;i++){ + std::cout << i << endl; + ret = processSample.Process(params, inputs, i); + if (ret != SUCCESS) { + ERROR_LOG("Sample process failed."); + return FAILED; + } + } + INFO_LOG("Execute sample success."); + printf("Test Finish!\n"); + printf("******************************\n"); + + return SUCCESS; +} diff --git a/AMEXEC/src/model_process.cpp b/AMEXEC/src/model_process.cpp new file mode 100755 index 0000000..0965309 --- /dev/null +++ b/AMEXEC/src/model_process.cpp @@ -0,0 +1,571 @@ +//Model_procccess.cpp + +/** +* @file model_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "model_process.h" +#include "utils.h" +#include +#include +#include +#include + +using namespace std; +extern bool g_isDevice; +extern bool f_isTXT; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), 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_NORMAL_ONLY); + 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_NORMAL_ONLY); + 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; + } +} + +Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) +{ + if (input_ == nullptr) { + 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 (ret != ACL_ERROR_NONE) { + ERROR_LOG("add input dataset buffer failed"); + aclDestroyDataBuffer(inputData); + 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::DumpModelOutputResult() +{ + stringstream ss; + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + static int executeNum = 0; + for (size_t i = 0; i < outputNum; ++i) { + ss << "output" << ++executeNum << "_" << i << ".bin"; + string outputFileName = ss.str(); + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSize(dataBuffer); + + void* outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&outHostData, len); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret); + return; + } + + ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret); + (void)aclrtFreeHost(outHostData); + return; + } + + fwrite(outHostData, len, sizeof(char), outputFile); + + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } else { + fwrite(data, len, sizeof(char), outputFile); + } + fclose(outputFile); + outputFile = nullptr; + } else { + ERROR_LOG("create output file [%s] failed", outputFileName.c_str()); + return; + } + } + + INFO_LOG("dump data success"); + return; +} + */ +void ModelProcess::OutputModelResult(std::string& s,std::string& modelName,size_t index) +{ + const char* temp_s = s.c_str(); + if (NULL == opendir(temp_s)){ + mkdir(temp_s,0775); + } + std::string T = Utils::TimeLine(); + //std::string t = s.c_str()+"/"+T.c_str(); + //const char* time = t.c_str(); + string times = s+"/"+T+"_"+to_string(index); + const char* time = times.c_str(); + cout << time <(dims); + ret = aclmdlGetOutputDims(modelDesc_, i, dim); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclmdlGetOutputDims failed, ret[%d]", ret); + return; + } + + void *outHostData = NULL; + ret = ACL_ERROR_NONE; + void *outData = NULL; + if (!g_isDevice) { + ret = aclrtMallocHost(&outHostData, len); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret); + return; + } + + ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret); + return; + } + switch (datatype) + { + case 0: + outData = reinterpret_cast(outHostData); + break; + case 1: + outData = reinterpret_cast(outHostData); + break; + case 2: + outData = reinterpret_cast(outHostData); + break; + case 3: + outData = reinterpret_cast(outHostData); + break; + case 4: + outData = reinterpret_cast(outHostData); + break; + case 6: + outData = reinterpret_cast(outHostData); + break; + case 7: + outData = reinterpret_cast(outHostData); + break; + case 8: + outData = reinterpret_cast(outHostData); + break; + case 9: + outData = reinterpret_cast(outHostData); + break; + case 10: + outData = reinterpret_cast(outHostData); + break; + case 11: + outData = reinterpret_cast(outHostData); + break; + case 12: + outData = reinterpret_cast(outHostData); + break; + default : + printf("undefined data type!\n"); + break; + } + + } else { + outData = reinterpret_cast(data); + } + if (f_isTXT) + { + ofstream outstr(times+"/"+modelName+"_output_"+to_string(i)+".txt", ios::out); + switch (datatype) + { + case 0: + for (int i = 0; i < len/sizeof(float); i++) + { + float out = *((float*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 1: + for (int i = 0; i < len/sizeof(aclFloat16); i++) + { + aclFloat16 out = *((aclFloat16*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 2: + for (int i = 0; i < len/sizeof(int8_t); i++) + { + int8_t out = *((int8_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 3: + for (int i = 0; i < len/sizeof(int); i++) + { + int out = *((int*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 4: + for (int i = 0; i < len/sizeof(uint8_t); i++) + { + uint8_t out = *((uint8_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 6: + for (int i = 0; i < len/sizeof(int16_t); i++) + { + int16_t out = *((int16_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 7: + for (int i = 0; i < len/sizeof(uint16_t); i++) + { + uint16_t out = *((uint16_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 8: + for (int i = 0; i < len/sizeof(uint32_t); i++) + { + uint32_t out = *((uint32_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 9: + for (int i = 0; i < len/sizeof(int64_t); i++) + { + int64_t out = *((int64_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 10: + for (int i = 0; i < len/sizeof(uint64_t); i++) + { + uint64_t out = *((uint64_t*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 11: + for (int i = 0; i < len/sizeof(double); i++) + { + double out = *((double*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + case 12: + for (int i = 0; i < len/sizeof(bool); i++) + { + int out = *((bool*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } + break; + default : + printf("undefined data type!\n"); + break; + } + outstr.close(); + } + else + { + ofstream outstr(times+"/"+modelName+"_output_"+to_string(i)+".bin", ios::out|ios::binary); + + outstr.write((char*)outData, len); + outstr.close(); + } + + + if (!g_isDevice) { + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + } + + INFO_LOG("output data success"); + return; +} + +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 syccess, model Id is %u", modelId_); +} diff --git a/AMEXEC/src/sample_process.cpp b/AMEXEC/src/sample_process.cpp new file mode 100755 index 0000000..60c2908 --- /dev/null +++ b/AMEXEC/src/sample_process.cpp @@ -0,0 +1,193 @@ +//Sample_process.cpp + +/** +* @file sample_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "sample_process.h" +#include "model_process.h" +#include "acl/acl.h" +#include "utils.h" +using namespace std; +extern bool g_isDevice; +extern bool f_isTXT; + +SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) +{ +} + +SampleProcess::~SampleProcess() +{ + DestroyResource(); +} + +Result SampleProcess::InitResource() +{ + // ACL init + const char *aclConfigPath = ""; + 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"); + + // get run mode + aclrtRunMode runMode; + ret = aclrtGetRunMode(&runMode); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl get run mode failed"); + return FAILED; + } + g_isDevice = (runMode == ACL_DEVICE); + INFO_LOG("get run mode success"); + return SUCCESS; +} + +Result SampleProcess::Process(vector& params, vector& input_files, size_t idx) +{ + // model init + ModelProcess processModel; + const char* omModelPath = params[0].c_str(); + std::string output_path = params[2].c_str(); + const char* outfmt = params[3].c_str(); + const char* fmt_TXT = "TXT"; + f_isTXT = (strcmp(outfmt,fmt_TXT)==0); + const char* dumpConf = params[4].c_str(); + const char* profConf = params[5].c_str(); + const char* dymBatch = params[6].c_str(); + + std::string modelPath = params[0].c_str(); + std::string modelName = Utils::modelName(modelPath); + + Result ret = processModel.LoadModelFromFileWithMem(omModelPath); + if (ret != SUCCESS) { + ERROR_LOG("load model from file failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("create model description failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("create model output failed"); + return FAILED; + } + + vector picDevBuffer(input_files.size(),nullptr); + + for (size_t index = 0; index < input_files.size(); ++index) { + INFO_LOG("start to process file:%s", input_files[index].c_str()); + // model process + uint32_t devBufferSize; + picDevBuffer[index] = Utils::GetDeviceBufferOfFile(input_files[index], devBufferSize); + if (picDevBuffer[index] == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); + return FAILED; + } + + ret = processModel.CreateInput(picDevBuffer[index], devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("model create input failed"); + for (size_t i = 0; i <= index; i++) { + aclrtFree(picDevBuffer[i]); + } + return FAILED; + } + + // loop end + + printf("Inference begin time: "); + Utils::printCurrentTime(); + ret = processModel.Execute(); + printf("Inference end time: "); + Utils::printCurrentTime(); + if (ret != SUCCESS) { + ERROR_LOG("model execute failed"); + for (size_t i = 0; i < index; i++) { + aclrtFree(picDevBuffer[i]); + } + return FAILED; + } + + // print the top 5 confidence values with indexes.use function DumpModelOutputResult + // if want to dump output result to file in the current directory + //processModel.DumpModelOutputResult(); + processModel.OutputModelResult(output_path,modelName,idx); + processModel.DestroyInput(); +} + // release model input buffer + for (size_t i = 0; i < input_files.size(); i++) { + aclrtFree(picDevBuffer[i]); + } + + 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/AMEXEC/src/utils.cpp b/AMEXEC/src/utils.cpp new file mode 100755 index 0000000..099b448 --- /dev/null +++ b/AMEXEC/src/utils.cpp @@ -0,0 +1,177 @@ +//Util.cpp + +/** +* @file utils.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "utils.h" +#include +#include "acl/acl.h" +using namespace std; +extern bool g_isDevice; +extern bool f_isTXT; + +void* Utils::ReadBinFile(std::string fileName, uint32_t &fileSize) +{ + std::ifstream binFile(fileName, std::ifstream::binary); + if (binFile.is_open() == false) { + ERROR_LOG("open file %s failed", fileName.c_str()); + return nullptr; + } + + binFile.seekg(0, binFile.end); + uint32_t binFileBufferLen = binFile.tellg(); + if (binFileBufferLen == 0) { + ERROR_LOG("binfile is empty, filename is %s", fileName.c_str()); + binFile.close(); + return nullptr; + } + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen); + binFile.close(); + return nullptr; + } + } + binFile.read(static_cast(binFileBufferData), binFileBufferLen); + binFile.close(); + fileSize = binFileBufferLen; + return binFileBufferData; +} + +void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t &fileSize) +{ + uint32_t inputHostBuffSize = 0; + void* inputHostBuff = Utils::ReadBinFile(fileName, inputHostBuffSize); + if (inputHostBuff == nullptr) { + return nullptr; + } + if (!g_isDevice) { + void *inBufferDev = nullptr; + uint32_t inBufferSize = inputHostBuffSize; + aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, ACL_MEM_MALLOC_NORMAL_ONLY); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + + ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u", + inBufferSize, inputHostBuffSize); + aclrtFree(inBufferDev); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + aclrtFreeHost(inputHostBuff); + fileSize = inBufferSize; + return inBufferDev; + } else { + fileSize = inputHostBuffSize; + return inputHostBuff; + } +} + +void Utils::SplitString(std::string& s, std::vector& v, char c) +{ + std::string::size_type pos1, pos2; + pos2 = s.find(c); + pos1 = 0; + while(std::string::npos != pos2) + { + v.push_back(s.substr(pos1, pos2-pos1)); + pos1 = pos2 + 1; + pos2 = s.find(c, pos1); + } + if(pos1 != s.length()) + v.push_back(s.substr(pos1)); +} + +int Utils::str2num(char *str) +{ + int n = 0; + int flag = 0; + while(*str >= '0' && *str <= '9') + { + n = n*10 + (*str - '0'); + str++; + } + if(flag == 1) + { + n = -n; + } + return n; +} + +std::string Utils::modelName(string& s) +{ + string::size_type position1,position2; + position1 = s.find_last_of("/"); + if (position1 == s.npos) + { + position1 = 0; + } + position2 = s.find_last_of("."); + std::string modelName = s.substr(position1,position2-position1); + return modelName; +} + +std::string Utils::TimeLine() +{ + time_t currentTime = time(NULL); + char chCurrentTime[64]; + strftime(chCurrentTime, sizeof(chCurrentTime), "%Y%m%d_%H%M%S", localtime(¤tTime)); + std::string stCurrentTime = chCurrentTime; + return stCurrentTime; +} + +void Utils::printCurrentTime() +{ + char szBuf[256] = {0}; + struct timeval tv; + struct timezone tz; + struct tm *p; + + gettimeofday(&tv, &tz); + p = localtime(&tv.tv_sec); + printf("%02d-%02d-%02d %02d:%02d:%02d.%06ld\n", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, tv.tv_usec); + +} +void Utils::printHelpLetter() +{ + cout<< "generate offline model inference output file example:" << endl; + cout<< "./amexec --model /home/HwHiAiUser/ljj/colorization.om --input /home/HwHiAiUser/ljj/colorization_input.bin --output /home/HwHiAiUser/ljj/AMEXEC/out/output1 --outfmt TXT --loop 2" << endl << endl; + + cout<< "arguments explain:" << endl; + cout<< " --model Model file path" << endl; + cout<< " --input Input data path(only accept binary data file) If there are several file, please seprate by ','" << endl; + cout<< " --output Output path(User needs to have permission to create directories)" << endl; + cout<< " --outfmt Output file format (TXT or BIN, default BIN)" << endl; + cout<< " --loop loop time(must in 1 to 100)" << endl; + cout<< " --dumpConf dump configure file path (Do not support now)" << endl; + cout<< " --profConf profiling configure file path (Do not support now)" << endl; + cout<< " --dymBatch dynamic batch (Do not support now)" << endl << endl << endl; + + + cout<< "NOTECE: " << endl; + cout<< " The order of parameter must follow in --model --input --output --outfmt --loop " << endl; +} diff --git a/AMEXEC/模型推理工具.docx b/AMEXEC/模型推理工具.docx new file mode 100755 index 0000000..07e052c Binary files /dev/null and b/AMEXEC/模型推理工具.docx differ diff --git a/imgtobin/Readme.md b/imgtobin/Readme.md new file mode 100644 index 0000000..58d5551 --- /dev/null +++ b/imgtobin/Readme.md @@ -0,0 +1,40 @@ +# imgtobin + +imgtobin能够生成模型推理所需的输入数据,以.bin格式保存。 +有两类数据,一类是图片数据,另一类是模型需要的第二个输入数据,如fasterrcnn的第二个输入是图片的shape信息。 + +## 使用方法 + +-i后跟**目录**表示转换图片,-i后跟**文件路径**表示转换第二类数据。 + +### 第一类图片: + +- 脚本会将 -i 后指定的图片目录下的所有图片按参数设置做相应的预处理,并以"文件名.bin"命名保存在-o指定的输出目录下。 + +``` +python3 imgtobin.py -i ./images -w 416 -h 416 -f BGR -a NCHW -m [104,117,123] -c [1,1,1] -o ./out +``` + +### 第二类: + +- 第二类数据,需要新建一个文件,文件模板为test.txt,input_node为数据,shape为数据的shape信息。 +- 第二类数据只需 -i、-t、-o三个参数。 +- 参数 -i 需要指定文件的路径,-t 需要指定数据类型,-o指定输出目录。 + +``` +python3 imgtobin.py -i ./test.txt -t uint8 -o ./out +``` + +## 参数说明 + +| 参数名 | 说明 | +| - | - | +| -i | 图片的输入目录或第二个输入的文件路径 | +| -w | 输出图片宽 | +| -h | 输出图片高 | +| -f | 输出图片色彩格式,支持(BGR/RGB/YUV/GRAY) | +| -a | 输出图片格式,支持(NCHW/NHWC) | +| -t | 图片或第二个数据的输出数据类型,支持(float32/uint8/int32/uint32) | +| -m | 减均值,默认为[0,0,0],顺序与图片色彩格式保持一致
当色彩格式为yuv时,设置[0,0]
当色彩格式为gray时,设置[0] | +| -c | 归一化,默认为 [1,1,1],顺序与图片色彩格式保持一致
当色彩格式为yuv时,设置[1,1]
当色彩格式为gray时,设置[1] | +| -o | 输出目录 | \ No newline at end of file diff --git a/imgtobin/bgr2.bin b/imgtobin/bgr2.bin new file mode 100644 index 0000000..3a803ab Binary files /dev/null and b/imgtobin/bgr2.bin differ diff --git a/imgtobin/imgtobin.py b/imgtobin/imgtobin.py new file mode 100644 index 0000000..40ff247 --- /dev/null +++ b/imgtobin/imgtobin.py @@ -0,0 +1,234 @@ +# !/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# +# ======================================================================= +# +# Copyright (C) 2018, Hisilicon Technologies Co., Ltd. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1 Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2 Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3 Neither the names of the copyright holders nor the names of the +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ======================================================================= +# +import argparse +import configparser +import cv2 as cv +import numpy as np +import json +import os +import re +import sys + + +def get_args(): + parser = argparse.ArgumentParser( + conflict_handler='resolve', + description='''eg1: python3 imgtobin.py + -i ./images -w 416 -h 416 -f BGR -a NCHW -m [104,117,123] -o ./out + eg2: python3 imgtobin.py -i ./test.txt -t uint8''') + parser.add_argument('-i', '--input', required=True, type=str, \ + help='folder of input image or file of other input.') + parser.add_argument('-w', '--width', type=int, \ + help='resized image width before inference.') + parser.add_argument('-h', '--height', type=int, \ + help='resized image height before inference.') + parser.add_argument('-f', '--output_image_format', default='BGR', type=str, \ + help='output image format in (BGR/RGB/YUV/GRAY).') + parser.add_argument('-a', '--output_format', default='NCHW', type=str, \ + help='output format in (NCHW/NHWC).') + parser.add_argument('-t', '--output_type', required=True, type=str, \ + help='output type in (float32/uint8/int32/uint32).') + parser.add_argument('-m', '--mean', default='[0, 0, 0]', \ + help='reduce mean for each channel.') + parser.add_argument('-c', '--coefficient', default='[1, 1, 1]', \ + help='multiplying coefficients for each channel.') + parser.add_argument('-o', '--output', default='./', \ + help='output path.') + return parser.parse_args() + + +def eprint(*args, **kwargs): + """print error message to stderr + """ + print(*args, file=sys.stderr, **kwargs) + + +def check_args(args): + """check console parameters according to restrictions. + :return: True or False + """ + check_flag = True + is_dir = True + if os.path.isdir(args.input): + #print(args) + if not os.listdir(args.input): + eprint('[ERROR] input image path=%r is empty.' % path) + check_flag = False + elif os.path.isfile(args.input): + is_dir = False + else: + eprint('[ERROR] input path=%r does not exist.' % path) + check_flag = False + + if args.output_image_format not in ('BGR','RGB', 'YUV', 'GRAY'): + eprint("ERROR:Convert to %d is not support"%(args.output_image_format)) + check_flag = False + # if os.path.isfile(args.output_path): + # eprint('[ERROR] argument output_path should be a folder.') + # elif not os.path.exists(args.output_path): + # os.makedirs(args.output_path) + # if not 16 <= args.model_width <= 4096: + # eprint('[ERROR] resized image width should between 16 and 4096.') + # check_flag = False + # if not 16 <= args.model_height <= 4096: + # eprint('[ERROR] resized image height should between 16 andd 4096.') + # check_flag = False + return check_flag, is_dir + + +def convert_img(args, input_img): + if args.output_image_format == 'BGR': + converted_input_img = input_img + elif args.output_image_format == 'RGB': + converted_input_img = cv.cvtColor(input_img, cv.COLOR_BGR2RGB) + elif args.output_image_format == 'YUV': + if input_img.shape[0] % 2 == 1: + if input_img.shape[1] % 2 == 1: + input_img = cv.resize(input_img, ((input_img.shape[0] + 1), (input_img.shape[1] + 1))) + else: + input_img = cv.resize(input_img, ((input_img.shape[0] + 1), input_img.shape[1])) + elif input_img.shape[1] % 2 == 1: + input_img = cv.resize(input_img, (input_img.shape[0], input_img.shape[1] + 1)) + converted_input_img = cv.cvtColor(input_img, cv.COLOR_BGR2YUV_I420) + elif args.output_image_format == 'GRAY': + converted_input_img = cv.cvtColor(input_img, cv.COLOR_BGR2GRAY) + return converted_input_img + + +def resize_img(args, input_img): + resized_img = cv.resize(input_img, (args.width, args.height)) + return resized_img + + +def change_type(args, input_img): + if args.output_type == 'float32': + change_type_img = input_img.astype(np.float32) + elif args.output_type == 'int32': + change_type_img = input_img.astype(np.int32) + elif args.output_type == 'uint32': + change_type_img = input_img.astype(np.uint32) + else: + change_type_img = input_img.astype(np.uint8) + return change_type_img + + +def mean(args, input_img): + if isinstance (args.mean, str): + args.mean = json.loads(args.mean) + input_img = input_img.astype(np.float32) + if args.output_image_format == 'GRAY': + input_img[:, :] -= args.mean[0] + elif args.output_image_format in ('BGR', 'RGB'): + input_img[:, :, 0] -= args.mean[0] + input_img[:, :, 1] -= args.mean[1] + input_img[:, :, 2] -= args.mean[2] + else: + input_img[: int(args.width / 1.5), :] -= args.mean[0] + input_img[int(args.width / 1.5) :, :: 2] -= args.mean[1] + input_img[int(args.width / 1.5) :, 1: 2] -= args.mean[2] + return input_img + + +def coefficient(args, input_img): + if isinstance (args.coefficient, str): + args.coefficient = json.loads(args.coefficient) + input_img = input_img.astype(np.float32) + if args.output_image_format == 'GRAY': + input_img[:, :] *= args.coefficient[0] + elif args.output_image_format in ('BGR', 'RGB'): + input_img[:, :, 0] *= args.coefficient[0] + input_img[:, :, 1] *= args.coefficient[1] + input_img[:, :, 2] *= args.coefficient[2] + else: + input_img[: int(args.width / 1.5), :] *= args.coefficient[0] + input_img[int(args.width / 1.5) :, :: 2] *= args.coefficient[1] + input_img[int(args.width / 1.5) :, 1: 2] *= args.coefficient[2] + return input_img + + +def change_format(args, input_img): + if args.output_format == 'NCHW': + if args.output_image_format in ('RGB', 'BGR'): + change_format_img = input_img.transpose(2,0,1).copy() + return change_format_img + return input_img + + +def mkdir_output(args): + if not os.path.exists(args.output): + os.makedirs(args.output) + return + + +def main(): + """main function to receive params them change data to bin. + """ + args = get_args() + ret,is_dir = check_args(args) + if ret: + if is_dir: + img_names = os.listdir(args.input) + for img_name in img_names: + img_path = os.path.join(args.input, img_name) + input_img = cv.imread(img_path) + if args.output_image_format == 'YUV': + resized_img1 = resize_img(args, input_img) + converted_img = convert_img(args, resized_img1) + mean_img = mean(args, converted_img) + else: + converted_img = convert_img(args, input_img) + resized_img = resize_img(args, converted_img) + mean_img = mean(args, resized_img) + coefficient_img = coefficient(args, mean_img) + change_type_img = change_type(args, coefficient_img) + change_format_img = change_format(args, change_type_img) + out_path = os.path.join(args.output, os.path.splitext(img_name)[0] + ".bin") + mkdir_output(args) + change_format_img.tofile(out_path) + else: + config = configparser.ConfigParser() + config.read(args.input) + input_node = json.loads(config['baseconf']['input_node']) + shape = json.loads(config['baseconf']['shape']) + input_node_np = np.array(input_node) + change_type_img_info = change_type(args, input_node_np) + img_info = np.reshape(change_type_img_info, shape) + out_path = os.path.join(args.output, os.path.splitext(args.input)[0] + ".bin") + mkdir_output(args) + img_info.tofile(out_path) + + +if __name__ == '__main__': + main() diff --git a/imgtobin/pic/dog2.jpg b/imgtobin/pic/dog2.jpg new file mode 100644 index 0000000..e57bf80 Binary files /dev/null and b/imgtobin/pic/dog2.jpg differ diff --git a/imgtobin/test.txt b/imgtobin/test.txt new file mode 100644 index 0000000..740a983 --- /dev/null +++ b/imgtobin/test.txt @@ -0,0 +1,3 @@ +[baseconf] +input_node=[1200,1150,416,416] +shape=[1,4] \ No newline at end of file