facerecognize.cpp 18 KB


#include "facerecognize.h" FaceRecognize::FaceRecognize(){} // FaceRecognize::~FaceRecognize(){ //     net->releaseModel(); //     net->releaseSession(session1); //     net->releaseSession(session2); // } bool FaceRecognize::init_model(string model_path){     net=shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(model_path.c_str()));     ScheduleConfig config;     config.numThread=num_thread;     config.type=forward_type;     session1 = net->createSession(config);     session2 = net->createSession(config);     input_tensor1 = net->getSessionInput(session1,NULL);     input_tensor2 = net->getSessionInput(session2,NULL);     net->resizeTensor(input_tensor1,{1,3,input_size[1],input_size[0]});     net->resizeSession(session1);     net->resizeTensor(input_tensor2,{1,3,input_size[1],input_size[0]});     net->resizeSession(session2);     //数据预处理     MNN::CV::ImageProcess::Config image_config;     image_config.sourceFormat = MNN::CV::BGR;     image_config.destFormat = MNN::CV::BGR;     ::memcpy(image_config.mean,mean,sizeof(mean));     ::memcpy(image_config.normal,normal,sizeof(normal));     pretreat = shared_ptr<MNN::CV::ImageProcess>(MNN::CV::ImageProcess::create(image_config));     model_init = true;     return model_init; } cv::Mat FaceRecognize::meanAxis0(const cv::Mat &src)     {         int num = src.rows;         int dim = src.cols;          cv::Mat output(1,dim,CV_32F);         for(int i = 0 ; i <  dim; i ++)         {             float sum = 0 ;             for(int j = 0 ; j < num ; j++)             {                 sum+=src.at<float>(j,i);             }             output.at<float>(0,i) = sum/num;         }          return output;     }  cv::Mat FaceRecognize::elementwiseMinus(const cv::Mat &A,const cv::Mat &B)     {         cv::Mat output(A.rows,A.cols,A.type());          assert(B.cols == A.cols);         if(B.cols == A.cols)         {             for(int i = 0 ; i <  A.rows; i ++)             {                 for(int j = 0 ; j < B.cols; j++)                 {                     output.at<float>(i,j) = A.at<float>(i,j) - B.at<float>(0,j);                 }             }         }         return output;     }  cv::Mat FaceRecognize::varAxis0(const cv::Mat &src)     {         cv:Mat temp_ = elementwiseMinus(src,meanAxis0(src));         cv::multiply(temp_ ,temp_ ,temp_ );         return meanAxis0(temp_);      }  int FaceRecognize::MatrixRank(cv::Mat M)     {         Mat w, u, vt;         SVD::compute(M, w, u, vt);         Mat1b nonZeroSingularValues = w > 0.0001;         int rank = countNonZero(nonZeroSingularValues);         return rank;      }  cv::Mat FaceRecognize::similarTransform(cv::Mat src,cv::Mat dst) {         int num = src.rows;         int dim = src.cols;         cv::Mat src_mean = meanAxis0(src);         cv::Mat dst_mean = meanAxis0(dst);         cv::Mat src_demean = elementwiseMinus(src, src_mean);         cv::Mat dst_demean = elementwiseMinus(dst, dst_mean);         cv::Mat A = (dst_demean.t() * src_demean) / static_cast<float>(num);         cv::Mat d(dim, 1, CV_32F);         d.setTo(1.0f);         if (cv::determinant(A) < 0) {             d.at<float>(dim - 1, 0) = -1;         }         Mat T = cv::Mat::eye(dim + 1, dim + 1, CV_32F);         cv::Mat U, S, V;         SVD::compute(A, S,U, V);          // the SVD function in opencv differ from scipy .         int rank = MatrixRank(A);         if (rank == 0) {             assert(rank == 0);          } else if (rank == dim - 1) {             if (cv::determinant(U) * cv::determinant(V) > 0) {                 T.rowRange(0, dim).colRange(0, dim) = U * V;             } else {                 int s = d.at<float>(dim - 1, 0) = -1;                 d.at<float>(dim - 1, 0) = -1;                  T.rowRange(0, dim).colRange(0, dim) = U * V;                 cv::Mat diag_ = cv::Mat::diag(d);                 cv::Mat twp = diag_*V; //np.dot(np.diag(d), V.T)                 Mat B = Mat::zeros(3, 3, CV_8UC1);                 Mat C = B.diag(0);                 T.rowRange(0, dim).colRange(0, dim) = U* twp;                 d.at<float>(dim - 1, 0) = s;             }         }         else{             cv::Mat diag_ = cv::Mat::diag(d);             cv::Mat twp = diag_*V.t(); //np.dot(np.diag(d), V.T)             cv::Mat res = U* twp; // U             T.rowRange(0, dim).colRange(0, dim) = -U.t()* twp;         }         cv::Mat var_ = varAxis0(src_demean);         float val = cv::sum(var_).val[0];         cv::Mat res;         cv::multiply(d,S,res);         float scale =  1.0/val*cv::sum(res).val[0];         T.rowRange(0, dim).colRange(0, dim) = - T.rowRange(0, dim).colRange(0, dim).t();         cv::Mat  temp1 = T.rowRange(0, dim).colRange(0, dim); // T[:dim, :dim]         cv::Mat  temp2 = src_mean.t(); //src_mean.T         cv::Mat  temp3 = temp1*temp2; // np.dot(T[:dim, :dim], src_mean.T)         cv::Mat temp4 = scale*temp3;         T.rowRange(0, dim).colRange(dim, dim+1)=  -(temp4 - dst_mean.t()) ;         T.rowRange(0, dim).colRange(0, dim) *= scale;         return T;     } Mat FaceRecognize::preprocess_face(Mat image,vector<vector<float>> land){     Mat out;     cv::resize(image,out,Size(112,112));     float default1[5][2] = {              {38.2946f, 51.6963f},             {73.5318f, 51.6963f},             {56.0252f, 71.7366f},             {41.5493f, 92.3655f},             {70.7299f, 92.3655f}         };     float lands[5][2]={         {float(land[0][0]*112.0)/float(image.cols),float(land[0][1]*112.0)/float(image.rows)},         {float(land[1][0]*112.0)/float(image.cols),float(land[1][1]*112.0)/float(image.rows)},         {float(land[2][0]*112.0)/float(image.cols),float(land[2][1]*112.0)/float(image.rows)},         {float(land[3][0]*112.0)/float(image.cols),float(land[3][1]*112.0)/float(image.rows)},         {float(land[4][0]*112.0)/float(image.cols),float(land[4][1]*112.0)/float(image.rows)}     };     cv::Mat src(5,2,CV_32FC1,default1);     memcpy(src.data, default1, 2 * 5 * sizeof(float));     cv::Mat dst(5,2,CV_32FC1,lands);     memcpy(dst.data, lands, 2 * 5 * sizeof(float));     cv::Mat M = similarTransform(dst, src);     float M_[2][3]={         {M.at<float>(0,0),M.at<float>(0,1),M.at<float>(0,2)},         {M.at<float>(1,0),M.at<float>(1,1),M.at<float>(1,2)},     };         cv::Mat M__(2,3,CV_32FC1,M_);     cv::Mat align_image;     cv::warpAffine(out,align_image,M__,Size(112, 112));     return align_image; } double FaceRecognize::getMold(const vector<double>& vec) { 	int n = vec.size(); 	double sum = 0.0; 	for (int i = 0; i < n; ++i) 		sum += vec[i] * vec[i]; 	return sqrt(sum); } double FaceRecognize::cos_distance(const vector<double>& base, const vector<double>& target) { 	int n = base.size(); 	assert(n == target.size()); 	double tmp = 0.0; 	for (int i = 0; i < n; ++i) 		tmp += base[i] * target[i]; 	double simility =  tmp / (getMold(base)*getMold(target)); 	return simility; } double FaceRecognize::inference(Mat image1,Mat image2){     cv::resize(image1,image1,Size2d(input_size[0],input_size[1]));     cv::resize(image2,image2,Size2d(input_size[0],input_size[1]));     pretreat->convert(image1.data,input_size[0],input_size[1],0,input_tensor1);     pretreat->convert(image2.data,input_size[0],input_size[1],0,input_tensor2);     //推理     net->runSession(session1);     auto output1= net->getSessionOutput(session1, NULL);     //推理     net->runSession(session2);     auto output2= net->getSessionOutput(session2, NULL);     MNN::Tensor feat_tensor1(output1, output1->getDimensionType());     MNN::Tensor feat_tensor2(output2, output2->getDimensionType());     output1->copyToHostTensor(&feat_tensor1);     output2->copyToHostTensor(&feat_tensor2);     auto feature1 = feat_tensor1.host<float>();     auto feature2 = feat_tensor2.host<float>();         vector<double> v1,v2;     for(int i=0;i<int(feat_tensor1.size()/4);i++){         v1.push_back((double)feature1[i]);         v2.push_back((double)feature2[i]);     }     double cos_score=cos_distance(v1,v2);     return cos_score; } double FaceRecognize::inference(string image_path1,string image_path2){     Mat image1 = cv::imread(image_path1);     Mat image2 = cv::imread(image_path2);     cv::resize(image1,image1,Size2d(input_size[0],input_size[1]));     cv::resize(image2,image2,Size2d(input_size[0],input_size[1]));     pretreat->convert(image1.data,input_size[0],input_size[1],0,input_tensor1);     pretreat->convert(image2.data,input_size[0],input_size[1],0,input_tensor2);     //推理     net->runSession(session1);     auto output1= net->getSessionOutput(session1, NULL);     //推理     net->runSession(session2);     auto output2= net->getSessionOutput(session2, NULL);     MNN::Tensor feat_tensor1(output1, output1->getDimensionType());     MNN::Tensor feat_tensor2(output2, output2->getDimensionType());     output1->copyToHostTensor(&feat_tensor1);     output2->copyToHostTensor(&feat_tensor2);     auto feature1 = feat_tensor1.host<float>();     auto feature2 = feat_tensor2.host<float>();         vector<double> v1,v2;     for(int i=0;i<int(feat_tensor1.size()/4);i++){         v1.push_back((double)feature1[i]);         v2.push_back((double)feature2[i]);     }     double cos_score=cos_distance(v1,v2);     return cos_score; }

