测试seetaface人脸识别引擎

来源:互联网 发布:消费资本论是传销 知乎 编辑:程序博客网 时间:2024/05/20 13:10

该测试文件需要放置在FaceIdentification/src/test目录下,为方便编译,代码预处理部分跟文件夹中test_face_verification.cpp相同。编译该文件之前,需要先完成facedetection,facealignment,faceidentification三个模块的编译。

代码如下:

#include<iostream>using namespace std;#ifdef _WIN32#pragma once#include <opencv2/core/version.hpp>#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) \  CVAUX_STR(CV_SUBMINOR_VERSION)#ifdef _DEBUG#define cvLIB(name) "opencv_" name CV_VERSION_ID "d"#else#define cvLIB(name) "opencv_" name CV_VERSION_ID#endif //_DEBUG#pragma comment( lib, cvLIB("core") )#pragma comment( lib, cvLIB("imgproc") )#pragma comment( lib, cvLIB("highgui") )#endif //_WIN32#if defined(__unix__) || defined(__APPLE__)#ifndef fopen_s#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL#endif //fopen_s#endif //__unix#include <opencv/cv.h>#include <opencv/highgui.h>#include "face_identification.h"#include "recognizer.h"#include "face_detection.h"#include "face_alignment.h"#include <dirent.h>#include "math_functions.h"#include <time.h> #include <unistd.h>#include <stdlib.h>#include <vector>#include <string>#include <iostream>#include <algorithm>#include <thread>#include <mutex>using namespace seeta;#define TEST(major, minor) major##_##minor##_Tester()#define EXPECT_NE(a, b) if ((a) == (b)) std::cout << "ERROR: "#define EXPECT_EQ(a, b) if ((a) != (b)) std::cout << "ERROR: "//声明变量==============================================================================    cv::Mat frame;      std::vector<std::string> file_name;    float temp_fea[2048];    std::mutex mtx;    bool get_face=false;    struct st_a{    std::string name;    float fea[2048];    float sim;    };    struct st_b{    std::string name;    float sim;    };    st_a * fea;//声明函数=============================================================================    void extract_from_file(std::vector<seeta::FaceInfo> &,int n );    std::vector<std::string> read_name_from_file(const char* filepath);    void extract_from_cam(seeta::FaceDetection & ,seeta::FaceAlignment & ,FaceIdentification & ,std::vector<seeta::FaceInfo> & );    void show_video(cv::VideoCapture & cap);    void show_picture(std::string filename,std::string win_name,int h_position,int v_position);//main main main==============================================================================================int main(){    const char* filepath = "/home/wd/seeta/image_storehouse";    const char* image_path = "/home/wd/seeta/picture";    std::string s_filepath = "/home/wd/seeta/image_storehouse";    cv::Mat img1;    cv::Mat img2;    cv::Mat img3;    cv::Mat img1_resize;    cv::Mat img2_resize;    cv::Mat img3_resize;    std::vector<seeta::FaceInfo> faces;    cv::Mat kong_img = cv::imread("/home/wd/seeta/kong.jpg", 1);//初始化模型===========================================================================    std::cout<<"初始化FaceDetection..."<<std::endl;    seeta::FaceDetection detector("/home/wd/seeta/model/seeta_fd_frontal_v1.0.bin");    detector.SetMinFaceSize(40);    detector.SetScoreThresh(2.f);    detector.SetImagePyramidScaleFactor(0.8f);    detector.SetWindowStep(4, 4);    std::cout<<"初始化FaceAlignment..."<<std::endl;    seeta::FaceAlignment point_detector("/home/wd/seeta/model/seeta_fa_v1.1.bin");    std::cout<<"初始化face_recognizer..."<<std::endl;    FaceIdentification face_recognizer("/home/wd/seeta/model/seeta_fr_v1.0.bin");    std::cout<<"完成模型初始化..."<<std::endl;    std::cout<<"读取照片文件名..."<<std::endl;//调用read_name_from_file得到照片名称===========================    file_name = read_name_from_file(filepath);    std::cout<<"读取到"<<file_name.size()<<"张图片..."<<std::endl;//============声明和初始化结构体==================================    fea = new st_a[file_name.size()];    st_b temp_sim[3];    for(int i = 0;i<file_name.size();i++){    fea[i].name=file_name[i];    fea[i].sim=0.0;    for(int ii = 0 ;ii<2048;ii++){        fea[i].fea[ii]=0.0;    }    }    temp_sim[0].sim=0.0;    temp_sim[1].sim=0.0;    temp_sim[2].sim=0.0;    temp_sim[0].name="无";    temp_sim[1].name="无";    temp_sim[2].name="无";//调用extract_from_file得到特征值==============================================================long t0 = cv::getTickCount();std::cout<<"打开3线程提取人脸特征..."<<std::endl;//三线程提取人脸特征    std::thread tt1(extract_from_file,std::ref(faces),0);    std::thread tt2(extract_from_file,std::ref(faces),1);    std::thread tt3(extract_from_file,std::ref(faces),2);//引用对象需要用std::ref()包装    tt1.join();    tt2.join();    tt3.join();    long t11 = cv::getTickCount();    double secs = (t11 - t0)/cv::getTickFrequency();    std::cout<<"提取特征耗时"<<secs<<"秒..."<<std::endl;    std::cout<<"已完成对图库的人脸特征提取。已提取"<<file_name.size()<<"张照片..."<<std::endl;//============================================================================================    cv::VideoCapture cap(0);    cv::namedWindow("NO1", cv::WINDOW_AUTOSIZE);    cv::moveWindow("NO1",600,100);    cv::namedWindow("NO2", cv::WINDOW_AUTOSIZE);    cv::moveWindow("NO2",850,100);    cv::namedWindow("NO3", cv::WINDOW_AUTOSIZE);    cv::moveWindow("NO3",1100,100);    std::cout<<"打开摄像头...间隔0.5秒抓取视频图像..."<<std::endl;    std::thread t1(show_video,std::ref(cap));     t1.detach();     //t1.join();    sleep(1);    while(1){        extract_from_cam(detector,point_detector,face_recognizer,faces);        if(get_face){        for(int i = 0;i<file_name.size();i++){            fea[i].sim=face_recognizer.CalcSimilarity(fea[i].fea, temp_fea);        }//对fea排序,得到temp_fea===============================================================================        for(int i = 0;i<file_name.size();i++){            if(fea[i].sim>temp_sim[2].sim){            temp_sim[2].name=fea[i].name;            temp_sim[2].sim=fea[i].sim;            if(fea[i].sim>temp_sim[1].sim){                temp_sim[2]=temp_sim[1];                temp_sim[1].name=fea[i].name;            temp_sim[1].sim=fea[i].sim;                if(fea[i].sim>temp_sim[0].sim){                temp_sim[1]=temp_sim[0];                temp_sim[0].name=fea[i].name;                temp_sim[0].sim=fea[i].sim;                }            }            }        }//显示结果============================================================================        if(temp_sim[0].sim>0.5&temp_sim[0].name != "无"){        img1 = cv::imread("/home/wd/seeta/image_storehouse/"+temp_sim[0].name, 1);        if (!img1.empty())            cv::resize(img1,img1_resize,cv::Size(0,0),250./img1.cols,250./img1.cols);            cv::imshow("NO1",img1_resize);        }        else cv::imshow("NO1",kong_img);        if(temp_sim[1].sim>0.5&temp_sim[1].name != "无"){        img2 = cv::imread("/home/wd/seeta/image_storehouse/"+temp_sim[1].name, 1);        if (!img2.empty())            cv::resize(img2,img2_resize,cv::Size(0,0),250./img2.cols,250./img2.cols);            cv::imshow("NO2",img2_resize);        }        else cv::imshow("NO2",kong_img);        if(temp_sim[2].sim>0.5&temp_sim[2].name != "无"){        img3 = cv::imread("/home/wd/seeta/image_storehouse/"+temp_sim[2].name, 1);        if (!img3.empty())            cv::resize(img3,img3_resize,cv::Size(0,0),250./img3.cols,250./img3.cols);            cv::imshow("NO3",img3_resize);        }        else cv::imshow("NO3",kong_img);        std::cout<<"比对结果别分是:第一..."<<temp_sim[0].name<<"相似度是"<<temp_sim[0].sim<<std::endl;        std::cout<<"比对结果别分是:第二..."<<temp_sim[1].name<<"相似度是"<<temp_sim[1].sim<<std::endl;        std::cout<<"比对结果别分是:第三..."<<temp_sim[2].name<<"相似度是"<<temp_sim[2].sim<<std::endl<<std::endl;        cv::waitKey(500);        temp_sim[0].sim=0.0;            temp_sim[1].sim=0.0;            temp_sim[2].sim=0.0;        temp_sim[0].name="无";            temp_sim[1].name="无";            temp_sim[2].name="无";        }    else cv::waitKey(500);    }    return 1;}//工具函数======================================================================void show_picture(std::string filename,std::string win_name,int h_position,int v_position){    cv::Mat img = cv::imread(filename, 1);    cv::namedWindow(win_name, cv::WINDOW_AUTOSIZE);    cv::moveWindow(win_name,h_position,v_position);    cv::imshow(win_name, img);    sleep(5);    img.release();    cv::destroyWindow(win_name);}//工具函数======================================================================std::vector<std::string> read_name_from_file(const char* filepath){    std::vector<std::string> files;      DIR * dir;    struct dirent * ptr;    std::string p = ".";    std::string pp = "..";    dir = opendir(filepath);    while((ptr = readdir(dir)) != NULL) {    if((ptr->d_name != p)&(ptr->d_name != pp))        files.push_back(ptr->d_name);    }    closedir(dir);    return files;}//工具函数================================================================================================void extract_from_file(std::vector<seeta::FaceInfo> & faces,int n ){    seeta::FaceDetection detector("/home/wd/seeta/model/seeta_fd_frontal_v1.0.bin");    detector.SetMinFaceSize(40);    detector.SetScoreThresh(2.f);    detector.SetImagePyramidScaleFactor(0.8f);    detector.SetWindowStep(4, 4);    seeta::FaceAlignment point_detector("/home/wd/seeta/model/seeta_fa_v1.1.bin");    FaceIdentification face_recognizer("/home/wd/seeta/model/seeta_fr_v1.0.bin");    cv::Mat img_color;     cv::Mat img_gray;    seeta::ImageData img_data_color;    seeta::ImageData img_data_gray;    std:string file_dir_path = "/home/wd/seeta/image_storehouse";    seeta::FacialLandmark gallery_points[5];    for(int i = n;i<file_name.size();i=i+3){    if(i%10==0) std::cout<<"正在处理第"<<i<<"张图片\n";        img_color = cv::imread(file_dir_path+"/"+file_name[i], 1);        cv::cvtColor(img_color, img_gray, CV_BGR2GRAY);    img_data_gray.data = img_gray.data;        img_data_gray.width = img_gray.cols;        img_data_gray.height = img_gray.rows;        img_data_gray.num_channels = img_gray.channels();    img_data_color.data = img_color.data;        img_data_color.width = img_color.cols;        img_data_color.height = img_color.rows;        img_data_color.num_channels = img_color.channels();        faces = detector.Detect(img_data_gray);        if(faces.size()==0){        std::cout<<file_name[i]<<"中没有找到人脸!!!,已将该图片特征置零!!!"<<std::endl;        faces.clear();        }    else{        point_detector.PointDetectLandmarks(img_data_gray, faces[0], gallery_points);        face_recognizer.ExtractFeatureWithCrop(img_data_color, gallery_points, fea[i].fea);        faces.clear();    }    }}//工具函数================================================================================================void extract_from_cam(seeta::FaceDetection & detector,seeta::FaceAlignment & point_detector,FaceIdentification & face_recognizer,std::vector<seeta::FaceInfo> & faces){    seeta::FacialLandmark gallery_points[5];    cv::Mat gray_frame;//lock=============================================    mtx.lock();     cv::Mat iiframe = frame.clone();    mtx.unlock(); //unlock=============================================    cv::cvtColor(iiframe, gray_frame, cv::COLOR_BGR2GRAY);    ImageData img_data_color(iiframe.cols, iiframe.rows, iiframe.channels());    img_data_color.data = iiframe.data;    ImageData img_data_gray(gray_frame.cols, gray_frame.rows, gray_frame.channels());    img_data_gray.data = gray_frame.data;    faces = detector.Detect(img_data_gray);    if(faces.size()==0){    std::cout<<"摄像机中没有找到人脸!!!"<<std::endl;    faces.clear();    get_face = false;    }    else{    get_face = true;    point_detector.PointDetectLandmarks(img_data_gray, faces[0], gallery_points);    face_recognizer.ExtractFeatureWithCrop(img_data_color, gallery_points, temp_fea);    faces.clear();    }}//工具函数==========================================================================void show_video(cv::VideoCapture & cap){    seeta::FaceDetection detector("/home/wd/seeta/model/seeta_fd_frontal_v1.0.bin");    detector.SetMinFaceSize(40);    detector.SetScoreThresh(2.f);    detector.SetImagePyramidScaleFactor(0.8f);    detector.SetWindowStep(4, 4);        cv::Mat gray_frame;     cv::Mat iframe;    cv::Mat iframe_resize;         bool stop = false;          cv::Rect face_rect;        seeta::ImageData img_data;    std::vector<seeta::FaceInfo> ifaces;    cv::namedWindow("video", cv::WINDOW_AUTOSIZE);    cv::moveWindow("video",100,100);    while(!stop){  //lock=============================================        mtx.lock();    cap>>frame;     iframe = frame.clone();    mtx.unlock(); //unlock=============================================    cv::cvtColor(iframe, gray_frame, cv::COLOR_BGR2GRAY);        img_data.data = gray_frame.data;        img_data.width = gray_frame.cols;        img_data.height = gray_frame.rows;        img_data.num_channels = 1;        ifaces = detector.Detect(img_data);    int32_t num_face = static_cast<int32_t>(ifaces.size());        for (int32_t i = 0; i < num_face; i++) {            face_rect.x = ifaces[i].bbox.x;            face_rect.y = ifaces[i].bbox.y;            face_rect.width = ifaces[i].bbox.width;            face_rect.height = ifaces[i].bbox.height;        cv::rectangle(iframe, face_rect, CV_RGB(0, 0, 255), 4, 8, 0);        }    cv::resize(iframe,iframe_resize,cv::Size(0,0),500./iframe.cols,500./iframe.cols);        cv::imshow("video",iframe_resize);     ifaces.clear();        cv::waitKey(33);    }      cv::destroyWindow("video");}

测试结果是,用了350张图片寸照作为比对的图像库,用摄像头作为被比对图片的源,对单位8个同事做比对,均比对成功。

===========================================================
========= 以下是使用单个模块作测试============================

facedetection模块的运行所需时间最长,2K的图片,i5cpu单核处理所需时间为0.2秒。
以下是打印的信息。

Detections takes 0.209119 seconds OpenMP is used.SSE is used.Image size (wxh): 1200x1797

对于一张2K的图片,三个模块的运行时长:
以下是打印的信息。

人脸检测耗时0.208081...人脸对齐耗时0.00803882...提取特征耗时0.1143...比对特征耗时4.217e-06...相似度为:0.661551
0 0