人脸深度图活体检测_SVM(Ubuntu+opencv3)

环境

Ubuntu ,opencv3

数据准备

原始深度图(已标定过人脸位置) 百度云盘:https://pan.baidu.com/s/1Hi85o521oIGaAfDoavOXeA
使用MATLAB进行数据采集与处理:
1、运行dataGet_MATLAB/position_process.m,进行深度图片的人脸位置的快速批量标定,鼠标框出人脸位置,自动生成同名包含位置信息的txt文件。(百度云盘中已包含人脸位置信息,可跳过此步)

clc
clear
RAW_PATH = '/home/zhoujie/liveness detection/zjraw/face/';
file =dir([RAW_PATH ,'*.raw']);
for num=1:length(file)
f1 = fopen([RAW_PATH,file(num).name], 'r');
data0 = fread(f1, 'uint16');
fclose(f1);
img1 = reshape(data0, 400, 345);
dep_img = img1';
imshow(dep_img,[350,800]); 
mouse=imrect; 
pos=getPosition(mouse)% x1 y1 w h 
pos=round(pos);
txtname = strrep(file(num).name,'.raw','.txt');
fp=fopen([RAW_PATH,txtname],'a');
fprintf(fp,'%i %i %i %i\n',pos); 
fclose(fp);
end

2、运行dataGet_MATLAB/faceGet_process.m,进行人脸深度图的批量处理 ,需提前新建/data/face与/data/non-face空文件夹用来存放生成的正负训练样本

clc
clear
RAW_PATH = '/home/zhoujie/liveness detection/zjraw/face/';
jpg_path = '/home/zhoujie/liveness detection/svm/data/face/';
file =dir([RAW_PATH ,'*.raw']);
for j=1:length(file)
    try
        f1 = fopen([RAW_PATH,file(j).name], 'r');
        txtname = strrep(file(j).name,'.raw','.txt');
        [par1,par2,par3,par4] = textread([RAW_PATH,txtname],'%d%d%d%d',1);
        data0 = fread(f1, 'uint16');
        fclose(f1);
        img1 = reshape(data0, 400, 345);
        dep_img = img1';
        try
            face = dep_img(par2 :par2 +par4-2,par1 :par1 + par3-2);
        catch
             if par2 +par4-2 >345
                 face_height = 345;
             else
                 face_height = par2 +par4-2;
             end
             if par1 +par3-2 >400
                face_weight = 400;
             else
                face_weight = par1 +par3-2;
             end
             face = dep_img(par2 :face_height,par1 :face_weight);
        end
        [m,n]=size(face);
         faceData = reshape(face, 1, m*n);
         faceData(find(faceData==0))=[];
         able = 0;total = 0;
         for i =1:1000
             num = randperm(length(faceData),1);
             facePlane = faceData(num);
             distance = abs([-1,faceData(num)]*[faceData;ones(1,length(faceData))]);
             total=sum(distance<30); 
             if total>able           
                able=total;
                bestfacePlane=facePlane;
             end
         end
         xmax = bestfacePlane+50;
         xmin = bestfacePlane-50;
         face(find(face > xmax ))=xmax; 
         face(find(face < xmin ))=xmin; 
         ymax=255;ymin=0; 
         OutImg = round((ymax-ymin)*(face-xmin)/(xmax-xmin) + ymin); %归一化并取整
         Outface=uint8(OutImg); 
         Outface = imresize(Outface, [40 40]);
         jpgname = [jpg_path,num2str(j+538),'.jpg'];
         imwrite(Outface,jpgname);      
    catch
        disp(file(j).name)
    end
end

在这里插入图片描述
新建文件夹data/train_image/1、data/train_image/0、data/test_image/1、data/test_image/0
data/face文件夹中的五分之四复制到data/train_image/1,剩下的复制到data/test_image/1
data/non-face文件夹中的五分之四复制到data/train_image/0,剩下的复制到data/test_image/0

模型训练

#include <iostream> 
#include <string.h>
#include<time.h>
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/ml/ml.hpp>  
#include <dirent.h>

using namespace std; 
using namespace cv;
using namespace cv::ml;

void getFiles( string path, vector<string>& files); 
void get_num(int num, Mat& trainingImages, vector<int>& trainingLabels); 

int main() 
{ 
    //获取训练数据 
    Mat classes; 
    Mat trainingData;
    Mat trainingImages; 
    vector<int> trainingLabels;
    get_num(0, trainingImages, trainingLabels);
    get_num(1, trainingImages, trainingLabels);
    
    Mat(trainingImages).copyTo(trainingData); 
    trainingData.convertTo(trainingData, CV_32FC1); 
    Mat(trainingLabels).copyTo(classes); 
	
    //配置SVM训练器参数 
    Ptr<SVM> svm = SVM::create();   
    svm->setType(SVM::C_SVC);    
    svm->setKernel(SVM::LINEAR); 
    
    Ptr<TrainData> tData =TrainData::create(trainingData, ROW_SAMPLE, classes);
    cout << "SVM: start train ..." << endl;

    clock_t start,finish;
    double totaltime;
    start=clock();

    svm->trainAuto(tData);  
    svm->save("svm.xml");
    cout<<"SVM: TRAIN SUCCESS !"<<endl; 
    finish=clock();
    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
    cout<<"TRAIN TIME : "<<totaltime<<" S !"<<endl;
    // getchar(); 
    return 0; 
} 

