9cf21234 by 乔峰昇

update readme

1 parent 1ee93083
MNN1.0.0+opencv
信息结构体
struct OutputInfo{
int error_code;
bool result;
};
struct InitModelError{
vector<bool> init_error;
};
模型初始化
FaceComparison face_rec=FaceComparison(det_model_path,landm_model_path,rec_model_path)
InitModelError init_model_code;
FaceComparison face_rec = FaceComparison();
bool init_model = face_rec.init_model(face_det_model,face_landm_model,face_rec_model,init_model_code);
det_model_path:人脸检测模型retinaface的模型路径
landm_model_path:106人脸关键点模型的模型路径
rec_model_path:人脸识别模型的模型路径
init_model_code:保存每个模型初始化状态true/false
重要参数(include/facecomparison.h文件)
......@@ -24,13 +38,18 @@ FaceComparison face_rec=FaceComparison(det_model_path,landm_model_path,rec_model
接口(返回结果 bool:true/false)
bool inference(string image_path1,string image_path2);参数为两张图像地址,其中iamge1_path为face_id图像输入
bool inference(Mat image1,Mat image2);参数为两张opencv读取的图像矩阵,其中iamge1为face_id图像输入
int inference(string image_path1,string image_path2,OutputInfo &output_info);参数为两张图像地址,其中iamge1_path为face_id图像输入
int inference(Mat image1,Mat image2,OutputInfo &output_info);参数为两张opencv读取的图像矩阵,其中iamge1为face_id图像输入
调用方式
OutputInfo output_info;
int result = face_rec.inference(image1,image2,output_info);
编译
将CMakeLists.txt 中 set(FACECOMPARISON_DIR /home/situ/qfs/sdk_project/mnn_projects/face_recognize_mnn/lib)
改为lib文件夹所在的绝对地址
将CMakeLists.txt 中 set(FACECOMPARISON_DIR /home/situ/qfs/sdk_project/mnn_projects/face_recognize_mnn/include)
改为include文件夹所在的绝对地址
mkdir build
cd build
cmake ..
......
#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(){
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!