#include "facerecognize.h"

// FaceRecognize::~FaceRecognize(){
//     net->releaseModel();
//     net->releaseSession(session1);
//     net->releaseSession(session2);
// }

bool FaceRecognize::init_model(string model_path){
    net=shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(model_path.c_str()));
    if(nullptr==net){
        return false;
    }
    ScheduleConfig config;
    config.numThread=num_thread;
    config.type=forward_type;

    session1 = net->createSession(config);
    session2 = net->createSession(config);

    input_tensor1 = net->getSessionInput(session1,NULL);
    input_tensor2 = net->getSessionInput(session2,NULL);
    net->resizeTensor(input_tensor1,{1,3,input_size[1],input_size[0]});
    net->resizeSession(session1);
    net->resizeTensor(input_tensor2,{1,3,input_size[1],input_size[0]});
    net->resizeSession(session2);

    //数据预处理
    MNN::CV::ImageProcess::Config image_config;
    image_config.sourceFormat = MNN::CV::BGR;
    image_config.destFormat = MNN::CV::BGR;
    ::memcpy(image_config.mean,mean,sizeof(mean));
    ::memcpy(image_config.normal,normal,sizeof(normal));
    pretreat = shared_ptr<MNN::CV::ImageProcess>(MNN::CV::ImageProcess::create(image_config));
    
    return true;
}


