diff --git a/.jenkins/check/config/filter_cpplint.txt b/.jenkins/check/config/filter_cpplint.txt
index ba47bdc44cc888b46fd5d692270ee63842772b9e..2622a92004a0eba7417487086a53bf0ccf1f789d 100644
--- a/.jenkins/check/config/filter_cpplint.txt
+++ b/.jenkins/check/config/filter_cpplint.txt
@@ -3,6 +3,6 @@
"models/" "build/c++11"
# Modelzoo
-"mindspore/model_zoo/official/cv/yolov4_tiny/infer/mxbase/src/Yolov4TinyDetection.h" "runtime/references"
-"mindspore/model_zoo/official/cv/yolov4_tiny/infer/mxbase/src/PostProcess/Yolov4TinyMindsporePost.h" "runtime/references"
-"mindspore/model_zoo/official/cv/resnet/infer/ResNet18/mxbase/Resnet18ClassifyOpencv.h" "runtime/references"
+"models/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.h" "runtime/references"
+"models/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.cpp" "runtime/references"
+"models/research/cv/FaceRecognition/infer/mxbase/facerecognition/main_opencv.cpp" "runtime/references"
diff --git a/research/cv/FaceRecognition/default_config.yaml b/research/cv/FaceRecognition/default_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5c1a32f8acaf2f4483a78fa805cb0a8be95fd9a4
--- /dev/null
+++ b/research/cv/FaceRecognition/default_config.yaml
@@ -0,0 +1,102 @@
+# Builtin Configurations(DO NOT CHANGE THESE CONFIGURATIONS unless you know exactly what you are doing)
+enable_modelarts: False
+# Url for modelarts
+data_url: ""
+train_url: ""
+checkpoint_url: ""
+# Path for local
+data_path: "/cache/data"
+output_path: "/cache/train"
+load_path: "/cache/checkpoint_path"
+device_target: "Ascend"
+enable_profiling: False
+
+# ==============================================================================
+# Training options
+train_stage: "base"
+is_distributed: 1
+
+# dataset related
+data_dir: "/cache/data/face_recognition_dataset/train_dataset/"
+num_classes: 1
+per_batch_size: 192
+need_modelarts_dataset_unzip: True
+
+# network structure related
+backbone: "r100"
+use_se: 1
+emb_size: 512
+act_type: "relu"
+fp16: 1
+pre_bn: 1
+inference: 0
+use_drop: 1
+nc_16: 1
+
+# loss related
+margin_a: 1.0
+margin_b: 0.2
+margin_m: 0.3
+margin_s: 64
+
+# optimizer related
+lr: 0.4
+lr_scale: 1
+lr_epochs: "8,14,18"
+weight_decay: 0.0002
+momentum: 0.9
+max_epoch: 20
+pretrained: ""
+warmup_epochs: 2
+
+# distributed parameter
+local_rank: 0
+world_size: 1
+model_parallel: 0
+
+# logging related
+log_interval: 100
+ckpt_path: "outputs"
+max_ckpts: -1
+dynamic_init_loss_scale: 65536
+ckpt_steps: 1000
+
+# export option
+batch_size: 16
+file_name: "facerecognition"
+file_format: "AIR"
+export_pre_bn: 0
+export_inference: 1
+export_use_se: 0
+export_emb_size: 512
+export_act_type: "relu"
+export_backbone: "r100"
+export_use_drop: 0
+head: "0"
+
+---
+
+# Help description for each configuration
+enable_modelarts: "Whether training on modelarts, default: False"
+data_url: "Url for modelarts"
+train_url: "Url for modelarts"
+data_path: "The location of the input data."
+output_path: "The location of the output file."
+device_target: 'Target device type'
+enable_profiling: 'Whether enable profiling while training, default: False'
+
+train_stage: "Train stage, base or beta"
+is_distributed: "If multi device"
+
+# export option
+batch_size: "batch size"
+file_name: "file name"
+file_format: "file format, choices in ['MINDIR', 'AIR']"
+export_pre_bn: "1: bn-conv-bn-conv-bn, 0: conv-bn-conv-bn"
+export_inference: "use inference backbone"
+export_use_se: "use se block or not"
+export_emb_size: "embedding size of the network"
+export_act_type: "activation layer type"
+export_backbone: "backbone network"
+export_use_drop: "whether use dropout in network"
+head: "head type, default is 0"
\ No newline at end of file
diff --git a/research/cv/FaceRecognition/infer/Dockerfile b/research/cv/FaceRecognition/infer/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..360861ede17fb0ab697fbcac190acde7c1e29fef
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/Dockerfile
@@ -0,0 +1,5 @@
+ARG FROM_IMAGE_NAME
+FROM ${FROM_IMAGE_NAME}
+
+COPY requirements.txt .
+RUN pip3.7 install -r requirements.txt
diff --git a/research/cv/FaceRecognition/infer/convert/aipp.config b/research/cv/FaceRecognition/infer/convert/aipp.config
new file mode 100644
index 0000000000000000000000000000000000000000..7e13e4e29f60301164090ea06b74f019c3abbf50
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/convert/aipp.config
@@ -0,0 +1,15 @@
+aipp_op{
+ aipp_mode: static
+ src_image_size_w:112
+ src_image_size_h:112
+ input_format : RGB888_U8
+ csc_switch: false
+ rbuv_swap_switch : false
+
+ min_chn_0 : 127.5
+ min_chn_1 : 127.5
+ min_chn_2 : 127.5
+ var_reci_chn_0: 0.00784314
+ var_reci_chn_1: 0.00784314
+ var_reci_chn_2: 0.00784314
+}
diff --git a/research/cv/FaceRecognition/infer/convert/air2om.sh b/research/cv/FaceRecognition/infer/convert/air2om.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3fae4f76d60f0642ec985d4cfa192992b0f143f7
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/convert/air2om.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#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.
+
+model_path=$1
+output_model_name=$2
+
+/usr/local/Ascend/atc/bin/atc \
+--model=$model_path \
+--framework=1 \
+--output=$output_model_name \
+--input_format=NCHW \
+--input_shape="actual_input_1:1,3,112,112" \
+--soc_version=Ascend310 \
+--insert_op_conf=./aipp.config \
+--output_type=FP32
diff --git a/research/cv/FaceRecognition/infer/docker_start_infer.sh b/research/cv/FaceRecognition/infer/docker_start_infer.sh
new file mode 100644
index 0000000000000000000000000000000000000000..64cf90a2311bdfb21d68a4e90e08602670fdf632
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/docker_start_infer.sh
@@ -0,0 +1,48 @@
+#!/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
+data_dir=$2
+
+function show_help() {
+ echo "Usage: docker_start.sh docker_image data_dir"
+}
+
+function param_check() {
+ if [ -z "${docker_image}" ]; then
+ echo "please input docker_image"
+ show_help
+ exit 1
+ fi
+
+ if [ -z "${data_dir}" ]; then
+ echo "please input data_dir"
+ show_help
+ exit 1
+ fi
+}
+
+param_check
+
+docker run -it \
+ --device=/dev/davinci0 \
+ --device=/dev/davinci_manager \
+ --device=/dev/devmm_svm \
+ --device=/dev/hisi_hdc \
+ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
+ -v ${data_dir}:${data_dir} \
+ ${docker_image} \
+ /bin/bash
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/CMakeLists.txt b/research/cv/FaceRecognition/infer/mxbase/facerecognition/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a065fc748bf1ef96563d46190a1ce9bc126037f6
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.5.2)
+project(resnet50)
+add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+add_definitions(-DENABLE_DVPP_INTERFACE)
+set(TARGET resnet)
+set(ACL_LIB_PATH $ENV{ASCEND_HOME}/nnrt/latest/acllib)
+set(ACL_INC_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/$ENV{ARCH_PATTERN}/acllib/include)
+set(MXBASE_ROOT_DIR $ENV{MX_SDK_HOME})
+set(MXBASE_INC ${MXBASE_ROOT_DIR}/src/include)
+set(MXBASE_LIB_DIR ${MXBASE_ROOT_DIR}/dist/lib)
+set(MXBASE_POST_LIB_DIR ${MXBASE_ROOT_DIR}/dist/lib/modelpostprocessors)
+set(MXBASE_POST_PROCESS_DIR ${MXBASE_ROOT_DIR}/postprocess/include)
+if(DEFINED ENV{MXSDK_OPENSOURCE_DIR})
+ set(OPENSOURCE_DIR $ENV{MXSDK_OPENSOURCE_DIR})
+else()
+ set(OPENSOURCE_DIR ${MXBASE_ROOT_DIR}/opensource/dist)
+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})
+
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+include_directories($ENV{MX_SDK_HOME}/include)
+include_directories($ENV{MX_SDK_HOME}/opensource/include)
+include_directories($ENV{MX_SDK_HOME}/opensource/include/opencv4)
+include_directories($ENV{MX_SDK_HOME}/opensource/include/gstreamer-1.0)
+include_directories($ENV{MX_SDK_HOME}/opensource/include/opencv4/)
+include_directories($ENV{MX_SDK_HOME}/opensource/include/)
+include_directories("/usr/local/Ascend/nnrt/5.0.1/x86_64-linux/acllib/include/")
+include_directories($ENV{MX_SDK_HOME}/include/MxBase/postprocess/include/)
+link_directories($ENV{MX_SDK_HOME}/lib/)
+link_directories($ENV{MX_SDK_HOME}/opensource/lib/)
+link_directories($ENV{MX_SDK_HOME}/lib/modelpostprocessors)
+
+add_compile_options(-std=c++11 -fPIC -fstack-protector-all -pie -Wno-deprecated-declarations)
+add_compile_options("-DPLUGIN_NAME=${PLUGIN_NAME}")
+add_compile_options("-Dgoogle=mindxsdk_private")
+
+add_definitions(-DENABLE_DVPP_INTERFACE)
+
+include_directories(${ACL_LIB_PATH}/include)
+link_directories(${ACL_LIB_PATH}/lib64/)
+
+message("TARGET_LIBRARY:${TARGET_LIBRARY}.")
+
+
+add_executable(${TARGET} main_opencv.cpp FaceRecognition.cpp)
+target_link_libraries(${TARGET} glog cpprest mxbase libascendcl.so resnet50postprocess opencv_world)
\ No newline at end of file
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.cpp b/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b515a78eec64ae8a11919b2e8ec9852e6388742a
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.cpp
@@ -0,0 +1,532 @@
+/*
+ * 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 <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <map>
+#include <memory>
+#include "FaceRecognition.h"
+#include "MxBase/DeviceManager/DeviceManager.h"
+#include "MxBase/Log/Log.h"
+
+namespace {
+ const uint32_t YUV_BYTE_NU = 3;
+ const uint32_t YUV_BYTE_DE = 2;
+ const uint32_t VPC_H_ALIGN = 2;
+ const int emb_size = 256;
+}
+
+union Fp32 {
+ uint32_t u;
+ float f;
+};
+
+// calculate the acc
+std::vector<int> FaceRecognition::cal_topk(int idx, std::string str_zj,
+std::map<std::string, std::vector<std::string> >& zj2jk_pairs,
+std::map<std::string, std::vector<float> >& test_embedding_tot,
+std::vector<std::vector<float> >& dis_embedding_tot_np,
+const std::map<int, std::vector<std::vector<float> > >& jk_all_embedding,
+std::vector<std::string>& dis_label) {
+ std::ofstream zj_outfile;
+ std::ofstream jk_outfile;
+ std::vector<int>correct(2, 0);
+
+ std::vector<std::string>jk_all = zj2jk_pairs[str_zj];
+ std::vector<float>zj_embedding = test_embedding_tot[str_zj];
+ std::vector<float>mm(dis_embedding_tot_np.size(), 0);
+ float mm_max = FLT_MIN;
+ int zj_index = 0;
+
+ for (int i = 0; i < dis_embedding_tot_np.size(); i++) {
+ for (int j = 0; j < zj_embedding.size(); j++) {
+ mm[i] += zj_embedding[j]*dis_embedding_tot_np[i][j];
+ }
+ if (mm_max < mm[i]) {
+ mm_max = mm[i];
+ zj_index = i;
+ }
+ }
+
+ std::vector<float>mm_max_jk_all(jk_all.size(), FLT_MIN);
+ std::vector<int>jk_index;
+
+ float sum;
+ for (int k = 0; k < jk_all.size(); k++) {
+ std::vector<float>jk_embedding = test_embedding_tot[jk_all[k]];
+ int index = 0;
+ for (int i = 0; i < dis_embedding_tot_np.size(); i++) {
+ sum = 0;
+ for (int j = 0; j < jk_embedding.size(); j++) {
+ sum += jk_embedding[j]*dis_embedding_tot_np[i][j];
+ }
+ if (mm_max_jk_all[k] < sum) {
+ mm_max_jk_all[k] = sum;
+ index = i;
+ }
+ }
+ jk_index.push_back(index);
+ }
+ // the first step is write the groundtruth to the zj and jk
+ zj_outfile.open("./zj_result.txt", std::ios::app);
+ jk_outfile.open("./jk_result.txt", std::ios::app);
+ for (int i = 0; i < jk_all.size(); i++) {
+ std::vector<float>jk_embedding = test_embedding_tot[jk_all[i]];
+ zj_outfile << str_zj << " ";
+ jk_outfile << jk_all[i] << " ";
+ // 22:23
+ float similarity = inner_product(jk_embedding.begin(), jk_embedding.end(), zj_embedding.begin(), 0.0);
+ if (similarity > mm_max) {
+ correct[0]++;
+ zj_outfile << str_zj << "\n";
+ } else {
+ zj_outfile << dis_label[zj_index] << "\n";
+ }
+ if (similarity > mm_max_jk_all[i]) {
+ jk_outfile << jk_all[i] << "\n";
+ correct[1]++;
+ } else {
+ jk_outfile << dis_label[jk_index[i]] << "\n";
+ }
+ // pass ci
+ test_embedding_tot[jk_all[i]] = jk_embedding;
+ }
+ // pass ci
+ zj2jk_pairs[str_zj] = jk_all;
+ std::string temp = dis_label[0];
+ dis_label[0] = temp;
+ zj_outfile.close();
+ jk_outfile.close();
+ return correct;
+}
+
+void FaceRecognition::l2normalize(std::vector<std::vector<float>>& out) {
+ std::vector<std::vector<float> >out_o(out.begin(), out.end());
+
+ float epsilon = 1e-12;
+ std::vector<float>out1(out.size(), 0);
+ for (int i = 0; i < out_o.size(); i++) {
+ for (int j = 0; j < 256; j++) {
+ out_o[i][j] = abs(out_o[i][j]);
+ out_o[i][j] = pow(out_o[i][j], 2);
+ out1[i] += out_o[i][j];
+ }
+ out1[i] = pow(out1[i], 0.5);
+ if (out1[i] < 0 && out1[i] > -epsilon) {
+ out1[i] = -epsilon;
+ } else if (out1[i] >= 0 && out1[i] < epsilon) {
+ out1[i] = epsilon;
+ }
+ }
+ for (int i = 0; i < out.size(); i++) {
+ for (int j = 0; j < 256; j++) {
+ out[i][j] = out[i][j]/out1[i];
+ }
+ }
+}
+
+int FaceRecognition::line_of_txt(std::string s) {
+ int count = 0;
+ std::ifstream fin(s);
+ std::string ss;
+ while (getline(fin, ss)) {
+ count++;
+ }
+ return count;
+}
+
+void FaceRecognition::deal_txt_img(std::string s, int& count, int batch_img, int out_vector_len,
+std::vector<std::vector<float>>& test_embedding_tot_np,
+std::map<std::string, std::vector<float>>& test_embedding_tot) {
+ std::ifstream fin(s);
+ std::string ss;
+ while (getline(fin, ss)) {
+ // read image
+ int pos = 0;
+ for (int i = 0; i < ss.size(); i++) {
+ if (ss[i] == ' ') {
+ pos = i;
+ break;
+ }
+ }
+ std::string imgPath = ss.substr(0, pos);
+
+ // put the tensor to the net, and get the output
+ std::vector<std::vector<float> >out(batch_img, std::vector<float>(out_vector_len, 1));
+ Process(imgPath, out);
+
+
+ // l2normalize
+ l2normalize(out);
+
+ // The result of regularization is stored in test_embedding_tot_np
+ test_embedding_tot_np[count] = out[0];
+ test_embedding_tot[ss] = test_embedding_tot_np[count];
+
+ count++;
+ }
+}
+
+void FaceRecognition::deal_txt_img_dis(std::string s, int& count, int batch_img, int out_vector_len,
+std::vector<std::vector<float>>& test_embedding_tot_np,
+std::map<std::string, std::vector<float>>& test_embedding_tot,
+std::vector<std::string>& dis_label) {
+ std::ifstream fin(s);
+ std::string ss;
+ while (getline(fin, ss)) {
+ std::string imgPath = ss;
+ // store the image path
+ dis_label.push_back(imgPath);
+ // put the tensor to the net, and get the output
+ std::vector<std::vector<float> >out(batch_img, std::vector<float>(out_vector_len, 1));
+ Process(imgPath, out);
+
+ // l2normalize
+ l2normalize(out);
+
+ // The result of regularization is stored in test_embedding_tot_np
+ test_embedding_tot_np[count] = out[0];
+ test_embedding_tot[ss] = test_embedding_tot_np[count];
+
+ count++;
+ }
+}
+
+std::string FaceRecognition::get_lable_num(std::string s) {
+ int pos = 0;
+ for (int i = 0; i < s.size(); i++) {
+ if (s[i] == ' ') {
+ pos = i;
+ break;
+ }
+ }
+ return s.substr(pos+1);
+}
+
+void FaceRecognition::txt_to_pair(std::map<std::string, std::vector<std::string>>& zj2jk_pairs,
+int img_tot_zj, int img_tot_jk, std::vector<int>& ID_nums,
+const std::string &zj_list_path, const std::string &jk_list_path) {
+ std::ifstream zjFile;
+ zjFile.open(zj_list_path);
+ std::string str_zj;
+ getline(zjFile, str_zj, '\n');
+ std::string lable_num = get_lable_num(str_zj);
+
+ std::ifstream jkFile;
+ jkFile.open(jk_list_path);
+ std::string str_jk;
+
+ int id_nums = 0;
+ for (int i = 0; i < img_tot_jk; i++) {
+ getline(jkFile, str_jk, '\n');
+ if (lable_num == get_lable_num(str_jk)) {
+ id_nums++;
+ zj2jk_pairs[str_zj].push_back(str_jk);
+ } else {
+ ID_nums.push_back(id_nums);
+ id_nums = 1;
+ getline(zjFile, str_zj, '\n');
+ lable_num = get_lable_num(str_zj);
+ zj2jk_pairs[str_zj].push_back(str_jk);
+ }
+ }
+ ID_nums.push_back(id_nums);
+}
+
+void FaceRecognition::get_jk_all_embedding(std::vector<int>& ID_nums,
+std::map<std::string, std::vector<float> >& test_embedding_tot, std::map<int,
+std::vector<std::vector<float> > >& jk_all_embedding, const std::string &jk_list_path) {
+ std::ifstream jkFile;
+ jkFile.open(jk_list_path);
+ std::string str_jk;
+ for (int idx = 0; idx < ID_nums.size(); idx++) {
+ for (int i = 0; i < ID_nums[idx]; i++) {
+ getline(jkFile, str_jk, '\n');
+ jk_all_embedding[idx].push_back(test_embedding_tot[str_jk]);
+ }
+ }
+}
+
+APP_ERROR FaceRecognition::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;
+ }
+ MxBase::ConfigData configData;
+ const std::string softmax = initParam.softmax ? "true" : "false";
+ const std::string checkTensor = initParam.checkTensor ? "true" : "false";
+
+ 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 FaceRecognition::DeInit() {
+ model_->DeInit();
+ post_->DeInit();
+ MxBase::DeviceManager::GetInstance()->DestroyDevices();
+ return APP_ERR_OK;
+}
+
+bool FaceRecognition::ReadImage(const std::string &imgPath, cv::Mat &imageMat) {
+ imageMat = cv::imread(imgPath, cv::IMREAD_COLOR);
+ if (!imageMat.empty()) {
+ return true;
+ }
+ return false;
+}
+
+APP_ERROR FaceRecognition::ResizeImage(const cv::Mat &srcImageMat, cv::Mat &dstImageMat) {
+ static constexpr uint32_t resizeHeight = 112;
+ static constexpr uint32_t resizeWidth = 112;
+
+ cv::resize(srcImageMat, dstImageMat, cv::Size(resizeWidth, resizeHeight));
+ return APP_ERR_OK;
+}
+
+APP_ERROR FaceRecognition::CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase) {
+ const uint32_t dataSize = imageMat.cols * imageMat.rows * MxBase::YUV444_RGB_WIDTH_NU;
+ MxBase::MemoryData memoryDataDst(dataSize, MxBase::MemoryData::MEMORY_DEVICE, deviceId_);
+ MxBase::MemoryData memoryDataSrc(imageMat.data, dataSize, MxBase::MemoryData::MEMORY_HOST_MALLOC);
+
+ APP_ERROR ret = MxBase::MemoryHelper::MxbsMallocAndCopy(memoryDataDst, memoryDataSrc);
+ if (ret != APP_ERR_OK) {
+ LogError << GetError(ret) << "Memory malloc failed.";
+ return ret;
+ }
+
+ std::vector<uint32_t> shape = {imageMat.rows * MxBase::YUV444_RGB_WIDTH_NU, static_cast<uint32_t>(imageMat.cols)};
+ tensorBase = MxBase::TensorBase(memoryDataDst, false, shape, MxBase::TENSOR_DTYPE_UINT8);
+ return APP_ERR_OK;
+}
+
+APP_ERROR FaceRecognition::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]);
+ }
+ MxBase::TensorBase tensor(shape, dtypes[i], MxBase::MemoryData::MemoryType::MEMORY_DEVICE, deviceId_);
+ APP_ERROR ret = MxBase::TensorBase::TensorBaseMalloc(tensor);
+ if (ret != APP_ERR_OK) {
+ LogError << "TensorBaseMalloc failed, ret=" << ret << ".";
+ return ret;
+ }
+ outputs.push_back(tensor);
+ }
+ MxBase::DynamicInfo dynamicInfo = {};
+ dynamicInfo.dynamicType = MxBase::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(); // save time
+ inferCostTimeMilliSec += costMs;
+ if (ret != APP_ERR_OK) {
+ LogError << "ModelInference failed, ret=" << ret << ".";
+ return ret;
+ }
+ return APP_ERR_OK;
+}
+
+float FaceRecognition::uint6_cov_float(uint16_t value) {
+ const Fp32 magic = { (254U - 15U) << 23 };
+ const Fp32 was_infnan = { (127U + 16U) << 23 };
+ Fp32 out;
+ out.u = (value & 0x7FFFU) << 13; /* exponent/mantissa bits */
+ out.f *= magic.f; /* exponent adjust */
+ if (out.f >= was_infnan.f) {
+ out.u |= 255U << 23;
+ }
+ out.u |= (value & 0x8000U) << 16; /* sign bit */
+ return out.f;
+}
+
+APP_ERROR FaceRecognition::PostProcess(std::vector<MxBase::TensorBase> &tensors,
+ std::vector<std::vector<float>> &out) {
+ APP_ERROR ret = APP_ERR_OK;
+ for (MxBase::TensorBase &input : tensors) {
+ ret = input.ToHost();
+ if (ret != APP_ERR_OK) {
+ LogError << "----------Error occur!!" << std::endl;
+ }
+ }
+ auto inputs = tensors;
+ if (ret != APP_ERR_OK) {
+ LogError << "CheckAndMoveTensors failed. ret=" << ret;
+ return ret;
+ }
+ const uint32_t softmaxTensorIndex = 0;
+ auto softmaxTensor = inputs[softmaxTensorIndex];
+ void *softmaxTensorPtr = softmaxTensor.GetBuffer();
+ uint32_t topk = 256;
+ std::vector<uint32_t> idx = {};
+ for (uint32_t j = 0; j < topk; j++) {
+ idx.push_back(j);
+ }
+ for (uint32_t j = 0; j < topk; j++) {
+ float value = *(static_cast<float *>(softmaxTensorPtr) + 0 * topk + j);
+ out[0][j] = value;
+ }
+ return APP_ERR_OK;
+}
+
+// Add another parameter out, passing in the outgoing parameter
+APP_ERROR FaceRecognition::Process(const std::string &imgPath, std::vector<std::vector<float>>& out) {
+ LogInfo << "processing ---------" << imgPath << std::endl;
+ // read image
+ cv::Mat imageMat;
+ bool readTrue = ReadImage(imgPath, imageMat);
+ if (!readTrue) {
+ LogError << "ReadImage failed!!!" << std::endl;
+ }
+ // resize image
+ ResizeImage(imageMat, imageMat);
+ std::vector<MxBase::TensorBase> inputs = {};
+ std::vector<MxBase::TensorBase> outputs = {};
+ MxBase::TensorBase tensorBase;
+ // convert to tensor
+ 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();
+ // infer
+ ret = Inference(inputs, outputs);
+ auto endTime = std::chrono::high_resolution_clock::now();
+ double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count(); // save time
+ inferCostTimeMilliSec += costMs;
+ if (ret != APP_ERR_OK) {
+ LogError << "Inference failed, ret=" << ret << ".";
+ return ret;
+ }
+ // to postprocess
+ ret = PostProcess(outputs, out);
+ if (ret != APP_ERR_OK) {
+ LogError << "PostProcess failed, ret=" << ret << ".";
+ return ret;
+ }
+ return APP_ERR_OK;
+}
+
+APP_ERROR FaceRecognition::main(const std::string &zj_list_path, const std::string &jk_list_path,
+const std::string &dis_list_path) {
+ // read zj jk dis txt content
+ std::string s_zj = zj_list_path;
+ std::string s_jk = jk_list_path;
+ std::string s_dis = dis_list_path;
+ // total number of zj and jk txt length
+ int img_tot = 0;
+ img_tot += line_of_txt(s_zj);
+ int img_tot_zj = img_tot;
+ img_tot += line_of_txt(s_jk);
+ int img_tot_jk = img_tot - img_tot_zj;
+ LogInfo << img_tot << std::endl;
+ // out shape is 1,256
+ int batch_img = 1;
+ int out_vector_len = 256;
+ // Define test_tot_np (stored according to idx) to store out
+ std::vector<std::vector<float> >test_embedding_tot_np(img_tot, std::vector<float>(out_vector_len, 0));
+ // Define test_tot (stored according to label) to store out
+ std::map<std::string, std::vector<float> >test_embedding_tot;
+ // Process the images in the read txt
+ int count = 0;
+ LogInfo << "-------------------zj--------------------" << std::endl;
+ deal_txt_img(s_zj, count, batch_img, out_vector_len, test_embedding_tot_np, test_embedding_tot);
+ LogInfo << "-------------------jk--------------------" << std::endl;
+ deal_txt_img(s_jk, count, batch_img, out_vector_len, test_embedding_tot_np, test_embedding_tot);
+ // for dis images
+ int dis_img_tot = 0;
+ dis_img_tot += line_of_txt(s_dis);
+ std::vector<std::vector<float> >dis_embedding_tot_np(dis_img_tot, std::vector<float>(out_vector_len, 0));
+ std::map<std::string, std::vector<float> >dis_embedding_tot;
+ int dis_count = 0;
+ LogInfo << "-------------------dis--------------------" << std::endl;
+ // dis_label
+ std::vector<std::string> dis_label;
+ deal_txt_img_dis(s_dis, dis_count, batch_img, out_vector_len, dis_embedding_tot_np, dis_embedding_tot, dis_label);
+ // step3
+ // get zj2jk_pairs
+ LogInfo << "----------------step 3---------------" << std::endl;
+ std::map<std::string, std::vector<std::string> >zj2jk_pairs;
+ std::vector<int>ID_nums;
+ txt_to_pair(zj2jk_pairs, img_tot_zj, img_tot_jk, ID_nums, zj_list_path, jk_list_path);
+ LogInfo << "----------------step 3 over!!!------------" << std::endl;
+ // into cal_topk
+ std::ifstream zjFile;
+ zjFile.open(zj_list_path);
+ std::string str_zj;
+ // get jk_all_embedding
+ std::map<int, std::vector<std::vector<float> > >jk_all_embedding;
+ get_jk_all_embedding(ID_nums, test_embedding_tot, jk_all_embedding, jk_list_path);
+ int task_num = 1;
+ std::vector<int>correct(2*task_num, 0);
+ std::vector<int>tot(task_num, 0);
+ for (int idx = 0; idx < zj2jk_pairs.size(); idx++) {
+ getline(zjFile, str_zj, '\n');
+ std::vector<int>out1;
+ out1 = cal_topk(idx, str_zj, zj2jk_pairs, test_embedding_tot,
+ dis_embedding_tot_np, jk_all_embedding, dis_label);
+ correct[0] += out1[0];
+ correct[1] += out1[1];
+ tot[0] += zj2jk_pairs[str_zj].size();
+ }
+ LogInfo << "tot[0] is " << tot[0] << std::endl;
+ LogInfo << "correct[0] is " << correct[0] << std::endl;
+ LogInfo << "correct[1] is " << correct[1] << std::endl;
+
+ float zj2jk_acc = static_cast<float>(correct[0]) / static_cast<float>(tot[0]);
+ float jk2zj_acc = static_cast<float>(correct[1]) / static_cast<float>(tot[0]);
+ float avg_acc = (zj2jk_acc + jk2zj_acc) / 2;
+ LogInfo << " zj2jk_acc---------" << zj2jk_acc << std::endl;
+ LogInfo << " jk2zj_acc---------" << jk2zj_acc << std::endl;
+ LogInfo << " avg_acc---------" << avg_acc << std::endl;
+}
+
+
+
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.h b/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.h
new file mode 100644
index 0000000000000000000000000000000000000000..67b72ba608143e2016e503eb647c37c072580718
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/FaceRecognition.h
@@ -0,0 +1,103 @@
+/*
+ * 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_RESNET50CLASSIFYOPENCV_H
+#define MXBASE_RESNET50CLASSIFYOPENCV_H
+#include <time.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <cmath>
+#include <map>
+#include <memory>
+#include <numeric>
+#include <opencv2/opencv.hpp>
+
+#include "MxBase/DvppWrapper/DvppWrapper.h"
+#include "MxBase/ModelInfer/ModelInferenceProcessor.h"
+#include "ClassPostProcessors/Resnet50PostProcess.h"
+#include "MxBase/Tensor/TensorContext/TensorContext.h"
+
+
+struct InitParam {
+ uint32_t deviceId;
+ std::string labelPath;
+ uint32_t classNum;
+ uint32_t topk;
+ bool softmax;
+ bool checkTensor;
+ std::string modelPath;
+};
+
+class FaceRecognition {
+ public:
+ APP_ERROR Init(const InitParam &initParam);
+ APP_ERROR DeInit();
+ bool ReadImage(const std::string &imgPath, cv::Mat &imageMat);
+ APP_ERROR 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(std::vector<MxBase::TensorBase> &inputs,
+ std::vector<std::vector<float>> &out);
+ APP_ERROR Process(const std::string &imgPath, std::vector<std::vector<float>> &out);
+ APP_ERROR main(const std::string &zj_list_path, const std::string &jk_list_path, const std::string &dis_list_path);
+ float uint6_cov_float(uint16_t value);
+ // get infer time
+ double GetInferCostMilliSec() const {return inferCostTimeMilliSec;}
+
+ // lqy-function
+ std::vector<int> cal_topk(int idx, std::string str_zj,
+ std::map<std::string, std::vector<std::string> >& zj2jk_pairs,
+ std::map<std::string, std::vector<float> >& test_embedding_tot,
+ std::vector<std::vector<float> >& dis_embedding_tot_np,
+ const std::map<int, std::vector<std::vector<float> > >& jk_all_embedding,
+ std::vector<std::string>& dis_label);
+ void l2normalize(std::vector<std::vector<float>>& out);
+ int line_of_txt(std::string s);
+ void deal_txt_img(std::string s, int& count, int batch_img, int out_vector_len,
+ std::vector<std::vector<float>>& test_embedding_tot_np,
+ std::map<std::string, std::vector<float> >& test_embedding_tot);
+ void deal_txt_img_dis(std::string s, int& count, int batch_img, int out_vector_len,
+ std::vector<std::vector<float>>& test_embedding_tot_np,
+ std::map<std::string, std::vector<float> >& test_embedding_tot,
+ std::vector<std::string>& dis_label);
+ std::string get_lable_num(std::string s);
+ void txt_to_pair(std::map<std::string, std::vector<std::string> >& zj2jk_pairs,
+ int img_tot_zj, int img_tot_jk, std::vector<int>& ID_nums,
+ const std::string &zj_list_path, const std::string &jk_list_path);
+ void get_jk_all_embedding(std::vector<int>& ID_nums, std::map<std::string,
+ std::vector<float> >& test_embedding_tot,
+ std::map<int, std::vector<std::vector<float> > >& jk_all_embedding,
+ const std::string &jk_list_path);
+
+ private:
+ APP_ERROR SaveResult(const std::string &imgPath,
+ const std::vector<std::vector<MxBase::ClassInfo>> &batchClsInfos, int index);
+
+ private:
+ std::shared_ptr<MxBase::ModelInferenceProcessor> model_;
+ std::shared_ptr<MxBase::Resnet50PostProcess> post_;
+ MxBase::ModelDesc modelDesc_;
+ uint32_t deviceId_ = 0;
+ // infer time
+ double inferCostTimeMilliSec = 0.0;
+};
+
+
+#endif
+
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/build.sh b/research/cv/FaceRecognition/infer/mxbase/facerecognition/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5642b38c1db115f8bb61ebcaf79939e72ed44343
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+#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.
+
+rm -rf build
+mkdir build
+cd build
+cmake ..
+make -j
+cd ..
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/changeTxtPath.py b/research/cv/FaceRecognition/infer/mxbase/facerecognition/changeTxtPath.py
new file mode 100644
index 0000000000000000000000000000000000000000..c0aeb0f0fc9d41f85e500d619c237390fa09b731
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/changeTxtPath.py
@@ -0,0 +1,66 @@
+# 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 sys
+
+
+def change_zj_jk(file_path, path):
+ """ change txt """
+
+ tofile = "after_update_"+file_path.split("/")[-1]
+ fin = open(file_path, "r")
+ fwrite = open(tofile, "w")
+ for line in fin:
+ identity = line.split(" ")[1]
+ pathimg = line.split(" ")[0].split("/")
+
+ print(line)
+ print("修改过后的"+path + pathimg[-3] + '/' + pathimg[-2] + '/' + pathimg[-1])
+ fwrite.write(path + pathimg[-3] + '/' + pathimg[-2] + '/' + pathimg[-1] + " " + identity)
+ fin.close()
+ fwrite.close()
+
+
+def change_dis(file_path, path):
+ """ change txt """
+
+ tofile = './after_update_dis_list.txt'
+ fin = open(file_path, "r")
+ fwrite = open(tofile, "w")
+ for line in fin:
+ pathimg = line.split("/")
+
+ print(line)
+ print("修改过后 "+path + pathimg[-3] + '/' + pathimg[-2] + '/' + pathimg[-1])
+ fwrite.write(path + pathimg[-3] + '/' + pathimg[-2] + '/' + pathimg[-1])
+ fin.close()
+ fwrite.close()
+
+
+if __name__ == '__main__':
+ # This parameter means the path to zj_lists.txt
+ zj_txt_path = sys.argv[1]
+ # This parameter means the path to jk_lists.txt
+ jk_txt_path = sys.argv[2]
+ # This parameter means the path to dis_lists.txt
+ dis_txt_path = sys.argv[3]
+ # This parameter means the path to dataset path
+ dataset_path = sys.argv[4]
+ change_zj_jk(zj_txt_path, dataset_path)
+ change_zj_jk(jk_txt_path, dataset_path)
+ change_dis(dis_txt_path, dataset_path)
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/main_opencv.cpp b/research/cv/FaceRecognition/infer/mxbase/facerecognition/main_opencv.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..01c99dcb69a0f85f3e3c0716eac228d70484bcdc
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/main_opencv.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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<stdio.h>
+#include<stdlib.h>
+#include<iostream>
+#include<fstream>
+#include<string>
+#include<sstream>
+
+#include "FaceRecognition.h"
+#include "MxBase/Log/Log.h"
+
+namespace {
+const int emb_size = 256;
+} // namespace
+
+
+
+APP_ERROR ScanImages(const std::string &path) {
+ DIR *dirPtr = opendir(path.c_str());
+ if (dirPtr == nullptr) {
+ LogError << "opendir failed. dir:" << path;
+ return APP_ERR_INTERNAL_ERROR;
+ }
+ closedir(dirPtr);
+ return APP_ERR_OK;
+}
+
+
+int main(int argc, char* argv[]) {
+ if (argc <= 5) {
+ LogWarn << "Please input image path, such as './lists image_dir'.";
+ return APP_ERR_OK;
+ }
+ InitParam initParam = {};
+ initParam.deviceId = 0;
+ initParam.classNum = emb_size;
+ initParam.labelPath = argv[1];
+ initParam.topk = emb_size;
+ initParam.softmax = false;
+ initParam.checkTensor = true;
+ initParam.modelPath = argv[2];
+ auto resnet50 = std::make_shared<FaceRecognition>();
+ APP_ERROR ret = resnet50->Init(initParam);
+ if (ret != APP_ERR_OK) {
+ LogError << "facerecognition init failed, ret=" << ret << ".";
+ return ret;
+ }
+
+ std::string zj_list_path = argv[3];
+ std::string jk_list_path = argv[4];
+ std::string dis_list_path = argv[5];
+
+ ret = resnet50->main(zj_list_path, jk_list_path, dis_list_path);
+ if (ret != APP_ERR_OK) {
+ LogError << "facerecognition main failed, ret=" << ret << ".";
+ resnet50->DeInit();
+ return ret;
+ }
+ resnet50->DeInit();
+ return APP_ERR_OK;
+}
+
diff --git a/research/cv/FaceRecognition/infer/mxbase/facerecognition/run.sh b/research/cv/FaceRecognition/infer/mxbase/facerecognition/run.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3b3b1004821eb67dcfcb90ab5c9df510c07812ea
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/mxbase/facerecognition/run.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+#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.
+
+bash build.sh
+label_name=$1
+model_path=$2
+zj_list_path=$3
+jk_list_path=$4
+dis_list_path=$5
+
+nohup ./build/resnet ${label_name} ${model_path} ${zj_list_path} ${jk_list_path} ${dis_list_path} &
diff --git a/research/cv/FaceRecognition/infer/requirements.txt b/research/cv/FaceRecognition/infer/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bebf9a963748edb137acd13b36489da7ddbc0938
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/requirements.txt
@@ -0,0 +1,2 @@
+numpy
+pyyaml
diff --git a/research/cv/FaceRecognition/infer/sdk/pipeline/facerecognition.pipeline b/research/cv/FaceRecognition/infer/sdk/pipeline/facerecognition.pipeline
new file mode 100644
index 0000000000000000000000000000000000000000..33f9826c9991a146a1c61ad85b69399544347923
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/sdk/pipeline/facerecognition.pipeline
@@ -0,0 +1,47 @@
+{
+ "im_resnetface": {
+ "stream_config": {
+ "deviceId": "0"
+ },
+ "appsrc0": {
+ "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": "112",
+ "resizeWidth": "112"
+ },
+ "factory": "mxpi_imageresize",
+ "next": "mxpi_tensorinfer0"
+ },
+ "mxpi_tensorinfer0": {
+ "props": {
+ "dataSource": "mxpi_imageresize0",
+ "modelPath": "/home/cy_mindx/FaceRecognitionInfer/om/facerecognition.om",
+ "waitingTime": "2000",
+ "outputDeviceId": "-1"
+ },
+ "factory": "mxpi_tensorinfer",
+ "next": "appsink0"
+ },
+ "appsink0": {
+ "props": {
+ "blocksize": "4096000"
+ },
+ "factory": "appsink"
+ }
+ }
+}
diff --git a/research/cv/FaceRecognition/infer/sdk/python_facerecognition/config.py b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..133627573bff237a9cb53ea955a58de71fd1ec6d
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/config.py
@@ -0,0 +1,130 @@
+#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.
+
+"""Parse arguments"""
+
+import os
+import ast
+import argparse
+from pprint import pprint, pformat
+import yaml
+
+
+class Config:
+ """
+ Configuration namespace. Convert dictionary to members.
+ """
+
+ def __init__(self, cfg_dict):
+ for k, v in cfg_dict.items():
+ if isinstance(v, (list, tuple)):
+ setattr(self, k, [Config(x) if isinstance(x, dict) else x for x in v])
+ else:
+ setattr(self, k, Config(v) if isinstance(v, dict) else v)
+
+ def __str__(self):
+ return pformat(self.__dict__)
+
+ def __repr__(self):
+ return self.__str__()
+
+
+def parse_cli_to_yaml(parser, cfg, helper=None, choices=None, cfg_path="default_config.yaml"):
+ """
+ Parse command line arguments to the configuration according to the default yaml.
+
+ Args:
+ parser: Parent parser.
+ cfg: Base configuration.
+ helper: Helper description.
+ cfg_path: Path to the default yaml config.
+ """
+ parser = argparse.ArgumentParser(description="[REPLACE THIS at config.py]",
+ parents=[parser])
+ helper = {} if helper is None else helper
+ choices = {} if choices is None else choices
+ for item in cfg:
+ if not isinstance(cfg[item], list) and not isinstance(cfg[item], dict):
+ help_description = helper[item] if item in helper else "Please reference to {}".format(cfg_path)
+ choice = choices[item] if item in choices else None
+ if isinstance(cfg[item], bool):
+ parser.add_argument("--" + item, type=ast.literal_eval, default=cfg[item], choices=choice,
+ help=help_description)
+ else:
+ parser.add_argument("--" + item, type=type(cfg[item]), default=cfg[item], choices=choice,
+ help=help_description)
+ args = parser.parse_args()
+ return args
+
+
+def parse_yaml(yaml_path):
+ """
+ Parse the yaml config file.
+
+ Args:
+ yaml_path: Path to the yaml config.
+ """
+ with open(yaml_path, 'r') as fin:
+ try:
+ cfgs = yaml.load_all(fin.read(), Loader=yaml.FullLoader)
+ cfgs = [x for x in cfgs]
+ if len(cfgs) == 1:
+ cfg_helper = {}
+ cfg = cfgs[0]
+ cfg_choices = {}
+ elif len(cfgs) == 2:
+ cfg, cfg_helper = cfgs
+ cfg_choices = {}
+ elif len(cfgs) == 3:
+ cfg, cfg_helper, cfg_choices = cfgs
+ else:
+ raise ValueError("At most 3 docs (config, description for help, choices) are supported in config yaml")
+ print(cfg_helper)
+ except:
+ raise ValueError("Failed to parse yaml")
+ return cfg, cfg_helper, cfg_choices
+
+
+def merge(args, cfg):
+ """
+ Merge the base config from yaml file and command line arguments.
+
+ Args:
+ args: Command line arguments.
+ cfg: Base configuration.
+ """
+ args_var = vars(args)
+ for item in args_var:
+ cfg[item] = args_var[item]
+ return cfg
+
+
+def get_config():
+ """
+ Get Config according to the yaml file and cli arguments.
+ """
+ parser = argparse.ArgumentParser(description="default name", add_help=False)
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ parser.add_argument("--config_path", type=str, default=os.path.join(current_dir, "../yaml/inference_config.yaml"),
+ help="Config file path")
+ path_args, _ = parser.parse_known_args()
+ default, helper, choices = parse_yaml(path_args.config_path)
+ pprint(default)
+ args = parse_cli_to_yaml(parser=parser, cfg=default, helper=helper, choices=choices, cfg_path=path_args.config_path)
+ final_config = merge(args, default)
+ return Config(final_config)
+
+
+config = get_config()
diff --git a/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.py b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..4104e1b2204c30eaa04e5a79ba3c318132da8a83
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.py
@@ -0,0 +1,335 @@
+# 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 math
+import os
+import time
+import numpy as np
+import MxpiDataType_pb2 as MxpiDataType
+from StreamManagerApi import StreamManagerApi
+from StreamManagerApi import MxDataInput, StringVector
+from config import config
+
+zj_test_result_name = 'zj_result.txt'
+jk_test_result_name = 'jk_result.txt'
+
+
+def l2normalize(features):
+ epsilon = 1e-12
+ l2norm = np.sum(np.abs(features) ** 2, axis=1, keepdims=True) ** (1. / 2)
+ l2norm[np.logical_and(l2norm < 0, l2norm > -epsilon)] = -epsilon
+ l2norm[np.logical_and(l2norm >= 0, l2norm < epsilon)] = epsilon
+ return features / l2norm
+
+
+def check_minmax(data, min_value=0.99, max_value=1.01):
+ min_data = data.min()
+ max_data = data.max()
+ if np.isnan(min_data) or np.isnan(max_data):
+ print('ERROR, nan happened, please check if used fp16 or other error')
+ raise Exception
+ if min_data < min_value or max_data > max_value:
+ print('ERROR, min or max is out if range, range=[{}, {}], minmax=[{}, {}]'.format(
+ min_value, max_value, min_data, max_data))
+ raise Exception
+
+
+def generate_test_pair(jk_list, zj_list):
+ '''generate_test_pair'''
+ file_paths = [jk_list, zj_list]
+ jk_dict = {}
+ zj_dict = {}
+ jk_zj_dict_list = [jk_dict, zj_dict]
+ # The following code is to put the pictures corresponding to the tags (ids) in each list into a list,
+ # for example, people has n pictures, so x_dict [people] can take out the paths of the n pictures.
+ for path, x_dict in zip(file_paths, jk_zj_dict_list):
+ with open(path, 'r') as fr:
+ for line in fr:
+ label = line.strip().split(' ')[1]
+ tmp = x_dict.get(label, [])
+ tmp.append(line.strip())
+ x_dict[label] = tmp
+ zj2jk_pairs = []
+ # Here is zj and jk two lists are stored inside the path corresponding to the id,
+ # so they are directly combined with each other
+ for key in jk_dict:
+ jk_file_list = jk_dict[key]
+ zj_file_list = zj_dict[key]
+ for zj_file in zj_file_list:
+ zj2jk_pairs.append([zj_file, jk_file_list])
+ return zj2jk_pairs
+
+
+class DistributedSampler():
+ '''DistributedSampler'''
+
+ def __init__(self, dataset):
+ self.dataset = dataset
+ self.num_replicas = 1
+ self.rank = 0
+ self.num_samples = int(math.ceil(len(self.dataset) * 1.0 / self.num_replicas))
+
+ def __iter__(self):
+ # Here len(self.dataset) means the number of people in the test image
+ indices = list(range(len(self.dataset)))
+ indices = indices[self.rank::self.num_replicas]
+ return iter(indices)
+
+ def __len__(self):
+ return self.num_samples
+
+
+def topk(matrix, k, axis=1):
+ '''topk'''
+ if axis == 0:
+ row_index = np.arange(matrix.shape[1 - axis])
+ topk_index = np.argpartition(-matrix, k, axis=axis)[0:k, :]
+ topk_data = matrix[topk_index, row_index]
+ topk_index_sort = np.argsort(-topk_data, axis=axis)
+ topk_data_sort = topk_data[topk_index_sort, row_index]
+ topk_index_sort = topk_index[0:k, :][topk_index_sort, row_index]
+ else:
+ column_index = np.arange(matrix.shape[1 - axis])[:, None]
+ topk_index = np.argpartition(-matrix, k, axis=axis)[:, 0:k]
+ topk_data = matrix[column_index, topk_index]
+ topk_index_sort = np.argsort(-topk_data, axis=axis)
+ topk_data_sort = topk_data[column_index, topk_index_sort]
+ topk_index_sort = topk_index[:, 0:k][column_index, topk_index_sort]
+ return topk_data_sort, topk_index_sort, topk_index
+
+
+def cal_topk(idx, zj2jk_pairs, test_embedding_tot, dis_embedding_tot, dis_labels):
+ '''cal_topk'''
+ correct = np.array([0] * 2)
+ tot = np.array([0])
+
+ # Here we get zj's label and all the images corresponding to this person
+ zj, jk_all = zj2jk_pairs[idx]
+ # Get the feature vector of the id
+ zj_embedding = test_embedding_tot[zj]
+ # Here is to take out all the feature vectors of all the images corresponding to zj in jk
+ jk_all_embedding = np.concatenate([np.expand_dims(test_embedding_tot[jk], axis=0) for jk in jk_all], axis=0)
+
+ test_time = time.time()
+ # mm is the vector in zj multiplied by all the vectors in dis_embedding zj(1,256) dis(257,256)
+ mm = np.matmul(np.expand_dims(zj_embedding, axis=0), dis_embedding_tot)
+ # Here the dimension (1, N) is turned into (N, )
+ _, _, jk2zj_sort_1 = topk(mm, 1)
+ top100_jk2zj = np.squeeze(topk(mm, 1)[0], axis=0)
+ top100_zj2jk, _, zj2jk_sort_1 = topk(np.matmul(jk_all_embedding, dis_embedding_tot), 1)
+ test_time_used = time.time() - test_time
+ print('INFO, calculate top1 acc index:{}, np.matmul().top(100) time used:{:.2f}s'.format(
+ idx, test_time_used))
+ tot[0] = len(jk_all)
+
+ for i, jk in enumerate(jk_all):
+ jk_embedding = test_embedding_tot[jk]
+ similarity = np.dot(jk_embedding, zj_embedding)
+ # write the groundtruth to the txt
+ writeresult(1, zj + " ")
+ writeresult(0, jk + " ")
+ if similarity > top100_jk2zj[0]:
+ writeresult(1, zj + "\n")
+ correct[0] += 1
+ else:
+ writeresult(1, dis_labels[jk2zj_sort_1[0, 0]] + "\n")
+ if similarity > top100_zj2jk[i, 0]:
+ writeresult(0, jk + "\n")
+ correct[1] += 1
+ else:
+ writeresult(0, dis_labels[zj2jk_sort_1[i, 0]] + "\n")
+ return correct, tot
+
+
+def writeresult(flag=1, string="test"):
+ # write the result to zj
+ if flag == 1:
+ with open(zj_test_result_name, 'a') as f:
+ f.write(string)
+ # write the result to jk
+ else:
+ with open(jk_test_result_name, 'a') as f:
+ f.write(string)
+
+
+stream_manager_api = StreamManagerApi()
+ret = stream_manager_api.InitManager()
+if ret != 0:
+ print("Failed to init Stream manager, ret=%s" % str(ret))
+ exit()
+print("create streams by pipeline config file")
+
+with open("../pipeline/facerecognition.pipeline", 'rb') as pipeline_file:
+ pipelineStr = pipeline_file.read()
+ret = stream_manager_api.CreateMultipleStreams(pipelineStr)
+
+if ret != 0:
+ print("Failed to create Stream, ret=%s" % str(ret))
+ exit()
+print("Construct the input of the stream")
+
+data_input = MxDataInput()
+
+
+def calculate(file_path):
+ """ calculate the output"""
+
+ with open(file_path, 'rb') as f:
+ print("processing img ", file_path)
+ data_input.data = f.read()
+
+ stream_name = b'im_resnetface'
+ 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()
+
+ keys = [b"mxpi_tensorinfer0"]
+ keyVec = StringVector()
+ for key in keys:
+ keyVec.push_back(key)
+
+ infer_result = stream_manager_api.GetProtobuf(stream_name, unique_id, keyVec)
+
+ result = MxpiDataType.MxpiTensorPackageList()
+ result.ParseFromString(infer_result[0].messageBuf)
+
+ result = np.frombuffer(result.tensorPackageVec[0].tensorVec[0].dataStr, dtype='float32')
+
+ out = np.expand_dims(result, axis=0)
+ out = out.astype(np.float32)
+
+ embeddings = l2normalize(out)
+ return embeddings
+
+
+def run_eval(test_img_predix, test_img_list, dis_img_predix, dis_img_list):
+ """ init stream manager """
+
+ print(" read zj_list and jk_list ")
+
+ zj_jk_labels = []
+ zj_jk_imgs = []
+ print(" jk's txt first zj's txt second ")
+
+ for file in test_img_list:
+ with open(file, 'r') as ft:
+ lines = ft.readlines()
+ for line in lines:
+ imgpath = line.strip().split(" ")[0]
+ zj_jk_imgs.append(imgpath)
+ zj_jk_labels.append(line.strip())
+ print(" test img total number ")
+
+ img_tot = len(zj_jk_labels)
+ print("*" * 20, "total img number is {}".format(img_tot))
+ print("This is the feature vector used to store the images in jk and zj ")
+
+ test_embedding_tot_np = np.zeros((img_tot, config.emb_size))
+ test_img_labels = zj_jk_labels
+ print(" Read the images in turn and get the corresponding feature vectors ")
+
+ for index in range(img_tot):
+ file_path = zj_jk_imgs[index]
+ embeddings = calculate(file_path)
+ test_embedding_tot_np[index] = embeddings[0]
+ # there aim is to check value
+ try:
+ check_minmax(np.linalg.norm(test_embedding_tot_np, ord=2, axis=1))
+ except ValueError:
+ print("-" * 20, "error occur!!")
+
+ # Construct the feature vectors of the images in the test set as key-value pairs ,Use each line of the txt as a key
+ test_embedding_tot = {}
+ for index in range(img_tot):
+ test_embedding_tot[test_img_labels[index]] = test_embedding_tot_np[index]
+
+ # for dis images
+ dis_labels = []
+ dis_img = []
+ with open(dis_img_list[0], 'r') as ft:
+ lines = ft.readlines()
+ for line in lines:
+ imgpath = line.strip().split(" ")[0]
+ # 得到dis_embedding当中对应的人的id
+ dis_labels.append(imgpath)
+ dis_img.append(line.strip())
+ dis_img_tot = len(dis_labels)
+ dis_embedding_tot_np = np.zeros((dis_img_tot, config.emb_size))
+
+ print("dis_label is ", dis_labels)
+ for index in range(dis_img_tot):
+ file_path = dis_img[index]
+ embeddings = calculate(file_path)
+ dis_embedding_tot_np[index] = embeddings[0]
+ # there aim is to check value
+ try:
+ check_minmax(np.linalg.norm(dis_embedding_tot_np, ord=2, axis=1))
+ except ValueError:
+ print("-" * 20, "error occur!!")
+
+ # convert the dis_embedding_tot_np shape to (emb_size , total dis img number)
+ dis_embedding_tot_np = np.transpose(dis_embedding_tot_np, (1, 0))
+
+ # find best match
+ assert len(test_img_list) % 2 == 0
+ task_num = int(len(test_img_list) / 2)
+ correct = np.array([0] * (2 * task_num))
+ tot = np.array([0] * task_num)
+
+ # calculate the accuracy
+ for i in range(int(len(test_img_list) / 2)):
+ jk_list = test_img_list[2 * i]
+ zj_list = test_img_list[2 * i + 1]
+
+ # merge the data (zj and jk)
+ zj2jk_pairs = sorted(generate_test_pair(jk_list, zj_list))
+ print("-" * 20, "数据融合完成!")
+
+ # Here you only need the number of samplers, that is, the number of test objects in zj_list.txt
+ sampler = DistributedSampler(zj2jk_pairs)
+ print('INFO, calculate top1 acc sampler len:{}'.format(len(sampler)))
+ for idx in sampler:
+ out1, out2 = cal_topk(idx, zj2jk_pairs, test_embedding_tot, dis_embedding_tot_np, dis_labels)
+ correct[2 * i] += out1[0]
+ correct[2 * i + 1] += out1[1]
+ tot[i] += out2[0]
+
+ print('tot={},correct={}'.format(tot, correct))
+
+ for i in range(int(len(test_img_list) / 2)):
+ test_set_name = 'test_dataset'
+ zj2jk_acc = correct[2 * i] / tot[i]
+ jk2zj_acc = correct[2 * i + 1] / tot[i]
+ avg_acc = (zj2jk_acc + jk2zj_acc) / 2
+ results = '[{}]: zj2jk={:.4f}, jk2zj={:.4f}, avg={:.4f}'.format(test_set_name, zj2jk_acc, jk2zj_acc, avg_acc)
+ print(results)
+ # destroy streams
+ stream_manager_api.DestroyAllStreams()
+
+
+if __name__ == '__main__':
+ test_dir = config.test_dir
+ test_img_predix_fixversion = [os.path.join(test_dir, config.test_img_predix),
+ os.path.join(test_dir, config.test_img_predix)]
+ test_img_list_fixversion = [os.path.join(test_dir, config.test_img_list_jk),
+ os.path.join(test_dir, config.test_img_list_zj)]
+ dis_img_predix_fixversion = [os.path.join(test_dir, config.dis_img_predix)]
+ dis_img_list_fixversion = [os.path.join(test_dir, config.dis_img_list)]
+
+ run_eval(test_img_predix_fixversion, test_img_list_fixversion, dis_img_predix_fixversion, dis_img_list_fixversion)
diff --git a/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.sh b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.sh
new file mode 100644
index 0000000000000000000000000000000000000000..07d0ce7735d3fd23b6904eca01a5ccfb36623c3c
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/sdk/python_facerecognition/main.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.
+#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" ; }
+
+# export MX_SDK_HOME=${CUR_PATH}/../../..
+export LD_LIBRARY_PATH=${MX_SDK_HOME}/lib:${MX_SDK_HOME}/opensource/lib:/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64:${LD_LIBRARY_PATH}
+export GST_PLUGIN_SCANNER=${MX_SDK_HOME}/opensource/libexec/gstreamer-1.0/gst-plugin-scanner
+export GST_PLUGIN_PATH=${MX_SDK_HOME}/opensource/lib/gstreamer-1.0:${MX_SDK_HOME}/lib/plugins
+
+#to set PYTHONPATH, import the StreamManagerApi.py
+export PYTHONPATH=$PYTHONPATH:${MX_SDK_HOME}/python
+
+# Output the result to nohup.out If you want to print directly to the console, you can change the command to python3.7 main.py
+nohup python3.7 main.py &
+exit 0
diff --git a/research/cv/FaceRecognition/infer/sdk/yaml/inference_config.yaml b/research/cv/FaceRecognition/infer/sdk/yaml/inference_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b36f40672616fb59732a21b7639df7f828eb1a97
--- /dev/null
+++ b/research/cv/FaceRecognition/infer/sdk/yaml/inference_config.yaml
@@ -0,0 +1,102 @@
+# Builtin Configurations(DO NOT CHANGE THESE CONFIGURATIONS unless you know exactly what you are doing)
+enable_modelarts: False
+# Url for modelarts
+data_url: ""
+train_url: ""
+checkpoint_url: ""
+# Path for local
+data_path: "/cache/data"
+output_path: "/cache/train"
+load_path: "/cache/checkpoint_path"
+
+
+device_target: "Ascend"
+enable_profiling: False
+
+# ==============================================================================
+# Training options
+
+# distributed parameter
+is_distributed: 0
+local_rank: 0
+world_size: 1
+
+#result_dir
+result_dir: ''
+
+# test weight
+#weight: 'your_test_model'
+#'''2021/8/31'''
+weight: '/home/LiuYi/facerecognition_ascend_v120_humanface_research_cv_bs192_acc93.ckpt'
+test_dir: '/home/cy_mindx/FaceRecognitionInfer/datasets/'
+need_modelarts_dataset_unzip: False
+
+# model define
+backbone: "r100"
+use_se: 0
+emb_size: 256
+act_type: "relu"
+fp16: 1
+pre_bn: 0
+inference: 1
+use_drop: 0
+
+# test and dis batch size
+test_batch_size: 128
+dis_batch_size: 512
+
+# log
+log_interval: 100
+ckpt_path: "outputs/models"
+
+# test and dis image list
+test_img_predix: "test_dataset/"
+test_img_list_jk: "lists/jk_list.txt"
+test_img_list_zj: "lists/zj_list.txt"
+dis_img_predix: "dis_dataset/"
+dis_img_list: "lists/dis_list.txt"
+
+# export option
+batch_size: 16
+file_name: "fr.midnir"
+file_format: "MINDIR"
+export_pre_bn: 0
+export_inference: 1
+export_use_se: 0
+export_emb_size: 256
+export_act_type: "relu"
+export_backbone: "r100"
+export_use_drop: 0
+head: "0"
+
+---
+
+# Help description for each configuration
+enable_modelarts: "Whether training on modelarts, default: False"
+data_url: "Url for modelarts"
+train_url: "Url for modelarts"
+data_path: "The location of the input data."
+output_path: "The location of the output file."
+device_target: 'Target device type'
+enable_profiling: 'Whether enable profiling while training, default: False'
+# Dataset description
+
+test_dir: 'This is the directory where the test need is located (It is best to fill in the absolute path, so that you can save the probability of error is smaller)'
+test_img_predix: 'Table of contents for the test set img'
+test_img_list_jk: 'Path location of the test set txt file under testdir'
+test_img_list_zj: 'Path location of the test set txt file under testdir'
+dis_img_predix: 'Path location of the different people img under testdir'
+dis_img_list: 'Path location of the different people test set txt file under testdir'
+
+# export option
+batch_size: "batch size"
+file_name: "file name"
+file_format: "file format, choices in ['MINDIR', 'AIR']"
+export_pre_bn: "1: bn-conv-bn-conv-bn, 0: conv-bn-conv-bn"
+export_inference: "use inference backbone"
+export_use_se: "use se block or not"
+export_emb_size: "embedding size of the network (this should be same as emb_size after trained)"
+export_act_type: "activation layer type"
+export_backbone: "backbone network"
+export_use_drop: "whether use dropout in network"
+head: "head type, default is 0"
diff --git a/research/cv/FaceRecognition/modelarts/default_config.yaml b/research/cv/FaceRecognition/modelarts/default_config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5c1a32f8acaf2f4483a78fa805cb0a8be95fd9a4
--- /dev/null
+++ b/research/cv/FaceRecognition/modelarts/default_config.yaml
@@ -0,0 +1,102 @@
+# Builtin Configurations(DO NOT CHANGE THESE CONFIGURATIONS unless you know exactly what you are doing)
+enable_modelarts: False
+# Url for modelarts
+data_url: ""
+train_url: ""
+checkpoint_url: ""
+# Path for local
+data_path: "/cache/data"
+output_path: "/cache/train"
+load_path: "/cache/checkpoint_path"
+device_target: "Ascend"
+enable_profiling: False
+
+# ==============================================================================
+# Training options
+train_stage: "base"
+is_distributed: 1
+
+# dataset related
+data_dir: "/cache/data/face_recognition_dataset/train_dataset/"
+num_classes: 1
+per_batch_size: 192
+need_modelarts_dataset_unzip: True
+
+# network structure related
+backbone: "r100"
+use_se: 1
+emb_size: 512
+act_type: "relu"
+fp16: 1
+pre_bn: 1
+inference: 0
+use_drop: 1
+nc_16: 1
+
+# loss related
+margin_a: 1.0
+margin_b: 0.2
+margin_m: 0.3
+margin_s: 64
+
+# optimizer related
+lr: 0.4
+lr_scale: 1
+lr_epochs: "8,14,18"
+weight_decay: 0.0002
+momentum: 0.9
+max_epoch: 20
+pretrained: ""
+warmup_epochs: 2
+
+# distributed parameter
+local_rank: 0
+world_size: 1
+model_parallel: 0
+
+# logging related
+log_interval: 100
+ckpt_path: "outputs"
+max_ckpts: -1
+dynamic_init_loss_scale: 65536
+ckpt_steps: 1000
+
+# export option
+batch_size: 16
+file_name: "facerecognition"
+file_format: "AIR"
+export_pre_bn: 0
+export_inference: 1
+export_use_se: 0
+export_emb_size: 512
+export_act_type: "relu"
+export_backbone: "r100"
+export_use_drop: 0
+head: "0"
+
+---
+
+# Help description for each configuration
+enable_modelarts: "Whether training on modelarts, default: False"
+data_url: "Url for modelarts"
+train_url: "Url for modelarts"
+data_path: "The location of the input data."
+output_path: "The location of the output file."
+device_target: 'Target device type'
+enable_profiling: 'Whether enable profiling while training, default: False'
+
+train_stage: "Train stage, base or beta"
+is_distributed: "If multi device"
+
+# export option
+batch_size: "batch size"
+file_name: "file name"
+file_format: "file format, choices in ['MINDIR', 'AIR']"
+export_pre_bn: "1: bn-conv-bn-conv-bn, 0: conv-bn-conv-bn"
+export_inference: "use inference backbone"
+export_use_se: "use se block or not"
+export_emb_size: "embedding size of the network"
+export_act_type: "activation layer type"
+export_backbone: "backbone network"
+export_use_drop: "whether use dropout in network"
+head: "head type, default is 0"
\ No newline at end of file
diff --git a/research/cv/FaceRecognition/modelarts/train_start_final.py b/research/cv/FaceRecognition/modelarts/train_start_final.py
new file mode 100644
index 0000000000000000000000000000000000000000..4bd44211b73bfe62473714ce0be3be9955766b98
--- /dev/null
+++ b/research/cv/FaceRecognition/modelarts/train_start_final.py
@@ -0,0 +1,391 @@
+# 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 argparse
+import os
+import time
+import numpy as np
+import mindspore
+from mindspore import Tensor
+from mindspore.nn import Cell
+from mindspore import context
+from mindspore.context import ParallelMode
+from mindspore.communication.management import init
+from mindspore.nn.optim import Momentum
+from mindspore.train.model import Model
+from mindspore.train.callback import ModelCheckpoint, CheckpointConfig
+from mindspore.train.loss_scale_manager import DynamicLossScaleManager
+from mindspore.train.serialization import load_checkpoint, load_param_into_net, export
+from src.my_logging import get_logger
+from src.init_network import init_net
+from src.dataset_factory import get_de_dataset
+from src.backbone.resnet import get_backbone
+from src.metric_factory import get_metric_fc
+from src.loss_factory import get_loss
+from src.lrsche_factory import warmup_step_list, list_to_gen
+from src.callback_factory import ProgressMonitor
+
+from model_utils.config import config
+from model_utils.device_adapter import get_device_id, get_device_num, get_rank_id
+
+mindspore.common.seed.set_seed(1)
+context.set_context(mode=context.GRAPH_MODE, device_target=config.device_target, save_graphs=False,
+ reserve_class_name_in_scope=False, enable_graph_kernel=config.device_target == "GPU")
+
+parser = argparse.ArgumentParser(description='Image classification')
+
+parser.add_argument('--per_batch_size', type=int, default=10, help='dataloader batch size')
+parser.add_argument('--batch_size', type=int, default=1, help='bach size')
+parser.add_argument('--backbone', type=str, default='r100', help="Backbone net")
+parser.add_argument('--lr', type=float, default=0.4, help='learning rate')
+parser.add_argument('--max_epoch', type=int, default=1, help='the max epoch')
+parser.add_argument('--data_url',
+ metavar='DIR',
+ default='/cache/data_url',
+ help='path to dataset')
+parser.add_argument('--train_url',
+ default="/mindspore-dataset/output/",
+ type=str,
+ help="setting dir of training output")
+parser.add_argument('--pretrained',
+ default=None,
+ type=str,
+ help="setting dir of ckpt")
+
+args_opt = parser.parse_args()
+
+
+class DistributedHelper(Cell):
+ '''DistributedHelper'''
+
+ def __init__(self, backbone, margin_fc):
+ super(DistributedHelper, self).__init__()
+ self.backbone = backbone
+ self.margin_fc = margin_fc
+ if margin_fc is not None:
+ self.has_margin_fc = 1
+ else:
+ self.has_margin_fc = 0
+
+ def construct(self, x, label):
+ embeddings = self.backbone(x)
+ if self.has_margin_fc == 1:
+ return embeddings, self.margin_fc(embeddings, label)
+ return embeddings
+
+
+class BuildTrainNetwork(Cell):
+ '''BuildTrainNetwork'''
+
+ def __init__(self, network, criterion, args_1):
+ super(BuildTrainNetwork, self).__init__()
+ self.network = network
+ self.criterion = criterion
+ self.args = args_1
+
+ if int(args_1.model_parallel) == 0:
+ self.is_model_parallel = 0
+ else:
+ self.is_model_parallel = 1
+
+ def construct(self, input_data, label):
+
+ if self.is_model_parallel == 0:
+ _, output = self.network(input_data, label)
+ loss = self.criterion(output, label)
+ else:
+ _ = self.network(input_data, label)
+ loss = self.criterion(None, label)
+
+ return loss
+
+
+def load_pretrain(cfg, net):
+ '''load pretrain function.'''
+
+ if os.path.isfile(cfg.pretrained):
+ param_dict = load_checkpoint(cfg.pretrained)
+ param_dict_new = {}
+ if cfg.train_stage.lower() == 'base':
+ for key, value in param_dict.items():
+ if key.startswith('moments.'):
+ continue
+ elif key.startswith('network.'):
+ param_dict_new[key[8:]] = value
+ else:
+ for key, value in param_dict.items():
+ if key.startswith('moments.'):
+ continue
+ elif key.startswith('network.'):
+ if 'layers.' in key and 'bn1' in key:
+ continue
+ elif 'se' in key:
+ continue
+ elif 'head' in key:
+ continue
+ elif 'margin_fc.weight' in key:
+ continue
+ else:
+ param_dict_new[key[8:]] = value
+ load_param_into_net(net, param_dict_new)
+ cfg.logger.info('load model {} success'.format(cfg.pretrained))
+ else:
+ if cfg.train_stage.lower() == 'beta':
+ raise ValueError("Train beta mode load pretrain model fail from: {}".format(cfg.pretrained))
+ init_net(cfg, net)
+ cfg.logger.info('init model success')
+ return net
+
+
+def modelarts_pre_process():
+ '''modelarts pre process function.'''
+
+ def unzip(zip_file, save_dir):
+ import zipfile
+ s_time = time.time()
+ if not os.path.exists(os.path.join(save_dir, "face_recognition_dataset")):
+ zip_isexist = zipfile.is_zipfile(zip_file)
+ if zip_isexist:
+ fz = zipfile.ZipFile(zip_file, 'r')
+ data_num = len(fz.namelist())
+ print("Extract Start...")
+ print("unzip file num: {}".format(data_num))
+ i = 0
+ for file in fz.namelist():
+ if i % int(data_num / 100) == 0:
+ print("unzip percent: {}%".format(i / int(data_num / 100)), flush=True)
+ i += 1
+ fz.extract(file, save_dir)
+ print("cost time: {}min:{}s.".format(int((time.time() - s_time) / 60),
+ int(int(time.time() - s_time) % 60)))
+ print("Extract Done.")
+ else:
+ print("This is not zip.")
+ else:
+ print("Zip has been extracted.")
+
+ if config.need_modelarts_dataset_unzip:
+ zip_file_1 = os.path.join(config.data_path, "face_recognition_dataset.zip")
+ save_dir_1 = os.path.join(config.data_path)
+
+ sync_lock = "/tmp/unzip_sync.lock"
+
+ # Each server contains 8 devices as most.
+ if get_device_id() % min(get_device_num(), 8) == 0 and not os.path.exists(sync_lock):
+ print("Zip file path: ", zip_file_1)
+ print("Unzip file save dir: ", save_dir_1)
+ unzip(zip_file_1, save_dir_1)
+ print("===Finish extract data synchronization===")
+ try:
+ os.mknod(sync_lock)
+ except IOError:
+ pass
+
+ while True:
+ if os.path.exists(sync_lock):
+ break
+ time.sleep(1)
+
+ print("Device: {}, Finish sync unzip data from {} to {}.".format(get_device_id(), zip_file_1, save_dir_1))
+
+ print(" Here the total output address is changed to /train_url/ ")
+
+ config.ckpt_path = os.path.join(args_opt.train_url, str(get_rank_id()), config.ckpt_path)
+
+
+def calculate_numclasses():
+ if config.nc_16 == 1 and config.model_parallel == 0 and config.num_classes % 16 != 0:
+ config.num_classes = (config.num_classes // 16 + 1) * 16
+ if config.nc_16 == 1 and config.model_parallel != 0 and config.num_classes % (config.world_size * 16) != 0:
+ config.num_classes = (config.num_classes // (config.world_size * 16) + 1) * config.world_size * 16
+
+
+def run_export_modelarts(path, outpath):
+ ''' run export. '''
+
+ config.pre_bn = config.export_pre_bn
+ config.inference = config.export_inference
+ config.use_se = config.export_use_se
+ config.emb_size = config.export_emb_size
+ config.act_type = config.export_act_type
+ config.backbone = config.export_backbone
+ config.use_drop = config.export_use_drop
+
+ devid = 0
+ context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", save_graphs=False, device_id=devid)
+
+ network = get_backbone(config)
+
+ # ckpt_path = config.pretrained
+ ckpt_path = path
+ if os.path.isfile(ckpt_path):
+ param_dict = load_checkpoint(ckpt_path)
+ param_dict_new = {}
+ for key, values in param_dict.items():
+ if key.startswith('moments.'):
+ continue
+ elif key.startswith('network.'):
+ param_dict_new[key[8:]] = values
+ else:
+ param_dict_new[key] = values
+ load_param_into_net(network, param_dict_new)
+ print('-----------------------load model success-----------------------')
+ else:
+ print('-----------------------load model failed -----------------------')
+
+ network.add_flags_recursive(fp16=True)
+ network.set_train(False)
+
+ input_data = np.random.uniform(low=0, high=1.0, size=(config.batch_size, 3, 112, 112)).astype(np.float32)
+ tensor_input_data = Tensor(input_data)
+
+ export(network, tensor_input_data, file_name=outpath + config.file_name, file_format=config.file_format)
+ print('-----------------------export model success, save file:{}-----------------------'.format(
+ outpath + config.file_name))
+
+
+def run_train():
+ """Here you need to change the path to the dataset to the specified address on the server"""
+
+ config.data_dir = args_opt.data_url
+ config.ckpt_path = os.path.join(args_opt.train_url, str(get_rank_id()), config.ckpt_path)
+ config.pretrained = args_opt.pretrained
+ print('run train function.')
+
+ config.local_rank = get_rank_id()
+ config.world_size = get_device_num()
+
+ print(" write the logs ")
+
+ log_path = os.path.join(config.ckpt_path, 'logs')
+ config.logger = get_logger(log_path, config.local_rank)
+
+ support_train_stage = ['base', 'beta']
+ if config.train_stage.lower() not in support_train_stage:
+ config.logger.info('your train stage is not support.')
+ raise ValueError('train stage not support.')
+
+ if not os.path.exists(config.data_dir):
+ config.logger.info('ERROR, data_dir is not exists, please set data_dir in config.py')
+ raise ValueError('ERROR, data_dir is not exists, please set data_dir in config.py')
+
+ parallel_mode = ParallelMode.HYBRID_PARALLEL if config.is_distributed else ParallelMode.STAND_ALONE
+ context.set_auto_parallel_context(parallel_mode=parallel_mode,
+ device_num=config.world_size, gradients_mean=True)
+ if config.is_distributed:
+ init()
+
+ if config.local_rank % 8 == 0:
+ if not os.path.exists(config.ckpt_path):
+ os.makedirs(config.ckpt_path)
+
+ # Obtain the dataset and the total number of training data
+ de_dataset, steps_per_epoch, num_classes = get_de_dataset(config)
+ config.logger.info('de_dataset: %d', de_dataset.get_dataset_size())
+
+ # Configure the data in the config for subsequent calls
+ config.steps_per_epoch = steps_per_epoch
+ config.num_classes = num_classes
+ config.lr_epochs = list(map(int, config.lr_epochs.split(',')))
+ config.logger.info('config.num_classes: %d', config.num_classes)
+ config.logger.info('config.world_size: %d', config.world_size)
+ config.logger.info('config.local_rank: %d', config.local_rank)
+ config.logger.info('config.lr: %f', config.lr)
+
+ calculate_numclasses()
+
+ config.logger.info('for D, loaded, class nums: %d', config.num_classes)
+ config.logger.info('steps_per_epoch: %d', config.steps_per_epoch)
+ config.logger.info('img_total_num: %d', config.steps_per_epoch * config.per_batch_size)
+
+ config.logger.info('get_backbone----in----')
+ print(" get the backbone ")
+
+ _backbone = get_backbone(config)
+ config.logger.info('get_backbone----out----')
+
+ config.logger.info('get_metric_fc----in----')
+ margin_fc_1 = get_metric_fc(config)
+ config.logger.info('get_metric_fc----out----')
+
+ config.logger.info('DistributedHelper----in----')
+ network_1 = DistributedHelper(_backbone, margin_fc_1)
+ config.logger.info('DistributedHelper----out----')
+
+ config.logger.info('network fp16----in----')
+ if config.fp16 == 1:
+ network_1.add_flags_recursive(fp16=True)
+ config.logger.info('network fp16----out----')
+
+ print(" get the loss function ")
+
+ criterion_1 = get_loss(config)
+ if config.fp16 == 1 and config.model_parallel == 0:
+ criterion_1.add_flags_recursive(fp32=True)
+
+ print(" Check if pre-training is needed by using the parameters in yaml ")
+
+ network_1 = load_pretrain(config, network_1)
+ train_net = BuildTrainNetwork(network_1, criterion_1, config)
+
+ print(" call warmup_step should behind the config steps_per_epoch 其实就是衰减策略")
+
+ config.lrs = warmup_step_list(config, gamma=0.1)
+ lrs_gen = list_to_gen(config.lrs)
+ opt = Momentum(params=train_net.trainable_params(), learning_rate=lrs_gen, momentum=config.momentum,
+ weight_decay=config.weight_decay)
+ scale_manager = DynamicLossScaleManager(init_loss_scale=config.dynamic_init_loss_scale, scale_factor=2,
+ scale_window=2000)
+ if config.device_target == "Ascend":
+ model = Model(train_net, optimizer=opt, metrics=None, loss_scale_manager=scale_manager)
+ elif config.device_target == "CPU":
+ model = Model(train_net, optimizer=opt, metrics=None, loss_scale_manager=None)
+
+ save_checkpoint_steps = config.ckpt_steps
+ config.logger.info('save_checkpoint_steps: %d', save_checkpoint_steps)
+ if config.max_ckpts == -1:
+ keep_checkpoint_max = int(config.steps_per_epoch * config.max_epoch / save_checkpoint_steps) + 5
+ else:
+ keep_checkpoint_max = config.max_ckpts
+ config.logger.info('keep_checkpoint_max: %d', keep_checkpoint_max)
+
+ callback_list = []
+ config.epoch_cnt = 0
+ progress_cb = ProgressMonitor(config)
+ callback_list.append(progress_cb)
+ if config.local_rank % 8 == 0:
+ ckpt_config = CheckpointConfig(save_checkpoint_steps=save_checkpoint_steps,
+ keep_checkpoint_max=keep_checkpoint_max)
+ config.logger.info('max_epoch_train: %d', config.max_epoch)
+ ckpt_cb = ModelCheckpoint(config=ckpt_config, directory=config.ckpt_path, prefix='{}'.format(config.local_rank))
+ callback_list.append(ckpt_cb)
+
+ new_epoch_train = config.max_epoch * steps_per_epoch // config.log_interval
+ model.train(new_epoch_train, de_dataset, callbacks=callback_list, sink_size=config.log_interval)
+
+ print('--------- Export start ---------')
+
+ for file in os.listdir(config.ckpt_path):
+ if ".ckpt" in file:
+ print("--------------file ", file)
+ print('冻结参数')
+
+ run_export_modelarts(config.ckpt_path + '/' + file, config.ckpt_path + '/')
+
+
+if __name__ == "__main__":
+ run_train()
diff --git a/research/cv/FaceRecognition/scripts/docker_start.sh b/research/cv/FaceRecognition/scripts/docker_start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7c1c17d85abfb5fdc2ae45ef6c8bde811541a93b
--- /dev/null
+++ b/research/cv/FaceRecognition/scripts/docker_start.sh
@@ -0,0 +1,38 @@
+#!/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
+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 ~/ascend/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
+ -v ~/ascend/log/npu/slog/:/var/log/npu/slog -v ~/ascend/log/npu/profiling/:/var/log/npu/profiling \
+ -v ~/ascend/log/npu/dump/:/var/log/npu/dump -v ~/ascend/log/npu/:/usr/slog ${docker_image} \
+ /bin/bash