diff --git a/official/cv/inceptionv3/infer/convert/aipp.cfg b/official/cv/inceptionv3/infer/convert/aipp.cfg new file mode 100644 index 0000000000000000000000000000000000000000..20e53dab18b9b10800c7e2e63b014c0c6cb69428 --- /dev/null +++ b/official/cv/inceptionv3/infer/convert/aipp.cfg @@ -0,0 +1,11 @@ +aipp_op { + aipp_mode: static + input_format : RGB888_U8 + rbuv_swap_switch : true + min_chn_0 : 123.675 + min_chn_1 : 116.28 + min_chn_2 : 103.53 + var_reci_chn_0 : 0.0171247538316637 + var_reci_chn_1 : 0.0175070028011204 + var_reci_chn_2 : 0.0174291938997821 +} \ No newline at end of file diff --git a/official/cv/inceptionv3/infer/convert/convert_om.sh b/official/cv/inceptionv3/infer/convert/convert_om.sh new file mode 100644 index 0000000000000000000000000000000000000000..3064b024550042ebbc22a10ad6ff64df69d442e0 --- /dev/null +++ b/official/cv/inceptionv3/infer/convert/convert_om.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Copyright 2021 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. +# ============================================================================ + +if [ $# -ne 3 ] +then + echo "Wrong parameter format." + echo "Usage:" + echo " bash $0 [INPUT_AIR_PATH] [AIPP_PATH] [OUTPUT_OM_PATH_NAME]" + echo "Example: " + echo " bash convert_om.sh xxx.air ./aipp.cfg xx" + + exit 1 +fi + +input_air_path=$1 +aipp_cfg_file=$2 +output_om_path=$3 + + +echo "Input AIR file path: ${input_air_path}" +echo "Output OM file path: ${output_om_path}" + +atc --input_format=NCHW \ + --framework=1 \ + --model="${input_air_path}" \ + --input_shape="x:1, 3, 299, 299" \ + --output="${output_om_path}" \ + --insert_op_conf="${aipp_cfg_file}" \ + --soc_version=Ascend310 \ No newline at end of file diff --git a/official/cv/inceptionv3/infer/data/config/inceptionv3.cfg b/official/cv/inceptionv3/infer/data/config/inceptionv3.cfg new file mode 100644 index 0000000000000000000000000000000000000000..581fc76d3d75445323ea9a387f7152a72bedd1d3 --- /dev/null +++ b/official/cv/inceptionv3/infer/data/config/inceptionv3.cfg @@ -0,0 +1,3 @@ +CLASS_NUM=1000 +SOFTMAX=false +TOP_K=5 diff --git a/official/cv/inceptionv3/infer/docker_start_infer.sh b/official/cv/inceptionv3/infer/docker_start_infer.sh new file mode 100644 index 0000000000000000000000000000000000000000..f501a561c22748e5077f399e3102825bdb44ae78 --- /dev/null +++ b/official/cv/inceptionv3/infer/docker_start_infer.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Copyright 2021 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. + +docker_image=$1 +share_dir=$2 +echo "$1" +echo "$2" +if [ -z "${docker_image}" ]; then + echo "please input docker_image" + exit 1 +fi + +if [ ! -d "${share_dir}" ]; then + echo "please input share directory that contains dataset, models and codes" + exit 1 +fi + + +docker run -it \ + --device=/dev/davinci0 \ + --device=/dev/davinci_manager \ + --device=/dev/devmm_svm \ + --device=/dev/hisi_hdc \ + --privileged \ + -v //usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ + -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ + -v ${share_dir}:${share_dir} \ + ${docker_image} \ + /bin/bash diff --git a/official/cv/inceptionv3/infer/mxbase/CMakeLists.txt b/official/cv/inceptionv3/infer/mxbase/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b9d4951dfc66249fe9df9e0754a91154e4d98527 --- /dev/null +++ b/official/cv/inceptionv3/infer/mxbase/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.10.0) +project(inceptionv3) + +set(TARGET inceptionv3) + +add_definitions(-DENABLE_DVPP_INTERFACE) +add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) +add_definitions(-Dgoogle=mindxsdk_private) +add_compile_options(-std=c++11 -fPIE -fstack-protector-all -fPIC -Wall) +add_link_options(-Wl,-z,relro,-z,now,-z,noexecstack -s -pie) + +set(ACL_INC_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/$ENV{ARCH_PATTERN}/acllib/include) +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/$ENV{ARCH_PATTERN}/acllib/lib64) + +set(MXBASE_ROOT_DIR $ENV{MX_SDK_HOME}) +set(MXBASE_INC ${MXBASE_ROOT_DIR}/include) +set(MXBASE_LIB_DIR ${MXBASE_ROOT_DIR}/lib) +set(MXBASE_POST_LIB_DIR ${MXBASE_ROOT_DIR}/lib/modelpostprocessors) +set(MXBASE_POST_PROCESS_DIR ${MXBASE_ROOT_DIR}/include/MxBase/postprocess/include) + +if(DEFINED ENV{MXSDK_OPENSOURCE_DIR}) + set(OPENSOURCE_DIR $ENV{MXSDK_OPENSOURCE_DIR}) +else() + set(OPENSOURCE_DIR ${MXBASE_ROOT_DIR}/opensource) +endif() + + +include_directories(${ACL_INC_DIR}) +include_directories(${OPENSOURCE_DIR}/include) +include_directories(${OPENSOURCE_DIR}/include/opencv4) + +include_directories(${MXBASE_INC}) +include_directories(${MXBASE_POST_PROCESS_DIR}) + +link_directories(${ACL_LIB_DIR}) +link_directories(${OPENSOURCE_DIR}/lib) +link_directories(${MXBASE_LIB_DIR}) +link_directories(${MXBASE_POST_LIB_DIR}) + +message("${MXBASE_POST_PROCESS_DIR}") +message("${MXBASE_POST_LIB_DIR}") + +add_executable(${TARGET} src/main.cpp src/InceptionV3.cpp) + +target_link_libraries(${TARGET} glog cpprest mxbase resnet50postprocess opencv_world) + +install(TARGETS ${TARGET} RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/) diff --git a/official/cv/inceptionv3/infer/mxbase/build.sh b/official/cv/inceptionv3/infer/mxbase/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..ff7e43d765f156befc686045868e04fb1e95d2ab --- /dev/null +++ b/official/cv/inceptionv3/infer/mxbase/build.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Copyright 2021 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. +# ============================================================================ + +mkdir -p build +cd build || exit + +function make_plugin() { + if ! cmake ..; + then + echo "cmake failed." + return 1 + fi + + if ! (make); + then + echo "make failed." + return 1 + fi + + return 0 +} + +if make_plugin; +then + echo "INFO: Build successfully." +else + echo "ERROR: Build failed." +fi + +cd - || exit diff --git a/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.cpp b/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b5efcf027960287f88c2d1deee4f4838d26c436 --- /dev/null +++ b/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.cpp @@ -0,0 +1,200 @@ +/* +* Copyright 2021 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. +*/ + +#include "InceptionV3.h" +#include <memory> +#include <string> +#include <vector> +#include <map> +#include "MxBase/DeviceManager/DeviceManager.h" +#include "MxBase/Log/Log.h" +using namespace MxBase; + +APP_ERROR InceptionV3::Init(const InitParam &initParam) { + deviceId_ = initParam.deviceId; + APP_ERROR ret = MxBase::DeviceManager::GetInstance()->InitDevices(); + if (ret != APP_ERR_OK) { + LogError << "Init devices failed, ret=" << ret << "."; + return ret; + } + ret = MxBase::TensorContext::GetInstance()->SetContext(initParam.deviceId); + if (ret != APP_ERR_OK) { + LogError << "Set context failed, ret=" << ret << "."; + return ret; + } + model_ = std::make_shared<MxBase::ModelInferenceProcessor>(); + ret = model_->Init(initParam.modelPath, modelDesc_); + if (ret != APP_ERR_OK) { + LogError << "ModelInferenceProcessor init failed, ret=" << ret << "."; + return ret; + } + + const std::string softmax = initParam.softmax ? "true" : "false"; + const std::string checkTensor = initParam.checkTensor ? "true" : "false"; + MxBase::ConfigData configData; + configData.SetJsonValue("CLASS_NUM", std::to_string(initParam.classNum)); + configData.SetJsonValue("TOP_K", std::to_string(initParam.topk)); + configData.SetJsonValue("SOFTMAX", softmax); + configData.SetJsonValue("CHECK_MODEL", checkTensor); + + auto jsonStr = configData.GetCfgJson().serialize(); + std::map<std::string, std::shared_ptr<void>> config; + config["postProcessConfigContent"] = std::make_shared<std::string>(jsonStr); + config["labelPath"] = std::make_shared<std::string>(initParam.labelPath); + post_ = std::make_shared<MxBase::Resnet50PostProcess>(); + ret = post_->Init(config); + if (ret != APP_ERR_OK) { + LogError << "Resnet50PostProcess init failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR InceptionV3::DeInit() { + model_->DeInit(); + post_->DeInit(); + MxBase::DeviceManager::GetInstance()->DestroyDevices(); + return APP_ERR_OK; +} + +void InceptionV3::ReadImage(const std::string &imgPath, cv::Mat *imageMat) { + *imageMat = cv::imread(imgPath, cv::IMREAD_COLOR); +} + +void InceptionV3::ResizeImage(const cv::Mat &srcImageMat, cv::Mat *dstImageMat) { + static constexpr uint32_t resizeHeight = 299; + static constexpr uint32_t resizeWidth = 299; + cv::resize(srcImageMat, *dstImageMat, cv::Size(resizeWidth, resizeHeight)); +} + +APP_ERROR InceptionV3::CVMatToTensorBase(const cv::Mat &imageMat, + MxBase::TensorBase *tensorBase) { + const uint32_t dataSize = imageMat.cols * imageMat.rows * YUV444_RGB_WIDTH_NU; + LogInfo << "image size after resize" << imageMat.cols << " " << imageMat.rows; + MemoryData memoryDataDst(dataSize, MemoryData::MEMORY_DEVICE, deviceId_); + MemoryData memoryDataSrc(imageMat.data, dataSize, MemoryData::MEMORY_HOST_MALLOC); + APP_ERROR ret = MemoryHelper::MxbsMallocAndCopy(memoryDataDst, memoryDataSrc); + if (ret != APP_ERR_OK) { + LogError << GetError(ret) << "Memory malloc failed."; + return ret; + } + std::vector<uint32_t> shape = { imageMat.rows * YUV444_RGB_WIDTH_NU, static_cast<uint32_t>(imageMat.cols) }; + *tensorBase = TensorBase(memoryDataDst, false, shape, TENSOR_DTYPE_UINT8); + return APP_ERR_OK; +} + +APP_ERROR InceptionV3::Inference(const std::vector<MxBase::TensorBase> &inputs, + std::vector<MxBase::TensorBase> *outputs) { + auto dtypes = model_->GetOutputDataType(); + for (size_t i = 0; i < modelDesc_.outputTensors.size(); ++i) { + std::vector<uint32_t> shape = {}; + for (size_t j = 0; j < modelDesc_.outputTensors[i].tensorDims.size(); ++j) { + shape.push_back((uint32_t)modelDesc_.outputTensors[i].tensorDims[j]); + } + TensorBase tensor(shape, dtypes[i], MemoryData::MemoryType::MEMORY_DEVICE, deviceId_); + APP_ERROR ret = TensorBase::TensorBaseMalloc(tensor); + if (ret != APP_ERR_OK) { + LogError << "TensorBaseMalloc failed, ret=" << ret << "."; + return ret; + } + outputs->push_back(tensor); + } + DynamicInfo dynamicInfo = {}; + dynamicInfo.dynamicType = DynamicType::STATIC_BATCH; + auto startTime = std::chrono::high_resolution_clock::now(); + APP_ERROR ret = model_->ModelInference(inputs, *outputs, dynamicInfo); + auto endTime = std::chrono::high_resolution_clock::now(); + double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count(); + inferCostTimeMilliSec += costMs; + if (ret != APP_ERR_OK) { + LogError << "ModelInference failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR InceptionV3::PostProcess(const std::vector<MxBase::TensorBase> &inputs, + std::vector<std::vector<MxBase::ClassInfo>> *clsInfos) { + APP_ERROR ret = post_->Process(inputs, *clsInfos); + if (ret != APP_ERR_OK) { + LogError << "Process failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR InceptionV3::SaveResult(const std::string &imgPath, + std::vector<std::vector<MxBase::ClassInfo>> *batchClsInfos) { + LogInfo << "image path" << imgPath; + std::string fileName = imgPath.substr(imgPath.find_last_of("/") + 1); + size_t dot = fileName.find_last_of("."); + std::string resFileName = "infer_results/" + fileName.substr(0, dot) + "_1.txt"; + LogInfo << "file path for saving result" << resFileName; + std::ofstream outfile(resFileName); + if (outfile.fail()) { + LogError << "Failed to open result file: "; + return APP_ERR_COMM_FAILURE; + } + uint32_t batchIndex = 0; + for (auto clsInfos : *batchClsInfos) { + std::string resultStr; + for (auto clsInfo : clsInfos) { + LogDebug << " className:" << clsInfo.className << " confidence:" << clsInfo.confidence << + " classIndex:" << clsInfo.classId; + resultStr += std::to_string(clsInfo.classId) + " "; + } + outfile << resultStr << std::endl; + batchIndex++; + } + outfile.close(); + return APP_ERR_OK; +} + +APP_ERROR InceptionV3::Process(const std::string &imgPath) { + cv::Mat imageMat; + ReadImage(imgPath, &imageMat); + ResizeImage(imageMat, &imageMat); + std::vector<MxBase::TensorBase> inputs = {}; + std::vector<MxBase::TensorBase> outputs = {}; + TensorBase tensorBase; + APP_ERROR ret = CVMatToTensorBase(imageMat, &tensorBase); + if (ret != APP_ERR_OK) { + LogError << "CVMatToTensorBase failed, ret=" << ret << "."; + return ret; + } + inputs.push_back(tensorBase); + auto startTime = std::chrono::high_resolution_clock::now(); + ret = Inference(inputs, &outputs); + auto endTime = std::chrono::high_resolution_clock::now(); + double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count(); + inferCostTimeMilliSec += costMs; + if (ret != APP_ERR_OK) { + LogError << "Inference failed, ret=" << ret << "."; + return ret; + } + std::vector<std::vector<MxBase::ClassInfo>> BatchClsInfos = {}; + ret = PostProcess(outputs, &BatchClsInfos); + if (ret != APP_ERR_OK) { + LogError << "PostProcess failed, ret=" << ret << "."; + return ret; + } + ret = SaveResult(imgPath, &BatchClsInfos); + if (ret != APP_ERR_OK) { + LogError << "Save infer results into file failed. ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} diff --git a/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.h b/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.h new file mode 100644 index 0000000000000000000000000000000000000000..6f81ab78000a7b1d5799ee1e314039290fd21305 --- /dev/null +++ b/official/cv/inceptionv3/infer/mxbase/src/InceptionV3.h @@ -0,0 +1,65 @@ +/* + * Copyright 2021 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. + */ + +#ifndef MXBASE_INCEPTIONV3_H +#define MXBASE_INCEPTIONV3_H + +#include <string> +#include <vector> +#include <memory> +#include <opencv2/opencv.hpp> +#include "MxBase/DvppWrapper/DvppWrapper.h" +#include "MxBase/ModelInfer/ModelInferenceProcessor.h" +#include "MxBase/Tensor/TensorContext/TensorContext.h" +#include "ClassPostProcessors/Resnet50PostProcess.h" + +struct InitParam { + uint32_t deviceId; + std::string labelPath; + uint32_t classNum; + uint32_t topk; + bool softmax; + bool checkTensor; + std::string modelPath; +}; + +class InceptionV3 { + public: + APP_ERROR Init(const InitParam &initParam); + APP_ERROR DeInit(); + void ReadImage(const std::string &imgPath, cv::Mat *imageMat); + void ResizeImage(const cv::Mat &srcImageMat, cv::Mat *dstImageMat); + APP_ERROR CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase *tensorBase); + APP_ERROR Inference(const std::vector<MxBase::TensorBase> &inputs, + std::vector<MxBase::TensorBase> *outputs); + APP_ERROR PostProcess(const std::vector<MxBase::TensorBase> &inputs, + std::vector<std::vector<MxBase::ClassInfo>> *clsInfos); + APP_ERROR Process(const std::string &imgPath); + double GetInferCostMilliSec() const {return inferCostTimeMilliSec;} + + private: + APP_ERROR SaveResult(const std::string &imgPath, + std::vector<std::vector<MxBase::ClassInfo>> *batchClsInfos); + + private: + std::shared_ptr<MxBase::ModelInferenceProcessor> model_; + std::shared_ptr<MxBase::Resnet50PostProcess> post_; + MxBase::ModelDesc modelDesc_; + uint32_t deviceId_ = 0; + double inferCostTimeMilliSec = 0.0; +}; + +#endif diff --git a/official/cv/inceptionv3/infer/mxbase/src/main.cpp b/official/cv/inceptionv3/infer/mxbase/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9910d9dc98352678bff7373cebd446c9bb5a0ddc --- /dev/null +++ b/official/cv/inceptionv3/infer/mxbase/src/main.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2021 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. + */ + +#include <dirent.h> +#include "InceptionV3.h" +#include "MxBase/Log/Log.h" + +namespace { + const uint32_t CLASS_NUM = 1000; +} // namespace + +APP_ERROR ScanImages(const std::string &path, std::vector<std::string> *imgFiles) { + DIR *dirPtr = opendir(path.c_str()); + if (dirPtr == nullptr) { + LogError << "opendir failed. dir:" << path; + return APP_ERR_INTERNAL_ERROR; + } + dirent *direntPtr = nullptr; + while ((direntPtr = readdir(dirPtr)) != nullptr) { + std::string fileName = direntPtr->d_name; + if (fileName == "." || fileName == "..") { + continue; + } + + imgFiles->push_back(path + "/" + fileName); + } + closedir(dirPtr); + return APP_ERR_OK; +} + +int main(int argc, char* argv[]) { + if (argc <= 1) { + LogWarn << "Please input image path, such as './inceptionv3 image_dir'."; + return APP_ERR_OK; + } + + InitParam initParam = {}; + initParam.deviceId = 0; + initParam.classNum = CLASS_NUM; + initParam.labelPath = "../data/config/imagenet1000_clsidx_to_labels.names"; + initParam.topk = 5; + initParam.softmax = false; + initParam.checkTensor = true; + initParam.modelPath = "../data/models/inceptionv3.om"; + auto inferInceptionv3 = std::make_shared<InceptionV3>(); + APP_ERROR ret = inferInceptionv3->Init(initParam); + if (ret != APP_ERR_OK) { + inferInceptionv3->DeInit(); + LogError << "InceptionV3Classify init failed, ret=" << ret << "."; + return ret; + } + + std::string imgPath = argv[1]; + std::vector<std::string> imgFilePaths; + ret = ScanImages(imgPath, &imgFilePaths); + if (ret != APP_ERR_OK) { + inferInceptionv3->DeInit(); + return ret; + } + for (auto &imgFile : imgFilePaths) { + ret = inferInceptionv3->Process(imgFile); + if (ret != APP_ERR_OK) { + LogError << "InceptionV3 Classify process failed, ret=" << ret << "."; + inferInceptionv3->DeInit(); + return ret; + } + } + inferInceptionv3->DeInit(); + double fps = 1000.0 * imgFilePaths.size() / inferInceptionv3->GetInferCostMilliSec(); + LogInfo << " ms\tfps: " << fps << " imgs/sec"; + return APP_ERR_OK; +} diff --git a/official/cv/inceptionv3/infer/sdk/classification_task_metric.py b/official/cv/inceptionv3/infer/sdk/classification_task_metric.py new file mode 100644 index 0000000000000000000000000000000000000000..4fdf1ec2b3c16a4129b52cc388fe7cadb1a34f2f --- /dev/null +++ b/official/cv/inceptionv3/infer/sdk/classification_task_metric.py @@ -0,0 +1,137 @@ +#coding = utf-8 +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the BSD 3-Clause License (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://opensource.org/licenses/BSD-3-Clause +# +# 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 os +import sys +import json +import numpy as np + +np.set_printoptions(threshold=sys.maxsize) + +LABEL_FILE = "HiAI_label.json" + + +def gen_file_name(img_name): + full_name = img_name.split('/')[-1] + return os.path.splitext(full_name) + + +def cre_groundtruth_dict_fromtxt(gtfile_path): + img_gt_dict = {} + with open(gtfile_path, 'r')as f: + for line in f.readlines(): + temp = line.strip().split(" ") + img_name = temp[0].split(".")[0] + img_lab = temp[1] + img_gt_dict[img_name] = img_lab + return img_gt_dict + + +def load_statistical_predict_result(filepath): + with open(filepath, 'r')as f: + data = f.readline() + temp = data.strip().split(" ") + n_label = len(temp) + data_vec = np.zeros((n_label), dtype=np.float32) + if n_label != 0: + for ind, cls_ind in enumerate(temp): + data_vec[ind] = np.int_(cls_ind) + return data_vec, n_label + + +def create_visualization_statistical_result(prediction_file_path, + result_store_path, _json_file_name, + img_gt_dict, topn=5): + writer = open(os.path.join(result_store_path, _json_file_name), 'w') + table_dict = {} + table_dict["title"] = "Overall statistical evaluation" + table_dict["value"] = [] + + count = 0 + res_cnt = 0 + n_labels = "" + count_hit = np.zeros(topn) + for tfile_name in os.listdir(prediction_file_path): + count += 1 + temp = tfile_name.split('.')[0] + index = temp.rfind('_') + img_name = temp[:index] + filepath = os.path.join(prediction_file_path, tfile_name) + + ret = load_statistical_predict_result(filepath) + prediction = ret[0] + n_labels = ret[1] + + gt = img_gt_dict[img_name] + if n_labels == 1000: + real_label = int(gt) + elif n_labels == 1001: + real_label = int(gt) + 1 + else: + real_label = int(gt) + + res_cnt = min(len(prediction), topn) + for i in range(res_cnt): + if str(real_label) == str(int(prediction[i])): + count_hit[i] += 1 + break + if 'value' not in table_dict.keys(): + print("the item value does not exist!") + else: + table_dict["value"].extend( + [{"key": "Number of images", "value": str(count)}, + {"key": "Number of classes", "value": str(n_labels)}]) + if count == 0: + accuracy = 0 + else: + accuracy = np.cumsum(count_hit) / count + for i in range(res_cnt): + table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy", + "value": str( + round(accuracy[i] * 100, 2)) + '%'}) + json.dump(table_dict, writer) + writer.close() + + +if __name__ == '__main__': + try: + # txt file path + folder_davinci_target = sys.argv[1] + # annotation files path, "val_label.txt" + annotation_file_path = sys.argv[2] + # the path to store the results json path + result_json_path = sys.argv[3] + # result json file name + json_file_name = sys.argv[4] + except IndexError: + print("Please enter target file result folder | ground truth label file | result json file folder | " + "result json file name, such as ./result val_label.txt . result.json") + exit(1) + + if not os.path.exists(folder_davinci_target): + print("Target file folder does not exist.") + + if not os.path.exists(annotation_file_path): + print("Ground truth file does not exist.") + + if not os.path.exists(result_json_path): + print("Result folder doesn't exist.") + + img_label_dict = cre_groundtruth_dict_fromtxt(annotation_file_path) + create_visualization_statistical_result(folder_davinci_target, + result_json_path, json_file_name, + img_label_dict, topn=5) + \ No newline at end of file diff --git a/official/cv/inceptionv3/infer/sdk/inceptionv3.pipeline b/official/cv/inceptionv3/infer/sdk/inceptionv3.pipeline new file mode 100644 index 0000000000000000000000000000000000000000..834b66165ce4edcb37132d03c20e5983caff35b6 --- /dev/null +++ b/official/cv/inceptionv3/infer/sdk/inceptionv3.pipeline @@ -0,0 +1,64 @@ +{ + "im_inceptionv3": { + "stream_config": { + "deviceId": "0" + }, + "appsrc1": { + "props": { + "blocksize": "409600" + }, + "factory": "appsrc", + "next": "mxpi_imagedecoder0" + }, + "mxpi_imagedecoder0": { + "props": { + "handleMethod": "opencv" + }, + "factory": "mxpi_imagedecoder", + "next": "mxpi_imageresize0" + }, + "mxpi_imageresize0": { + "props": { + "handleMethod": "opencv", + "resizeType": "Resizer_Stretch", + "resizeHeight": "299", + "resizeWidth": "299" + }, + "factory": "mxpi_imageresize", + "next": "mxpi_tensorinfer0" + }, + "mxpi_tensorinfer0": { + "props": { + "dataSource": "mxpi_imageresize0", + "modelPath": "../data/models/inceptionv3.om", + "waitingTime": "2000", + "outputDeviceId": "-1" + }, + "factory": "mxpi_tensorinfer", + "next": "mxpi_classpostprocessor0" + }, + "mxpi_classpostprocessor0": { + "props": { + "dataSource": "mxpi_tensorinfer0", + "postProcessConfigPath": "../data/config/inceptionv3.cfg", + "labelPath": "../data/config/imagenet1000_clsidx_to_labels.names", + "postProcessLibPath": "libresnet50postprocess.so" + }, + "factory": "mxpi_classpostprocessor", + "next": "mxpi_dataserialize0" + }, + "mxpi_dataserialize0": { + "props": { + "outputDataKeys": "mxpi_classpostprocessor0" + }, + "factory": "mxpi_dataserialize", + "next": "appsink0" + }, + "appsink0": { + "props": { + "blocksize": "4096000" + }, + "factory": "appsink" + } + } +} diff --git a/official/cv/inceptionv3/infer/sdk/main.py b/official/cv/inceptionv3/infer/sdk/main.py new file mode 100644 index 0000000000000000000000000000000000000000..384b607d50fe900983547c66e1844394d222f10d --- /dev/null +++ b/official/cv/inceptionv3/infer/sdk/main.py @@ -0,0 +1,94 @@ +# Copyright 2021 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. +# ============================================================================ + +import datetime +import json +import os +import sys + +from StreamManagerApi import StreamManagerApi +from StreamManagerApi import MxDataInput + +def inference(): + # init stream manager + stream_manager_api = StreamManagerApi() + ret = stream_manager_api.InitManager() + if ret != 0: + print("Failed to init Stream manager, ret=%s" % str(ret)) + return + + # create streams by pipeline config file + with open("inceptionv3.pipeline", 'rb') as f: + pipelineStr = f.read() + ret = stream_manager_api.CreateMultipleStreams(pipelineStr) + + if ret != 0: + print("Failed to create Stream, ret=%s" % str(ret)) + return + + # Construct the input of the stream + data_input = MxDataInput() + dir_name = sys.argv[1] + res_dir_name = sys.argv[2] + file_list = os.listdir(dir_name) + if not os.path.exists(res_dir_name): + os.makedirs(res_dir_name) + + for file_name in file_list: + file_path = os.path.join(dir_name, file_name) + if not (file_name.lower().endswith(".jpg") or file_name.lower().endswith(".jpeg")): + continue + + with open(file_path, 'rb') as f: + data_input.data = f.read() + + stream_name = b'im_inceptionv3' + in_plugin_id = 0 + unique_id = stream_manager_api.SendData(stream_name, in_plugin_id, data_input) + if unique_id < 0: + print("Failed to send data to stream.") + exit() + # Obtain the inference result by specifying streamName and uniqueId. + start_time = datetime.datetime.now() + infer_result = stream_manager_api.GetResult(stream_name, unique_id) + end_time = datetime.datetime.now() + print('sdk run time: {}'.format((end_time - start_time).microseconds)) + if infer_result.errorCode != 0: + print("GetResultWithUniqueId error. errorCode=%d, errorMsg=%s" % ( + infer_result.errorCode, infer_result.data.decode())) + exit() + # print the infer result + infer_res = infer_result.data.decode() + print("process img: {}, infer result: {}".format(file_name, infer_res)) + + load_dict = json.loads(infer_result.data.decode()) + if load_dict.get('MxpiClass') is None: + dot = file_name.find_last_of(".") + with open(os.path.join(res_dir_name, '{}.txt'.format(file_name.substr(0, dot))), 'w') as f_write: + f_write.write("") + continue + res_vec = load_dict.get('MxpiClass') + + with open(os.path.join(res_dir_name, '{}_1.txt'.format(file_name[:-5])), 'w') as f_write: + res_list = [str(item.get("classId")) + " " for item in res_vec] + f_write.writelines(res_list) + f_write.write('\n') + + # destroy streams + stream_manager_api.DestroyAllStreams() + + +if __name__ == '__main__': + inference() diff --git a/official/cv/inceptionv3/infer/sdk/run.sh b/official/cv/inceptionv3/infer/sdk/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..855d58a2f24552bdad1063fb19c5d758a4788bfd --- /dev/null +++ b/official/cv/inceptionv3/infer/sdk/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Copyright 2021 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. +image_path=$1 +result_dir=$2 + +set -e + +# Simple log helper functions +info() { echo -e "\033[1;34m[INFO ][MxStream] $1\033[1;37m" ; } +warn() { echo >&2 -e "\033[1;31m[WARN ][MxStream] $1\033[1;37m" ; } + +python3.7 main.py $image_path $result_dir +exit 0 \ No newline at end of file diff --git a/official/cv/inceptionv3/modelarts/train_start.py b/official/cv/inceptionv3/modelarts/train_start.py new file mode 100644 index 0000000000000000000000000000000000000000..b4db0ea4747b476260f069cb8c2d0f7349b2ae44 --- /dev/null +++ b/official/cv/inceptionv3/modelarts/train_start.py @@ -0,0 +1,194 @@ +# Copyright 2021 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. +# ============================================================================ +"""inceptionv3 train""" +import os +import argparse +import glob +import moxing as mox +import numpy as np +import mindspore as ms +from mindspore import Model +from mindspore import Tensor +from mindspore import context +from mindspore.common import set_seed +from mindspore.common.initializer import XavierUniform, initializer +from mindspore.communication import init, get_rank, get_group_size +from mindspore.nn import RMSProp +from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, TimeMonitor, LossMonitor +from mindspore.train.loss_scale_manager import FixedLossScaleManager +from mindspore.train.model import ParallelMode +from mindspore.train.serialization import load_checkpoint, load_param_into_net +from mindspore import export +from src.model_utils.config import config +from src.model_utils.device_adapter import get_device_id, get_device_num +from src.dataset import create_dataset_imagenet, create_dataset_cifar10 +from src.inception_v3 import InceptionV3 +from src.loss import CrossEntropy +from src.lr_generator import get_lr + + +set_seed(1) +DS_DICT = { + "imagenet": create_dataset_imagenet, + "cifar10": create_dataset_cifar10, +} + +config.device_id = get_device_id() +config.device_num = get_device_num() +device_num = config.device_num +create_dataset = DS_DICT[config.ds_type] + +parser = argparse.ArgumentParser(description='Image classification') +parser.add_argument("--filter_weight", type=str, default=True, help="Filter head weight parameters, default is True.") +parser.add_argument('--data_url', metavar='DIR', default='/cache/data_url', help='path to dataset') +parser.add_argument('--train_url', default="/cache/output/", type=str, help="setting dir of training output") +parser.add_argument('--resume', default="", type=str, help="resume training with existed checkpoint") +parser.add_argument('--ds_type', default="imagenet", type=str, help="dataset type, imagenet or cifar10") +parser.add_argument('--num_classes', default="1000", type=int, help="classes") +parser.add_argument('--epoch_size', default="250", type=int, help="epoch_size") +parser.add_argument('--batch_size', default="128", type=int, help="batch_size") +args_opt = parser.parse_args() + +def filter_checkpoint_parameter_by_list(origin_dict, param_filter): + """remove useless parameters according to filter_list""" + for key in list(origin_dict.keys()): + for name in param_filter: + if name in key: + print("Delete parameter from checkpoint: ", key) + del origin_dict[key] + break + + +def frozen_to_air(network, args): + param_dict_t = load_checkpoint(args.get("ckpt_file")) + load_param_into_net(network, param_dict_t) + input_arr = Tensor(np.random.uniform(0.0, 1.0, size=[args.get("batch_size"), 3, args.get("width"), \ + args.get("height")]), ms.float32) + export(network, input_arr, file_name=args.get("file_name"), file_format=args.get("file_format")) + + +if __name__ == '__main__': + if not os.path.exists(config.data_path): + os.makedirs(config.data_path, exist_ok=True) + if not os.path.exists(config.load_path): + os.makedirs(config.load_path, exist_ok=True) + if not os.path.exists(config.output_path): + os.makedirs(config.output_path, exist_ok=True) + mox.file.copy_parallel(args_opt.data_url, config.data_path) + + config.class_num = args_opt.num_classes + config.epoch_size = args_opt.epoch_size + config.batch_size = args_opt.batch_size + config.resume = os.path.join(config.dataset_path, args_opt.resume) + config.dataset_path = os.path.join(config.dataset_path, "train") + + if config.platform == "GPU": + context.set_context(enable_graph_kernel=True) + + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, save_graphs=False) + if os.getenv('DEVICE_ID', "not_set").isdigit(): + context.set_context(device_id=int(os.getenv('DEVICE_ID'))) + + # init distributed + if config.is_distributed: + init() + config.rank = get_rank() + config.group_size = get_group_size() + parallel_mode = ParallelMode.DATA_PARALLEL + context.set_auto_parallel_context(parallel_mode=parallel_mode, device_num=config.group_size, + gradients_mean=True) + else: + config.rank = 0 + config.group_size = 1 + + # dataloader + dataset = create_dataset(config.dataset_path, True, config) + batches_per_epoch = dataset.get_dataset_size() + + # network + net = InceptionV3(num_classes=config.num_classes, dropout_keep_prob=config.dropout_keep_prob, \ + has_bias=config.has_bias) + + # loss + loss = CrossEntropy(smooth_factor=config.smooth_factor, num_classes=config.num_classes, factor=config.aux_factor) + + # learning rate schedule + lr = get_lr(lr_init=config.lr_init, lr_end=config.lr_end, lr_max=config.lr_max, warmup_epochs=config.warmup_epochs, + total_epochs=config.epoch_size, steps_per_epoch=batches_per_epoch, lr_decay_mode=config.decay_method) + lr = Tensor(lr) + + # optimizer + decayed_params = [] + no_decayed_params = [] + for param in net.trainable_params(): + if 'beta' not in param.name and 'gamma' not in param.name and 'bias' not in param.name: + decayed_params.append(param) + else: + no_decayed_params.append(param) + + if config.platform == "Ascend": + for param in net.trainable_params(): + if 'beta' not in param.name and 'gamma' not in param.name and 'bias' not in param.name: + param.set_data(initializer(XavierUniform(), param.data.shape, param.data.dtype)) + group_params = [{'params': decayed_params, 'weight_decay': config.weight_decay}, + {'params': no_decayed_params}, + {'order_params': net.trainable_params()}] + optimizer = RMSProp(group_params, lr, decay=0.9, weight_decay=config.weight_decay, + momentum=config.momentum, epsilon=config.opt_eps, loss_scale=config.loss_scale) + + if args_opt.resume: + ckpt = load_checkpoint(config.resume) + if args_opt.filter_weight: + filter_list = [x.name for x in net.logits.get_parameters()] + filter_checkpoint_parameter_by_list(ckpt, filter_list) + load_param_into_net(net, ckpt) + if config.platform == "Ascend": + loss_scale_manager = FixedLossScaleManager(config.loss_scale, drop_overflow_update=False) + model = Model(net, loss_fn=loss, optimizer=optimizer, metrics={'acc'}, amp_level=config.amp_level, + loss_scale_manager=loss_scale_manager) + else: + model = Model(net, loss_fn=loss, optimizer=optimizer, metrics={'acc'}, amp_level=config.amp_level) + + print("============== Starting Training ==============") + loss_cb = LossMonitor(per_print_times=batches_per_epoch) + time_cb = TimeMonitor(data_size=batches_per_epoch) + callbacks = [loss_cb, time_cb] + config_ck = CheckpointConfig(save_checkpoint_steps=batches_per_epoch, \ + keep_checkpoint_max=config.keep_checkpoint_max) + ckpoint_cb = ModelCheckpoint(prefix=f"inceptionv3-rank{config.rank}", \ + directory=config.output_path, config=config_ck) + if config.is_distributed & config.is_save_on_master: + if config.rank == 0: + callbacks.append(ckpoint_cb) + model.train(config.epoch_size, dataset, callbacks=callbacks, dataset_sink_mode=config.ds_sink_mode) + else: + callbacks.append(ckpoint_cb) + model.train(config.epoch_size, dataset, callbacks=callbacks, dataset_sink_mode=config.ds_sink_mode) + ckpt_list = glob.glob(config.output_path + "/inceptionv3*.ckpt") + if not ckpt_list: + print("ckpt file not generated.") + + ckpt_list.sort(key=os.path.getmtime) + ckpt_model = ckpt_list[-1] + print("checkpoint path", ckpt_model) + + net = InceptionV3(num_classes=config.num_classes, dropout_keep_prob=config.dropout_keep_prob, \ + has_bias=config.has_bias) + + frozen_to_air_args = {'ckpt_file': ckpt_model, 'batch_size': 1, 'height': 299, 'width': 299, + 'file_name': config.output_path + '/inceptionv3', 'file_format': 'AIR'} + frozen_to_air(net, frozen_to_air_args) + mox.file.copy_parallel(config.output_path, args_opt.train_url) + print("train success") diff --git a/official/cv/inceptionv3/scripts/docker_start.sh b/official/cv/inceptionv3/scripts/docker_start.sh new file mode 100644 index 0000000000000000000000000000000000000000..a033c3e3d5f6d0032397f027c2e2d9427429fa3d --- /dev/null +++ b/official/cv/inceptionv3/scripts/docker_start.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright 2021 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.mitations under the License. + +docker_image=$1 +data_dir=$2 +model_dir=$3 + +docker run -it --ipc=host \ + --device=/dev/davinci0 \ + --device=/dev/davinci1 \ + --device=/dev/davinci2 \ + --device=/dev/davinci3 \ + --device=/dev/davinci4 \ + --device=/dev/davinci5 \ + --device=/dev/davinci6 \ + --device=/dev/davinci7 \ + --device=/dev/davinci_manager \ + --device=/dev/devmm_svm --device=/dev/hisi_hdc \ + -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ + -v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \ + -v ${model_dir}:${model_dir} \ + -v ${data_dir}:${data_dir} \ + -v /root/ascend/log:/root/ascend/log ${docker_image} /bin/bash