cv::Mat FaceRecognize::meanAxis0(const cv::Mat &src)
    {
        int num = src.rows;
        int dim = src.cols;
 
        cv::Mat output(1,dim,CV_32F);
        for(int i = 0 ; i <  dim; i ++)
        {
            float sum = 0 ;
            for(int j = 0 ; j < num ; j++)
            {
                sum+=src.at<float>(j,i);
            }
            output.at<float>(0,i) = sum/num;
        }
 
        return output;
    }
 
cv::Mat FaceRecognize::elementwiseMinus(const cv::Mat &A,const cv::Mat &B)
    {
        cv::Mat output(A.rows,A.cols,A.type());
 
        assert(B.cols == A.cols);
        if(B.cols == A.cols)
        {
            for(int i = 0 ; i <  A.rows; i ++)
            {
                for(int j = 0 ; j < B.cols; j++)
                {
                    output.at<float>(i,j) = A.at<float>(i,j) - B.at<float>(0,j);
                }
            }
        }
        return output;
    }
 
cv::Mat FaceRecognize::varAxis0(const cv::Mat &src)
    {
        cv:Mat temp_ = elementwiseMinus(src,meanAxis0(src));
        cv::multiply(temp_ ,temp_ ,temp_ );
        return meanAxis0(temp_);
 
    }
 
