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

环境

Ubuntu ,opencv3

数据准备

原始深度图(已标定过人脸位置) 百度云盘:https://pan.baidu.com/s/1Hi85o521oIGaAfDoavOXeA
使用MATLAB进行数据采集与处理:

1、运行dataGet_MATLAB/position_process.m,进行深度图片的人脸位置的快速批量标定,鼠标框出人脸位置,自动生成同名包含位置信息的txt文件。(百度云盘中已包含人脸位置信息,可跳过此步)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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空文件夹用来存放生成的正负训练样本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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

模型训练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#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中

模型测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#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

0%