从官方网站下载
准备好人脸数据,放入各自的文件夹,然后给文件夹起好名字,这里就是人的名字拼音首字。准备好test数据
test数据也是图片,一次对比一张,其外,还要有dlib的face模型,包含两个文件,一个是dlib_face_recognition_resnet_model_v1.dat和shape_predictor_68_face_landmarks.dat,两个文件,在运行过程中必须加载
//查找文件夹下面的所有文件夹
//人名的文件夹
void face_reco::listfiles(std::string dir,std::string namefolder)
{
intptr_t handle;
_finddata_t findData;
string dirfilter =dir + "/" + namefolder + "/" + "*.*";
handle = _findfirst(dirfilter.c_str(), &findData); // 查找目录中的第一个文件
if (handle == -1)
{
cout << "Failed to find first file!\n";
return;
}
face_desc desc;
desc.name = namefolder;//子文件夹的名称为人名
do
{
if (!(findData.attrib & _A_SUBDIR))
desc.files.push_back(findData.name);
} while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
//cout << "Done!\n";
_findclose(handle); // 关闭搜索句柄
face_desc_vec.push_back(desc);
}
void face_reco::listfolder(std::string dir, std::vector<string> & names)
{
intptr_t handle;
_finddata_t findData;
string dirfilter = dir + "/" + "*.*";
handle = _findfirst(dirfilter.c_str(), &findData); // 查找目录中的第一个文件
if (handle == -1)
{
cout << "Failed to find first file!\n";
return;
}
do
{
if (findData.attrib & _A_SUBDIR)
//&& strcmp(findData.name, ".") != 0
//&& strcmp(findData.name, "..") != 0
//) // 是否是子目录并且不为"."或".."
{
if (findData.name[0] != '.')
names.push_back(findData.name);
//cout << findData.name << "\t\n";
}
else //否则是文件
{
//子文件
//face_desc_vec.files.push_back(findData.name);
}
//cout << findData.name << "\t" << findData.size << endl;
} while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
//cout << "Done!\n";
_findclose(handle); // 关闭搜索句柄
}
int face_reco::load_db_faces_prepare(string folder)
{
// We will also use a face landmarking model to align faces to a standard pose: (see face_landmark_detection_ex.cpp for an introduction)
deserialize("./shape_predictor_68_face_landmarks.dat") >> sp;
// And finally we load the DNN responsible for face recognition.
deserialize("./dlib_face_recognition_resnet_model_v1.dat") >> net;
std::vector<string> vecs;
listfolder(folder.c_str(), vecs);
auto iter = vecs.begin();
while(iter != vecs.end())
{
//文件夹名称就是人名
string name = *iter;
cout << name << endl;
//string mfolder = folder + "/" + name;
listfiles(folder,name);
iter++;
}
//把所有的文件都放到数据结构中,开始读取并且获取值
load_faces(folder);
return 0;
}
void face_reco::load_faces(string folder)
{
frontal_face_detector detector = get_frontal_face_detector();
auto iter = face_desc_vec.begin();
while (iter != face_desc_vec.end())
{
face_desc &desc = *iter;
matrix<rgb_pixel> img;
string path = folder + "/" + desc.name +"/"+ desc.files[0];
cout <<"path is " << path << endl;
//char path[260];
//sprintf_s(path, "%s/%s/%s", folder.c_str(),desc.name.c_str(),desc.files[0].c_str());
load_image(img, path);
//image_window win(img);
for (auto face : detector(img))
{
auto shape = sp(img, face);
matrix<rgb_pixel> face_chip;
extract_image_chip(img, get_face_chip_details(shape, 150, 0.25), face_chip);
//Record the all this face's information
//FACE_DESC sigle_face;
desc.face_chip = face_chip;
//sigle_face.name = fileinfo.name;
std::vector<matrix<rgb_pixel>> face_chip_vec;
std::vector<matrix<float, 0, 1>> face_all;
face_chip_vec.push_back(move(face_chip));
//Asks the DNN to convert each face image in faces into a 128D vector
face_all = net(face_chip_vec);
//Get the feature of this person
std::vector<matrix<float, 0, 1>>::iterator iter_begin = face_all.begin(),
iter_end = face_all.end();
if (face_all.size() > 1) break;
desc.face_feature = *iter_begin;
//all the person description into vector
//face_desc_vec.push_back(sigle_face);
}
iter++;
}
}
以上过程就是程序拿到取走文件夹中所有文件进行学习,实际上dlib本身是使用的dnn方式来训练网络数据的。
#include "face_recognition_dlib.h"
#include "Sort_method.h"
#include
#include
using namespace std;
#include
typedef struct face_pics
{
string name;
std::vector<string> pics;
}face_pics;
int load_folder_jpg()
{
return 0;
}
face_reco face_recognize;
int compareone(face_desc &desc)
{
return 0;
}
int main(int argc, char** argv)
{
//std::vector folder;
//listFiles("H:/git/dlib/qb_recognize/qbrecog/bin/face/*.*",folder, true);
//FACE_RECOGNITION dlib;
if (argc == 1)
{
cout << "Give some image files as arguments to this program." << endl;
return 0;
}
cout << "processing image " << argv[1] << endl;
std::string ff = "face";
face_recognize.load_db_faces_prepare(ff);
matrix<rgb_pixel> face_cap;
//save the capture in the project directory
load_image(face_cap, argv[1]);
image_window win(face_cap);
//Display the raw image on the screen
//image_window win1(face_cap);
frontal_face_detector detector = get_frontal_face_detector();
std::vector<matrix<rgb_pixel>> vect_faces;
for (auto face : detector(face_cap))
{
auto shape = face_recognize.sp(face_cap, face);
matrix<rgb_pixel> face_chip;
extract_image_chip(face_cap, get_face_chip_details(shape, 150, 0.25), face_chip);
vect_faces.push_back(move(face_chip));
//win1.add_overlay(face);
}
if (vect_faces.size() != 1)
{
cout << "Capture face error! face number " << vect_faces.size() << endl;
return -1;
}
//Use DNN and get the capture face's feature with 128D vector
std::vector<matrix<float, 0, 1>> face_cap_desc = face_recognize.net(vect_faces);
//Browse the face feature from the database, and find the match one
std::pair<double, std::string> candidate_face;
std::vector<double> len_vec;
std::vector<std::pair<double, std::string>> candi_face_vec;
candi_face_vec.reserve(256);
cout << "face find " << face_recognize.face_desc_vec.size() << endl;
for (size_t i = 0; i < face_recognize.face_desc_vec.size(); ++i)
{
auto len = length(face_cap_desc[0] - face_recognize.face_desc_vec[i].face_feature);
cout << "len is " << len << endl;
if (len < 0.4)
{
len_vec.push_back(len);
candidate_face.first = len;
candidate_face.second = face_recognize.face_desc_vec[i].name.c_str();
candi_face_vec.push_back(candidate_face);
//#ifdef _FACE_RECOGNIZE_DEBUG
// char buffer[256] = { 0 };
// sprintf_s(buffer, "Candidate face %s Euclid length %f",
// face_recognize.face_desc_vec[i].name.c_str(),
// len);
// MessageBox(CString(buffer), NULL, MB_YESNO);
//#endif
}
else
{
cout << "This face from database is not match the face, continue!" << endl;
}
}
//Find the most similar face
if (len_vec.size() != 0)
{
shellSort(len_vec);
int i(0);
for (i = 0; i != len_vec.size(); i++)
{
if (len_vec[0] == candi_face_vec[i].first)
break;
}
char buffer[256] = { 0 };
sprintf_s(buffer, "The face is %s -- Euclid length %f",
candi_face_vec[i].second.c_str(), candi_face_vec[i].first);
cout << buffer << endl;
/*if (MessageBox(CString(buffer), NULL, MB_YESNO) == IDNO)
{
face_record();
}*/
}
else
{
cout << "not found" << endl;
/*if (MessageBox(CString("Not the similar face been found"), NULL, MB_YESNO) == IDYES)
{
face_record();
}*/
}
//char a;
getchar();
return 0;
}
以上就是整个训练和使用过程,比较简单,读者可以继续深入研究,比如人脸图片曝光过强去除,人脸对齐等等,都是需要调整的,上面代码并不包含这些。