void getFiles( string path, vector<string>& files ) 
{ 
    DIR *dir;
	struct dirent *ptr;

    if ((dir=opendir(path.c_str())) == NULL)
    {
		perror("Open path error...");
        exit(1);
    }

    while ((ptr=readdir(dir)) != NULL) 
    { 
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir 
            continue; 
        else if(ptr->d_type == 8) ///file 
            {
                files.push_back(ptr->d_name); 
            }
        else if(ptr->d_type == 10) ///link file 
            {continue; }
        else if(ptr->d_type == 4) ///dir 
        { 
            files.push_back(ptr->d_name); 
        } 
    } 
    closedir(dir);
    sort(files.begin(), files.end());
}

void get_num(int num, Mat& trainingImages, vector<int>& trainingLabels) 
{ 
    string numpath = "/home/zhoujie/liveness detection/svm/data/train_image/";
    char char_num[2];
    sprintf(char_num,"%d",num);
    string str_num = char_num;
    string str = numpath + str_num;
    const char* filePath = str.data();
    string base;
    vector<string> files;
    getFiles(filePath, files); 
    int number = files.size(); 
    for (int i = 0;i < number;i++) 
    { 
        // cout << "*************************** n = " << i << " ************************************ "<< endl; 
        base = str + "/" + files[i];
        Mat SrcImage=imread(base.c_str()); 
        SrcImage= SrcImage.reshape(1, 1); 
        // cout << SrcImage << endl; 
        trainingImages.push_back(SrcImage); 
        trainingLabels.push_back(num); 
    } 
}

运行 svm_train.cpp

g++ svm_train.cpp `pkg-config --cflags --libs opencv` -o svm_train
./ svm_train

生成的SVM模型存储在根目录的svm.xml中

模型测试

#include <iostream>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/ml/ml.hpp>  
#include <string.h>
#include <dirent.h>

using namespace std; 
using namespace cv; 

void getFiles( string path, vector<string>& files ); 

int main() 
{ 
    for (int num = 0; num < 2; num ++) 
    {
        int response;
        int result = 0; 
        float accuracy;
        string numpath = "/home/zhoujie/liveness detection/svm/data/test_image/";
        char char_num[2];
        sprintf(char_num,"%d",num);
        string str_num = char_num;
        string str = numpath + str_num;
        const char* filePath = str.data();
        string base;
        vector<string> files; 
        getFiles(filePath, files ); 
        int number = files.size(); 
        cout <<"文件夹"<< num <<" 共有测试图片 " <<number <<" 张"<< endl;
        Ptr<ml::SVM>svm = ml::SVM::load("svm.xml");
    
        for (int i = 0;i < number;i++) 
        { 
            base = str + "/" + files[i];
            Mat inMat = imread(base.c_str()); 
            Mat p = inMat.reshape(1, 1); 
            p.convertTo(p, CV_32FC1); 
            response = (int)svm->predict(p);  // 核心代码,将检测的图片的标签返回回来,结果保存在response中
            // cout << "识别的数字为:" << response << endl;
            if (response == num) 
            { 
                result++; 
            } 
	 // else
	 // {
	 //	 cout << base.c_str() << " ERROR ! " << endl;
         // }
         } 
        accuracy = result*1.0/number;
        cout << "识别正确 " << result <<" 张,准确率: "<< accuracy << endl;
    }
    return 0; 
} 

void getFiles( string path, vector<string>& files ) 
{ 
    DIR *dir;
	struct dirent *ptr;

    if ((dir=opendir(path.c_str())) == NULL)
    {
		perror("Open path error...");
        exit(1);
    }

    while ((ptr=readdir(dir)) != NULL) 
    { 
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir 
            continue; 
        else if(ptr->d_type == 8) ///file 
            {
                files.push_back(ptr->d_name); 
            }
        else if(ptr->d_type == 10) ///link file 
           { 
		continue; 
	   }
        else if(ptr->d_type == 4) ///dir 
           { 
                files.push_back(ptr->d_name); 
           } 
    } 
    closedir(dir);
    sort(files.begin(), files.end());
}

运行 svm_test.cpp

g++ svm_test.cpp `pkg-config --cflags --libs opencv` -o svm_test
./ svm_test

运行结果

在这里插入图片描述
项目地址 :https://github.com/zj19941113/FaceLivenessDetection_SVM

猜你喜欢

转载自blog.csdn.net/ffcjjhv/article/details/84260060