关于dlib的人脸关键点的提取
1. dlib
- 认识dlib:http://dlib.net/
- 下载相应版本,cmake编译生成dlib和example,参见:http://dlib.net/compile.html,运行一下face detection 应该不会报错。
注意选中:DLIB_PNG_SUPPORT 和 DLIB_JPEG_SUPPORT
如果其中遇到一些问题可以翻墙参考:http://blog.dlib.net/2014/08/real-time-face-pose-estimation.html
2.训练dlib的数据集
人脸关键点标识:参见:https://ibug.doc.ic.ac.uk/resources/300-W/
dlib用于训练的数据格式和公开数据集的格式不太相同,能找到的有限,不过这些也就足够了。
68points的训练集可以在这里下载。
194points的数据集:http://stackoverflow.com/questions/36711905/dlib-train-shape-predictor-ex-cpp?answertab=votes#tab-top
194的数据集的下载需要翻墙。
关于其他点数的数据集 : 我的办法是,下载上述数据集;对应着关键点位置去提取需要的点,提取你想要的点之后,重新组成新的标签。
dlib关键点 face alignment 训练
- 关于dlib中train_shape_predictor_ex的注释,作者已经写的很清晰了,具体参数可以论文和实际需要做调整。
我只修改了不同的决策树的深度参数:trainer.set_tree_depth( )
树的深度会很影响整个模型的大小,训练5个点,不同深度模型大小有1.4M,11M,370M不同。根据各自的需要训练不同的model才是实际工程需要。遇到两个问题:
(1)首当其冲的就是内存不足,因为读图不像caffe是读batch,而是读入全部的图,数据集中又有了mirror图像增加了数据集的数量。
解决办法也是很粗暴,换大电脑。8G内存不够,换的16G内存的电脑,解决。(2)第二个问题应该不是谁都能遇到的,换16G电脑发现无法读PNG格式图片,我CMAKE的时候没有问题,在8G电脑也没问题,但是这里face detection和face alignment所有读PNG的都读不了报错。我已经崩溃,幸亏在师妹的帮助下才找到这个原因她又用了opencv去读的图。师妹非常有耐心,这方面比我强好多。
/*array2d<unsigned char> img;
load_image(img, argv[i])*/
array2d<unsigned char> img;
Mat Img=imread(argv[i]);
dlib::assign_image(img,dlib::cv_image<bgr_pixel> (Img));
dlib关键点模型的测试
1. input
关于dlib中 face_landmark_detection_ex的注释,作者已经写的很清晰了。
替换成为了自己的速度更快的人脸检测器,只是用了sp函数,其他全部做了修改:
//read img list&path
std::ifstream infile("D:/Datasets/.../Path_Images.txt");
string image_path;
std::vector<string> image_paths;
while(infile>>image_path)
{
image_paths.push_back(image_path);
}
//output as one sigle txt
//ofstream outfile("D:/Datasets/.../output.txt",ios::out);
2. output
根据不同需求不同输出
//output as individual txt
ofstream outfile(filename+".txt",ios::out);
int len = shapes.size();
std::cout<<"Number of shapes: "<<len<<endl;
for(auto &iter: shapes)
{
for(unsigned int i =0; i<5;++i){
outfile<<iter.part(i).x()<<' ';
outfile<<iter.part(i).y()<<endl;
}
}
outfile.close();
//output as one sigle txt
for(int i =0;i <shapes.size();++i)
{
for(int j = 0; j<5; ++j){
outfile<<shapes[i].part(j).x()<<' ';
outfile<<shapes[i].part(j).y()<<endl;
}
}
总结: 快速实现一种算法是科研训练必不可绕的路。