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