如何用dlib实现dlib 人脸检测测

基于深度学习的人脸识别系统系列(Caffe+OpenCV+Dlib)——【五】设计人脸识别的注册类 - 博客频道 - CSDN.NET
Mr_Curry的博客
vehicle engineering,interested in artificial intelligence..hahah
分类:人脸识别
基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库)、Caffe(深度学习库)、Dlib(机器学习库)、libfacedetection(人脸检测库)、cudnn(gpu加速库)。
用到了一个开源的深度学习模型:VGG model。
最终的效果是很赞的,识别一张人脸的速度是0.039秒,而且最重要的是:精度高啊!!!
CPU:intel i5-4590
GPU:GTX 980
系统:Win 10
OpenCV版本:3.1(这个无所谓)
Caffe版本:Microsoft caffe (微软编译的Caffe,安装方便,在这里安利一波)
Dlib版本:19.0(也无所谓
CUDA版本:7.5
cudnn版本:4
libfacedetection:6月份之后的(这个有所谓,6月后出了64位版本的)
这个系列纯C++构成,有问题的各位朋同学可以直接在博客下留言,我们互相交流学习。
====================================================================
本篇是该系列的第五篇博客,介绍设计一个人脸识别的注册类与识别类用于具体的识别任务。
回顾一下这个系列的前四篇博文,把人脸识别的整个任务剖析为了一个个的小任务。我们现在希望用我们定义的这些接口能够非常方便的进行人脸识别的任务,而且可以实现很短的时间内就匹配一个人脸。我们现在希望,可以将其用于一个具体的分类任务中。
我们可以自己来定义这个任务:假设我有20个人要进行人脸识别,我们希望通过我们设计的代码来实现这个任务。如何方便而又快捷的进行实现呢?
这里考虑设计两个类:Register与Recognition。当有人需要注册时,其信息会添加入Register类中的某个成员空间,这里我们用到的信息可以稍微简单一点:
姓名、注册图片、人脸空间。
其中姓名、注册图片是必须要的,而这个人脸空间的意思就是:我们可以实现很多不同场景下的人脸识别。比如在考勤方面,学校想要人脸识别时,受限于人脸数目众多,不可能把所有的人都放在一个数据库里。这个时候我们可以某个信息来区分他们,比如说:课程。 课程这个信息就可以算作一个人脸空间。当我们进行具体的识别时,只会在相应的人脸空间内进行匹配,而不会在其他的人脸空间内匹配。
由于在上一篇博客我们介绍了如何使用CUBLAS来进行人脸向量的运算,那么我们需要对代码进行一些修改,将其换为二维数组。
ExtractFeature.h:
#include &opencv.hpp&
using namespace
using namespace std;
float* ExtractFeature_(Mat FaceROI);
vector&float& ExtractFeature(Mat FaceROI);
void Caffe_Predefine();
在这里面添加相应的函数ExtractFeature.cpp:
float* ExtractFeature_(Mat FaceROI)
caffe::Caffe::set_mode(caffe::Caffe::GPU);
std::vector&Mat&
std::vector&int& testL
test.push_back(FaceROI);
testLabel.push_back(0);
memory_layer-&AddMatVector(test, testLabel);
test.clear();
testLabel.clear();
std::vector&caffe::Blob&float&*& input_
net-&Forward(input_vec);
boost::shared_ptr&caffe::Blob&float&& fc8 = net-&blob_by_name("fc8");
int test_num = 0;
float FaceVector[2622];
while (test_num & 2622)
FaceVector[test_num] = (fc8-&data_at(0, test_num, 1, 1));
test_num++;
return FaceV
我们希望整个类能够具有这样一些功能:可以新加入人脸到某个人脸空间中,可以将人脸空间中的人脸提取出来保存到一个矩阵当中(很多个向量组成的矩阵),可以把提取出来的矩阵和人脸的名字都保存起来以便于下一次的读取。
SaveVector.h:
#include &opencv.hpp&
#include &fstream&
#include &sstream&
using namespace
using namespace std;
void SaveNameVector(vector&string&
&NameVector, string filename);
vector&string& LoadNameVector(vector&string&
&NameVector, string filename);
void SaveFaceMatrix(float **FaceMatrix, string filename, int rows);
Mat LoadMat(string file);
float** MatToVector2d(Mat &FaceMatrix_mat);
SaveVector.cpp:
#include &SaveVector.h&
Mat Vector2dToMat(float **FaceMatrix,int rows)
Mat T(rows, 2622, CV_32F);
for (int i = 0; i & i++)
for (int j = 0; j & 2622; j++)
T.at&float&(i, j) = FaceMatrix[i][j];
void SaveMat(Mat &FaceMatrix_,string filename)
FileStorage fs(filename, FileStorage::WRITE);
fs && "FaceMatrix" && FaceMatrix_;
fs.release();
Mat LoadMat(string file)
FileStorage fs(file, FileStorage::READ);
Mat FaceMatrix_;
fs["FaceMatrix"] && FaceMatrix_;
return FaceMatrix_;
float** MatToVector2d(Mat &FaceMatrix_mat)
float **array2d = new float*[FaceMatrix_mat.rows];
for (int i = 0; i&FaceMatrix_mat. ++i)
array2d[i] = new float[FaceMatrix_mat.cols];
for (int i = 0; i&FaceMatrix_mat. ++i)
array2d[i] = FaceMatrix_mat.ptr&float&(i);
return array2d;
void SaveFaceMatrix(float *FaceMatrix[], string filename,int rows)
Mat T = Vector2dToMat(FaceMatrix, rows);
if (!T.empty())
SaveMat(T, filename);
cout && "Please check out your the matrix and the file.We can not read any information." &&
void SaveNameVector(vector&string&
&NameVector, string filename){
int Num = 0;
ofstream NameSaveFile(filename, ios::app);
while (Num & NameVector.size())
NameSaveFile && NameVector[Num++] &&
NameSaveFile.clear();
vector&string& LoadNameVector(vector&string&
&NameVector_, string filename)
ifstream in(filename);
int Num = 0;
while (getline(in, line))
NameVector_.push_back(line);
in.clear();
return NameVector_;
这里在存储时,先将二维数组转换为OpenCV的Mat类型,再使用FileStorage将其序列化。当然,你也可以使用boost库来做这个事情。
存储的结果是这样的(一个人):
然后我们再来实现类:
Register.h:
//define a register
#include &opencv.hpp&
#include &SaveVector.h&
using namespace
using namespace std;
class Register
string FaceS
vector&string& FaceN
float* MatToVector_(Mat TrainMat);
float *FaceMatrix[20];
void JoinFaceSpace_(Mat newFace, string FaceSpace, string FaceName);
float** LoadVector_(string FaceSpace);
Mat FaceMatrix_
void SaveVector_(float *FaceMatrix_[], vector&string& FaceName_, string FaceSpace_)
if (!(FaceMatrix_ == NULL) && !FaceName_.empty())
SaveFaceMatrix(FaceMatrix_, "data/" + FaceSpace_ + "_FaceMatrix.xml", FaceName_.size());
SaveNameVector(FaceName, "data/" + FaceSpace_ + "_NameVector.txt");
else { cout && "Sorry.There are some problems while saving your face and name. please try again" && }
Register.cpp:
#include &Register.h&
#include &FaceDetect.h&
#include &ComputeDistance.h&
#include &ExtractFeature_.h&
float* Register::MatToVector_(Mat TrainMat)
Mat TrainMat_ROI = Facedetect(TrainMat);
if (!TrainMat_ROI.empty())
return ExtractFeature_(TrainMat_ROI);
else return NULL;
void arrayJoinArray2d(float *feature, float *FaceMatrix[], int i)
FaceMatrix[i] =
void Register::JoinFaceSpace_(Mat newFace, string FaceSpace, string Name)
float *FaceVector = MatToVector_(newFace);
if (FaceVector!=NULL)
arrayJoinArray2d(FaceVector, FaceMatrix, FaceName.size());
FaceName.push_back(Name);
SaveVector_(FaceMatrix, FaceName, FaceSpace);
cout && "Please try again,We can not find your face." &&
float** Register::LoadVector_(string FaceSpace)
string FaceVectorRoad = "data/" + FaceSpace + "_FaceMatrix.xml";
string NameVectorRoad = "data/" + FaceSpace + "_NameVector.txt";
vector&string&
NameVector=LoadNameVector(NameVector, NameVectorRoad);
if ( !NameVector.empty())
FaceName = NameV
FaceMatrix_mat = LoadMat(FaceVectorRoad);
if (!FaceMatrix_mat.empty())
float** a = MatToVector2d(FaceMatrix_mat);
cout && "Sucessfully read the FaceSpace:" + FaceSpace + "'s data!" &&
else { cout && "There is no data in this FaceSpace:" + FaceSpace + ",Please input ." && }
这样一来,我们在main函数里就可以非常方便的调用。比如我们要提取一张人脸的图片(这个人的名字叫lena),将其保存在LLEENNAA这个人脸空间中:
#include &Register.h&
#include &FaceDetect.h&
#include &ExtractFeature_.h&
int main()
Caffe_Predefine();
Dlib_Predefine();
Mat lena = imread("lena.jpg");
train.JoinFaceSpace_(lena,"LLEENNAA","lena");
我们可以做个试验,看看程序的正确性。在执行train.JoinFaceSpace_(lena,”LLEENNAA”,”lena”)后,Register里的FaceMatrix会相应增加,并且也会保存为xml和txt。我们再读取这个xml和txt来看看。
#include &Register.h&
#include &FaceDetect.h&
#include &ExtractFeature_.h&
int main()
Caffe_Predefine();
Dlib_Predefine();
Mat lena = imread("lena.jpg");
train.JoinFaceSpace_(lena,"LLEENNAA","lena");
cout && "当前的人脸矩阵的第一个元素为" && train.FaceMatrix[0][0] &&
cout && "当前的人脸名容器的第一个元素为" && train.FaceName[0]&&
cout&&"读取保存的人脸矩阵,其第一个元素为"&&test.LoadVector_("LLEENNAA")[0][0]&&
cout && "读取保存的人脸名字容器,其第一个元素为" && test.FaceName[0]&&
imshow("lena.jpg",lena);
waitKey(0);
程序显示完全一致,表示正确:
=================================================================
基于深度学习的人脸识别系统系列(Caffe+OpenCV+Dlib)——【五】设计人脸识别的注册类
完结,如果在代码过程中出现了任何问题,直接在博客下留言即可,共同交流学习。
排名:千里之外
(3)(9)(1)一个简单的人脸识别程序,识别函数在openCV里面几行就搞定了。如果自己用C++去写识别函数,工作量会很大么?网上的程序基本上都是基于openCV开发的,有没有不用openCV的代码呢?
人脸检测速度稍慢,不能实时,应用hog来进行人脸检测。建议基于joint或是于仕其的快速人脸检测
当然可以,看怎么定义“简单”了,Windows hello里人脸识别模块大概3MB的CPP文件,当然这是在线识别部分,不包括训练,数据采集,标注,测试……
当然可以,看怎么定义“简单”了,Windows hello里人脸识别模块大概3MB的CPP文件,当然这是在线识别部分,不包括训练,数据采集,标注,测试……
你首先要明白人脸识别程序包括了哪些流程?&br&(1)不提数据采集了,第一步是图像或视频解码,光图像就有N多种格式:bmp,jpg,png,pgm,ppm等等,每种里面都可能还有细分,比如有损的图像,无损的图像,你都需要自己来写;&br&(2)人脸检测,最简单的就是harr特征,自己写,分类器是adaboost,自己写,人脸检测的训练流程,测试流程,人脸检测模型的读取和输出,都要自己写;&br&(3)人脸识别,最简单的,特征脸eigenface,其中涉及最简单的pca算法,矩阵特征分解算法,自己写,配上最简单的分类器最近邻,计算向量的距离,自己写,人脸识别训练流程,识别流程,自己写;&br&(4)其他的数据预处理,各种IO操作等等;&br&这里面已经是最简单的人脸识别流程了。。。&br&而opencv可以帮你完成上述90%的工作!如果不用opencv或者类似的库,我不知道你能不能写出所有的完整的流程,就算写出来了,我不知道,还能不能说是“简单的”程序?
你首先要明白人脸识别程序包括了哪些流程? (1)不提数据采集了,第一步是图像或视频解码,光图像就有N多种格式:bmp,jpg,png,pgm,ppm等等,每种里面都可能还有细分,比如有损的图像,无损的图像,你都需要自己来写; (2)人脸检测,最简单的就是harr…
已有帐号?
无法登录?
社交帐号登录
计算机视觉/信息融合/机器学习如何掌握Facebook自动人脸识别技术?这里是生动指南--百度百家
如何掌握Facebook自动人脸识别技术?这里是生动指南
分享到微信朋友圈
你是否注意到 Facebook 已经开发出了一项能识别你朋友照片的神奇能力?过去,你能通过点击 Facebook 照片中的人物并输入名字为朋友上标签。现在,只要你上传一张图片,Facebook 就能为你标注图片中的每一个人。
不知道你注意了没?Facebook 有一项自动识别你上传照片中的朋友的功能。过去你需要自己点开照片为上面的每个人添加标注,现在这些 Facebook 都能自动为你做好。它是怎么做到的呢?看完下面这篇文,你也能在自己的电脑上 Get 这个技能!
你是否注意到 Facebook 已经开发出了一项能识别你朋友照片的神奇能力?过去,你能通过点击 Facebook 照片中的人物并输入名字为朋友上标签。现在,只要你上传一张图片,Facebook 就能非常神奇的为你标注图片中的每一个人:
Facebook 能够自动为你图片中的人物打上标签,这个人你之前要曾标注过。我不确定这是有帮助的?还是诡异的?
这一技术被称为面部识别。Facebook 的算法能够在只被标注过数次之后识别出你朋友的面部。这是一项相当惊人的技术——Facebook 识别面部的准确率达到了 98%,这几乎与人类水平一样。
让我们学习一下面部识别是如何工作的!但只是识别你的朋友就太过简单了。我们把这一技术的限度增加到更具挑战性的问题:区别 Will Ferrell(知名演员)和 Chad Smith(知名摇滚歌手)!
在复杂问题上如何使用机器学习
在过去的博文中,我们曾使用机器学习解决只有一个步骤的孤立问题——估算房价、基于已有数据产生新数据、识别一张图片中是否包含特定目标。所有这些问题都能通过选择一个机器学习算法、输入数据、产生结果而解决。但面部识别却是一系列相关的问题:
首先,查看一张照片,找到里面所有的脸。
第二,聚焦于每一张脸,并且即使在这张脸的朝向诡异、光照不好的情况下也能理解这是同一张脸。
第三,能够挑选出面部的独特特征,从而区别它与其他人——像是眼睛有多大、脸有多长等。
最后,将这张脸的这些独特特征与你已经知道的所有人的脸作对比,从而决定个人的名字。
作为人类,你的大脑能自动迅速处理这些事。事实上,人类太擅长识别人脸了,以至于能在每种东西上都「看到」人脸。:
计算机就没有这种高水平的泛化能力(至少现在没有),所以我们要手把手教它们一步步该怎么做。
我们需要建立一个单独解决人脸识别每一步的流水线,由这一步的结果进入下一步。换句话说,我们将连接数个机器学习算法:
人脸识别——一步一步来
让我们依次解决这一问题。每一步,我们都将会学习一个不同的机器学习算法。我不打算详细解释每一个算法,但你将学到每一个背后的主要思想,而且你将学到如何在 Python 上使用 OpenFace 和 dlib 建立自己的面部识别系统。
第一步:找到所有的脸
第一步是面部检测。很明显,在进行面部区分之前我们需要定位照片中的每张脸。
如果过去 10 年中你使用过照相机,你可能见过的面部检测:
面部检测是照相机的一大特征。当照相机能自动挑选面部,它可以在拍照前确保聚焦到所有的脸。但我们将使用其做不同的事——发现我们想要的图像区域,从而进入下一步。
在刚刚进入21世纪那几年,当 Paul Viola 和 Michael Jones 创造出一种能在廉价相机上运行的快速面部检测方法时,面部检测就成为了主流。然而,如今已经有太多可靠的解决方案。所以,我们打算采用 2005 年创造的方法,名为 Histogram of Oriented Gradients,缩写也就是 HOG。
为了找到图像中的脸,开始我们将会把图片变成黑白的,因为我们不需要颜色数据:
然后,我们将挨个查看图片中的单像素(single pixel)。对每一单像素而言,我们想要查看直接围绕着它的像素:
我们的目标是要搞清相比于直接围绕着它的这些像素,这个像素有多暗。然后,我们想要绘制一个箭头,显示图像变暗的方向:
只查看这个像素以及围绕着它的像素,图像变暗的方向是向上。
如果你在图片中的每个单像素重复这一过程,最终每个像素都会被箭头取代。这些箭头被称为梯度,它们显示了整张图片中由亮变暗的过程。
这可能看起来像是一件做起来很随意的事,但有很好的理由解释使用梯度取代像素的原因。如果我们直接分析像素,同一个人非常暗的图片和非常亮的图片将有完全不同的像素值。但通过只考虑 亮度变化的方向,暗或亮的照片将有同样准确的表征。这解决起来问题更加的容易。
但是,保留每个单像素的梯度给了我们太多的细节。我们最终会变得只见树木不见森林。如果我们只看更高层次的亮度/暗度基础流这样会更好,我们就能看到图片的基础模式。
为了做到这一点,我们将图片分割成 16×16 的像素方块。在每个方块下,我们将计算每个主要方向中有多少个梯度点(多少指向上、多少指向下、指向右,等等)。然后,我们将用指向最多的方向箭头取代这个方块。
最终结果是我们以一种非常简单的方式,把原始图片变成了一个能抓住面部基础结构的表征:
原始图片变为了能抓住图片主要特征的 HOG 表征,不用考虑亮度。
为了在这个 HOG 图片中找到面部,我们所需要做的就是找到最类似于已知 HOG 模式(从其他面部训练数据中提取到的)的部分:
使用这一技术,我们能简单的发现任何图像中的脸:
如果你想要使用 Python 和 dlib 自己尝试这一不走,这是如何产生和查看图片 HOG 表征的代码:/ageitgey/1c1cb1c60ace0d48c228e1
第二步:姿势以及面部的突出
我们已经孤立了图片中的每张脸。但现在,我们需要处理这样一个问题:面部朝向不同方向对计算机而言看起来完全不同:
为了处理这种情况,我们将尝试打包每一个图片,以便于眼睛和嘴巴总是处于图片中的同样位置。这会使我们在下一步中更容易比较面部。
为了做到这一点,我们打算使用一个名为面部标志估算(face landmark estimation)的算法。也有很多方式能够做到这些,但我们打算使用 Vahid Kazemi 和 Josephine Sullivan 在 2014 年创造的方法。
基础的思路是我们将提出脸上存在的 68 个特殊点(被称为 landmarks):下巴的顶部、眼睛的外沿、眉毛的内沿等等。然后,我们将训练一个机器学习算法能够在任何脸上找到这些 68 个特殊点:
我们将在每张脸上定位的这 68 个标志
这是在我们的测试图像上定位的 68 个面部标志的结果:
你也能使用同样的技术部署自己的 Snapchat 实时 3d 面部过滤器!
现在,我们知道了眼睛和嘴巴的位置,我们将简单的旋转、按比例放大或缩小以及修改图像,以便于眼睛和嘴巴最好能够居中。我们不会做任何精致的 3d 扭曲( 3d warps),因为这会使得图片失真。我们只打算使用基础的图像变换技巧,像是旋转(rotation)以及按比例放大或缩小(scale),从而保留平行线(这被称为仿射变换,affine transformations):
现在,无论面部朝向如何,我们都能粗略地将眼睛和嘴巴集中到图片中的同一位置。这将使得我们的下一步更加准确。
如果你想尝试这一步,这里是寻找面部标志的代码:/ageitgey/ae340db3ee1f9c;这里是使用这些标志转换图像的代码:/ageitgey/82d0ea0fdb56dc93cb9b716e7ceb364b。
第三步:给脸编码
面部识别的最简单方法是直接将我们在第二步中找到的未知的的脸与我们拥有的已经被标记过的照片相比较。当我们发现一个之前标记过的脸与未知的脸非常相似,它必定是同一个人。看上去是个好主意,对吧?
但这个方法有个很大的问题。一个像 Facebook 这样的网站拥有几十亿的用户,上面贴了几万亿张照片,它不可能循环检查之前每个标记过的脸,并将它与每一张新上传的图片比较。这样需要的时间太长了。他们要能够在毫秒之间识别不同的脸,而不是以小时为单位。
我们需要的方法是从每一张脸中提取一些基础的测量数据。然后就可以用同样的方法测量未知的脸,并且找到最接近测量数据的那张已知的脸。例如,我们可以测量每个耳朵的大小、眼睛之间的距离、鼻子的长度等。如果你曾经看过一部像犯罪现场调查(CSI)那样的电视剧,你就知道我在说什么。
1.测量一张脸的最可靠方法
OK,所以我们需要从每张脸中测量些什么来建立已知脸的数据库?耳朵的大小?鼻子的长度?眼睛的颜色?或者其它的东西?
事实上,那些对人类而言来说非常明显的测量(像眼睛的颜色)对计算机来说没啥意义,因为计算机只看图像中的单个像素。研究人员已经发现最精确的方法是让计算机自己去测量它要收集的数据。深度学习要比人类更善于搞清楚面部什么部位测量起来更重要。
解决方案是训练一个深度卷积神经网络。但并不是训练这它去识别照片中的目标,而是要训练它产生每张脸的 128 个测量。
这个训练过程是同时看 3 张人脸照片:
加载一张已知人的训练面部图像
加载另一张同一人的照片
加载一张完全不同的人的照片
然后这个算法检查它当前为这三张人脸照片生成的测量数据。然后略微调整一下这个神经网络,确保#1 和#2的测量结果稍稍接近,而 #2 和 #3 的测量结果稍稍相远:
数千人的几百万张照片需要重复这个步骤几百万次,之后这个神经网络学习可靠地为每个人生成 128 个测量。对于任何一个人的十张不同的图片,它都应该给出大致相同的测量。
机器学习人士将这每张脸的 128 项测量称为一个嵌入。这个减少复杂原始数据(如图片插入计算机生成数字列表)的想法在机器学习中出现过很多(尤其是在语言翻译中)。我们使用的面部提取的方法是谷歌研究员在 2015 年发明的,但也存在很多相似的方法。
2.为人脸图像编码
训练一个卷积神经网络输出面部嵌入的方法需要大量数据和强大的计算能力。在自己的计算机上做这个有点不切实际,除非你有 8 &个 NVIDIA Telsa 视频显卡或者你愿意租用亚马逊的计算机服务。
但是一旦这个网络训练好了,它就能为任何一张脸生成测量数据,即便这张脸它从来没见过!所以,这一步只需要做一次就行了。我们很幸运,有人已经在 OpenFace 上做了,并公开了一些训练好的网络,我们可以直接使用 。
所以我们只需要用他们预先训练好的网络运行我们的人脸图像,来获得每张脸的 128 个测量数据。
那么这 128 个测量数据到底是什么?其实我们也不知道。这对我们来说真的不重要。我们所关心的是,这个神经网络在看同一个人的两个不同的图片时,产生了几乎相同测量数据。
如果你想自己尝试这个步骤,OpenFace 提供了一个 lua 脚本,将生成的所有图像嵌入在一个文件夹,把它们写成 CSV 文件。这里是步骤:/ageitgey/ddbae3b209ba3cf75719
第四步:从编码中找到这个人的名字
最后一步是整个过程中最简单的一步。我们所做的都是为了在已知人的数据库中找到这个人,这个人的测量数据要最接近我们的测试图像。
你可以用任何基本的机器学习分类算法来做这个事情,不需要什么花哨的深度学习技巧。我们将使用一个简单的线性 &SVM 分类器 ,但其他很多分类算法也都可以拿来用。
我们要做的就是训练一个分类器,它能吸收新测试图像的测量数据,并在已知的人中分辨出哪一个是最匹配的。运行这一分类器需要数毫秒。分类的结果就是这个人的名字。
所以让我们试试我自己的系统。首先 ,我用 Will Ferrell、Chad Smith 和 Jimmy Falon 三人每人 20 张照片来训练一个分类器。
然后我在这个分类器上运行了 YouTube 上 Will Ferrell 和 Chad Smith 在 Jimmy Falon 秀上相互模仿的那个视频的每一帧 :
结果成功了! 看看这些脸的不同姿势 —— 甚至是侧脸,都被它抓到了
自己来试试
让我们回顾一下这个步骤:
用 HOG 算法编码每一张照片,创建出这张照片的一个简单图像版本。然后用这个简单的图像找到图像的一部分,这部分看起来要像一张脸的通用 HOG 编码。
通过寻找脸的主要特征,找出脸的姿势。一旦我们发现这些特征,就用它们来弯曲图像,让眼睛和嘴巴都集中在一起。
利用一个知道如何测量面部特征的神经神经网络穿过这一集中的面部图像,保留这些 128 项测量。
查看我们过去已经测量的所有人脸,看哪一张与我们要测量的面部最为接近。这就是匹配项。
既然已知道了它是怎么做出来的,这里有一个在自己电脑上使用 OpenFace 运行整个人脸识别过程的指导:
要做的准备
确保你已经安装了 Python、OpenFace 和 dlib 。你也可以在 https://cmusatyalab.github.io/openface/setup/ &这个网站上手动安装,或者使用一个已经将所有东西都安装好了的预先设定的Docker 图象:
docker pull bamos/openface
docker run -p
-t -i bamos/openface /bin/bashcd /root/openface
贴士:如果你正在 OSK 上使用 Doker,你能使你的 OSK/Users/folder 在一个 docker 图像中可见,像这样:
docker run -v /Users:/host/Users -p
-t -i bamos/openface /bin/bash
cd /root/openface
然后你就能获取你在/host/Users/...的docker 图像里的所有 OSX 文件
ls /host/Users/
在 openface 文件中建立一个名为./training-images/的文件夹
mkdir training-images
为你想识别的每个人建立一个子文件夹。例如:
mkdir ./training-images/will-ferrell/
mkdir ./training-images/chad-smith/
mkdir ./training-images/jimmy-fallon/
将每个人的所有图像拷贝进对应的子文件夹。确保每张图像上只出现一张脸。不需要裁剪脸部周围的区域。OpenFace 会自己裁剪。
从这个 OpenFace 的根目录中运行这个 OpenFace 脚本。
首先,进行姿势检测和校准:
./util/align-dlib.py ./training-images/ align outerEyesAndNose ./aligned-images/ --size 96
这将创建一个新./aligned-images/子文件夹,带有每一个测试图像的裁剪过的并且对齐的版本。
第二,从对齐的图像中生成表征:
./batch-represent/main.lua -outDir ./generated-embeddings/ -data ./aligned-images/
运行完后,这个./aligned-images/子文件夹会包含一个带有每张图像的嵌入的 &csv 文件。
第三,训练自己的面部检测模型:
./demos/classifier.py train ./generated-embeddings/
这将产生名为./generated-embeddings/classifier.pkl的新文件名。这个文件有你将用来识别新面部的 SVM 模型。
到了这,你应该有一个可用的面部识别器。
第五步:识别面部!
获取一张未知脸的新照片。把它像这样传递给分类器脚本:
./demos/classifier.py infer ./generated-embeddings/classifier.pkl your_test_image.jpg
你需要得到一个看起来像这样的预测:
=== /test-images/will-ferrel-1.jpg ===
Predict will-ferrell with 0.73 confidence.
从这里开始直到你适应这个 ./demos/classifier.py Python 脚本 做任何你想做的。
重要提示:
如果你得到了坏的结果,请尝试在第三步中为每个人添加更多一些照片(尤其是不同姿势的照片)。
这个脚本总是会给出一个预测,即便是一张它不知道的脸。在真实的应用中,你会看到信度得分,并抛除低信度的预测,因为它们很可能是错误的。
本文选自:Medium,作者:Adam Geitgey,机器之心编译;
(C)机器之心,最专业的前沿科技媒体和产业服务平台,每日提供优质产业资讯与深度思考,欢迎关注微信公众号「机器之心」(almosthuman2014),或登录机器之心网站& , 查看更多精彩内容。
分享到微信朋友圈
在手机阅读、分享本文
还可以输入250个字
推荐文章RECOMMEND
阅读:10万
热门文章HOT NEWS
央行住房按揭贷款收紧,将可能改为整个国内住房市场价格上涨预期。...
八卦掌门人
百度新闻客户端
百度新闻客户端
百度新闻客户端
扫描二维码下载
订阅 "百家" 频道
观看更多百家精彩新闻

我要回帖

更多关于 dlib opencv 人脸检测 的文章

 

随机推荐