int FaceRecognize::MatrixRank(cv::Mat M)
    {
        Mat w, u, vt;
        SVD::compute(M, w, u, vt);
        Mat1b nonZeroSingularValues = w > 0.0001;
        int rank = countNonZero(nonZeroSingularValues);
        return rank;
 
    }
 
cv::Mat FaceRecognize::similarTransform(cv::Mat src,cv::Mat dst) {
        int num = src.rows;
        int dim = src.cols;
        cv::Mat src_mean = meanAxis0(src);
        cv::Mat dst_mean = meanAxis0(dst);
        cv::Mat src_demean = elementwiseMinus(src, src_mean);
        cv::Mat dst_demean = elementwiseMinus(dst, dst_mean);
        cv::Mat A = (dst_demean.t() * src_demean) / static_cast<float>(num);
        cv::Mat d(dim, 1, CV_32F);
        d.setTo(1.0f);
        if (cv::determinant(A) < 0) {
            d.at<float>(dim - 1, 0) = -1;
        }
        Mat T = cv::Mat::eye(dim + 1, dim + 1, CV_32F);
        cv::Mat U, S, V;
        SVD::compute(A, S,U, V);
 
        // the SVD function in opencv differ from scipy .
        int rank = MatrixRank(A);
        if (rank == 0) {
            assert(rank == 0);
 
        } else if (rank == dim - 1) {
            if (cv::determinant(U) * cv::determinant(V) > 0) {
                T.rowRange(0, dim).colRange(0, dim) = U * V;
            } else {
                int s = d.at<float>(dim - 1, 0) = -1;
                d.at<float>(dim - 1, 0) = -1;
 
                T.rowRange(0, dim).colRange(0, dim) = U * V;
                cv::Mat diag_ = cv::Mat::diag(d);
                cv::Mat twp = diag_*V; //np.dot(np.diag(d), V.T)
                Mat B = Mat::zeros(3, 3, CV_8UC1);
                Mat C = B.diag(0);
                T.rowRange(0, dim).colRange(0, dim) = U* twp;
                d.at<float>(dim - 1, 0) = s;
            }
        }
        else{
            cv::Mat diag_ = cv::Mat::diag(d);
            cv::Mat twp = diag_*V.t(); //np.dot(np.diag(d), V.T)
            cv::Mat res = U* twp; // U
            T.rowRange(0, dim).colRange(0, dim) = -U.t()* twp;
        }
        cv::Mat var_ = varAxis0(src_demean);
        float val = cv::sum(var_).val[0];
        cv::Mat res;
        cv::multiply(d,S,res);
        float scale =  1.0/val*cv::sum(res).val[0];
        T.rowRange(0, dim).colRange(0, dim) = - T.rowRange(0, dim).colRange(0, dim).t();
        cv::Mat  temp1 = T.rowRange(0, dim).colRange(0, dim); // T[:dim, :dim]
        cv::Mat  temp2 = src_mean.t(); //src_mean.T
        cv::Mat  temp3 = temp1*temp2; // np.dot(T[:dim, :dim], src_mean.T)
        cv::Mat temp4 = scale*temp3;
        T.rowRange(0, dim).colRange(dim, dim+1)=  -(temp4 - dst_mean.t()) ;
        T.rowRange(0, dim).colRange(0, dim) *= scale;
        return T;
    }

