编译dlib
从官方网站下载
准备好人脸数据
准备好人脸数据,放入各自的文件夹,然后给文件夹起好名字,这里就是人的名字拼音首字。准备好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);
_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)
{
if (findData.name[0] != '.')
names.push_back(findData.name);
}
else
{
}
} while (_findnext(handle, &findData) == 0);
_findclose(handle);
}
int face_reco::load_db_faces_prepare(string folder)
{
deserialize("./shape_predictor_68_face_landmarks.dat") >> sp;
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;
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;
load_image(img, path);
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);
desc.face_chip = face_chip;
std::vector<matrix<rgb_pixel>> face_chip_vec;
std::vector<matrix<float, 0, 1>> face_all;
face_chip_vec.push_back(move(face_chip));
face_all = net(face_chip_vec);
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;
}
iter++;
}
}
以上过程就是程序拿到取走文件夹中所有文件进行学习,实际上dlib本身是使用的dnn方式来训练网络数据的。
调用过程
#include "face_recognition_dlib.h"
#include "Sort_method.h"
#include <vector>
#include <string>
using namespace std;
#include <io.h>
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)
{
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;
load_image(face_cap, argv[1]);
image_window win(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));
}
if (vect_faces.size() != 1)
{
cout << "Capture face error! face number " << vect_faces.size() << endl;
return -1;
}
std::vector<matrix<float, 0, 1>> face_cap_desc = face_recognize.net(vect_faces);
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);
}
else
{
cout << "This face from database is not match the face, continue!" << endl;
}
}
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;
}
getchar();
return 0;
}
以上就是整个训练和使用过程,比较简单,读者可以继续深入研究,比如人脸图片曝光过强去除,人脸对齐等等,都是需要调整的,上面代码并不包含这些。
|