Mat FaceRecognize::preprocess_face(Mat image,vector<vector<float>> land){
    Mat out;
    cv::resize(image,out,Size(112,112));
    float default1[5][2] = {  
            {38.2946f, 51.6963f},
            {73.5318f, 51.6963f},
            {56.0252f, 71.7366f},
            {41.5493f, 92.3655f},
            {70.7299f, 92.3655f}
        };

    float lands[5][2]={
        {float(land[0][0]*112.0)/float(image.cols),float(land[0][1]*112.0)/float(image.rows)},
        {float(land[1][0]*112.0)/float(image.cols),float(land[1][1]*112.0)/float(image.rows)},
        {float(land[2][0]*112.0)/float(image.cols),float(land[2][1]*112.0)/float(image.rows)},
        {float(land[3][0]*112.0)/float(image.cols),float(land[3][1]*112.0)/float(image.rows)},
        {float(land[4][0]*112.0)/float(image.cols),float(land[4][1]*112.0)/float(image.rows)}
    };
    cv::Mat src(5,2,CV_32FC1,default1);
    memcpy(src.data, default1, 2 * 5 * sizeof(float));
    cv::Mat dst(5,2,CV_32FC1,lands);
    memcpy(dst.data, lands, 2 * 5 * sizeof(float));
    cv::Mat M = similarTransform(dst, src);
    float M_[2][3]={
        {M.at<float>(0,0),M.at<float>(0,1),M.at<float>(0,2)},
        {M.at<float>(1,0),M.at<float>(1,1),M.at<float>(1,2)},
    };
    
    cv::Mat M__(2,3,CV_32FC1,M_);
    cv::Mat align_image;
    cv::warpAffine(out,align_image,M__,Size(112, 112));
    return align_image;
}

double FaceRecognize::getMold(const vector<double>& vec)
{
	int n = vec.size();
	double sum = 0.0;
	for (int i = 0; i < n; ++i)
		sum += vec[i] * vec[i];
	return sqrt(sum);
}

double FaceRecognize::cos_distance(const vector<double>& base, const vector<double>& target)
{
	int n = base.size();
	assert(n == target.size());
	double tmp = 0.0;
	for (int i = 0; i < n; ++i)
		tmp += base[i] * target[i];
	double simility =  tmp / (getMold(base)*getMold(target));
	return simility;
}

double FaceRecognize::inference(Mat image1,Mat image2){
    cv::resize(image1,image1,Size2d(input_size[0],input_size[1]));
    cv::resize(image2,image2,Size2d(input_size[0],input_size[1]));
    pretreat->convert(image1.data,input_size[0],input_size[1],0,input_tensor1);
    pretreat->convert(image2.data,input_size[0],input_size[1],0,input_tensor2);
    //推理
    net->runSession(session1);
    auto output1= net->getSessionOutput(session1, NULL);
    //推理
    net->runSession(session2);
    auto output2= net->getSessionOutput(session2, NULL);


    MNN::Tensor feat_tensor1(output1, output1->getDimensionType());
    MNN::Tensor feat_tensor2(output2, output2->getDimensionType());
    output1->copyToHostTensor(&feat_tensor1);
    output2->copyToHostTensor(&feat_tensor2);
    auto feature1 = feat_tensor1.host<float>();
    auto feature2 = feat_tensor2.host<float>();
    
    vector<double> v1,v2;
    for(int i=0;i<int(feat_tensor1.size()/4);i++){
        v1.push_back((double)feature1[i]);
        v2.push_back((double)feature2[i]);
    }
    double cos_score=cos_distance(v1,v2);
    return cos_score;
}

double FaceRecognize::inference(string image_path1,string image_path2){
    Mat image1 = cv::imread(image_path1);
    Mat image2 = cv::imread(image_path2);
    cv::resize(image1,image1,Size2d(input_size[0],input_size[1]));
    cv::resize(image2,image2,Size2d(input_size[0],input_size[1]));
    pretreat->convert(image1.data,input_size[0],input_size[1],0,input_tensor1);
    pretreat->convert(image2.data,input_size[0],input_size[1],0,input_tensor2);
    //推理
    net->runSession(session1);
    auto output1= net->getSessionOutput(session1, NULL);
    //推理
    net->runSession(session2);
    auto output2= net->getSessionOutput(session2, NULL);


    MNN::Tensor feat_tensor1(output1, output1->getDimensionType());
    MNN::Tensor feat_tensor2(output2, output2->getDimensionType());
    output1->copyToHostTensor(&feat_tensor1);
    output2->copyToHostTensor(&feat_tensor2);
    auto feature1 = feat_tensor1.host<float>();
    auto feature2 = feat_tensor2.host<float>();
    
    vector<double> v1,v2;
    for(int i=0;i<int(feat_tensor1.size()/4);i++){
        v1.push_back((double)feature1[i]);
        v2.push_back((double)feature2[i]);
    }
    double cos_score=cos_distance(v1,v2);
    return cos_score;
}