网友搭了个《生活大爆炸》面部识别库,可以用 face-recognition.js 识别出谢耳朵
本文为 雷锋字幕组 编译的技术博客,原标题Node.js + face-recognition.js : Simple and Robust Face Recognition using Deep Learning,作者Vincent Mühler。
翻译 | 付腾 整理 | 凡江
已训练模型示范,可以很好的识别 拉贾·谢耳朵(这还能认错)雷纳德和霍华德
在这篇文章里我要向你们示范一下如何用 face-recognition.js 来完成有效的脸部检测(查看哪里有脸)和面部识别(这脸是谁的)。我一直在寻找好用的,基于Node.js的面部识别库 (精度要高),可惜没有找到,那么就动手自己做一个吧!
这个 npm软件包 使用 dlib 为基础并且使用Node.js与dlib当中的面部识别工具进行绑定,这样的设计是因为我发现这样能获得比较高的准确度。dlib库使用深度学习方法并且已经内置了一些训练好的模型,而且这些模型在对 LFW面部识别基准数据 的识别率上已经有了令人惊讶的99.38%的准确率。
为什么?
最近我准备用Node.js写一个面部识别的程序, 用来提取和识别《生活大爆炸》当中的角色面部信息。
开始的时候,我想以OpenCV的面部识别器为基础进行开发,就像我在 另一篇教程 (Node.js + OpenCV for Face Recognition.)里面提到的内容一样。
但是,这些面部识别器虽然速度很快,但是我发现他们的识别结果却并不可靠。更准确一点说,它们在识别正面面部图像时性能不错,但是当面部的姿态稍有不同(比如侧脸之类),它们的预测结果就不是很保险了。
因此我就找找看有没有可以替代的方法,于是找到了dlib C++库,然后试用了它的Python API,发现它的预测结果不错,于是最后决定:我要用这个库和Node.js来一发!所以,我创建了这个npm软件包用于提供简单的Node.js 面部识别API接口。
什么是face-recognition.js?
在face-recognition.js构思里,我想让这个npm软件包实现以下功能:
-
简单实用的API,易上手。
-
可调的精细分类(译者注:估计是用来适应不同的图片分辨率)。
-
容易安装(最好能直接用 npm install 命令安装)
这个软件包目前仍在开发中,目前,它可以提供以下功能:
面部检测
可以用深度神经网络来进行面部检测或者用简单的脸部正面识别来进行快速但是低可靠性的探测。
面部识别
面部识别器是一个深度神经网络,用了我刚才提到的模型来对一个特殊的面部描述器来进行计算。这个面部识别器可以用已经标定好的面部图像来进行训练,而且之后可以用来预测一个输入面部图片的标签。
脸型标记
你也可以用这个软件包来探测5个(下图上)或者68个(下图下)脸型标记点。
计划不错,来动手吧!
好的,就像我刚刚说的,我在最开始没有能用OpenCV解决这个任务。现在我有一些150*150大小的面部图片,里面有谢耳朵,拉贾,雷纳德,霍华德和斯图尔特。我现在就要给你展示一下用这些数据来训练一个面部识别器并且用它来识别一些新的面部图片是如何简单。这个例子的代码可以在这个 repo 里面找到。
准备数据
我每个角色大约收集了20张面部图片,而且是不同姿势的图片。
我们会用每个角色10张面部图片来训练(训练集)这个识别器并且用剩下的10张图片来做识别器的精确度评估(测试集)。
每个面部图片的文件名包含其中人物的名字,所以我们能够比较简单的把我们设定的类名(如下所示,即人名)映射到:
['sheldon', 'lennard', 'raj', 'howard', 'stuart']
每个类的图像数组 。你也可以通过文件路径+ fr.loadImage(fp) 的方式读取一张图片。
面部探测
如我之前所说,面部信息已经抽取成为一张张的150x150大小图片,我是通过 opencv4nodejs 提前处理好的。但是你也可以通过如下方式 检测,抓取,保存和标定面部信息。
训练识别器
现在我们的数据已经就位,可以开始训练我们的识别器了。
基本上,训练的过程是将每张面部图片输入神经网络,然后神经网络会为每个图片输出一个 描述器,并且神经网络会记录下所提供的输入类别的描述器。你也可以 设置 numJitters变量来作为第三个参数,以此来训练数据做抖动处理。抖动处理包括旋转,缩放和镜像变换图片,通过这些变换操作,每个输入面部图像会产生新的图像(译者注:而这些新的图像可以作为训练图片输入识别器,以此达到用较少训练数据扩大训练效果的目的),增加抖动的类别和数量有可能提升识别器的预测准确度,但是同样可能增加训练时间。
此外,我们也能够将训练好的识别器的状态储存起来,这样我们就不需要重复训练,下次需要调用识别器的时候我们就可以直接从文件中把它读取出来。
识别器的保存
识别器的读取
识别新的面部
现在我们可以用剩下的测试数据来对训练好的识别器来进行预测准确度的测试,并且记录下结果。
预测是通过计算 输入面部图像的描述器向量 (descriptor vector) 与给定类的向量之间的欧式距离 (euclidean distance )来完成的。即首先计算一个输入图像的描述器向量与各个 类 的描述器向量的欧式距离,获得一个数组,是由欧式距离组成的。 然后对这个欧式距离组 求平均值 (mean value) 。可能有人觉得 Kmean 聚类算法或者 支持向量机 (SVM) 分类器 可能更加适合这个任务,所以我也很可能在将来引入这些算法。但是在目前这个阶段,使用欧式距离的计算是比较快速并且很有效率的。(译者注:这段有些绕,但是实际的分类的过程其实和Kmean 聚类算法的实现是高度类似的,都是基于欧式距离的计算,只不过这里的训练数据是给定了标签的)
通过调用 predictBest 方法,输入图片会被赋予与它在欧式距离上最短的类的标签 (即两者最为相似)。输出结果看起来如下所示:
{ className: 'sheldon', distance: 0.5 }
如果你想获得更多的信息,比如输入图片与所有类的欧式距离,你可以直接调用 recognizer.predict(image)方法 (image是输入图片变量),这样输出就是一组数组,其中包含了输入图片与所有类别的欧式距离。
[
{ className: 'sheldon', distance: 0.5 },
{ className: 'raj', distance: 0.8 },
{ className: 'howard', distance: 0.7 },
{ className: 'lennard', distance: 0.69 },
{ className: 'stuart', distance: 0.75 }
]
结果
运行上面的例子就能得出下面的结果:
每张脸用10张图像作为训练集
sheldon ( 90.9% ) : 10 of 11 faces have been recognized correctly
lennard ( 100% ) : 12 of 12 faces have been recognized correctly
raj ( 100% ) : 12 of 12 faces have been recognized correctly
howard ( 100% ) : 12 of 12 faces have been recognized correctly
stuart ( 100% ) : 3 of 3 faces have been recognized correctly
每张脸用5张图像作为训练集
sheldon ( 100% ) : 16 of 16 faces have been recognized correctly
lennard ( 88.23% ) : 15 of 17 faces have been recognized correctly
raj ( 100% ) : 17 of 17 faces have been recognized correctly
howard ( 100% ) : 17 of 17 faces have been recognized correctly
stuart ( 87.5% ) : 7 of 8 faces have been recognized correctly
(所以你是想说谢耳朵初见让你印象深刻,然后越看越生厌是吗?这里是可能存在overfitting的问题。)
结果展示,我们用完成训练的面部识别器来对视频当中的图片进行面部识别。
结论
看看结果,我们可以看到,就算只用了很小的训练集,我们已经能够获得很好的预测准确度,就算一些抓取的图片比较模糊(这是因为我从网上抓取的部分图片尺寸太小,像素不高)。
如果你喜欢这篇文章,那么一定要来试试这个npm软件包。当然,如果你能在我的 github repository 上为它点个赞,或者提建议,我会非常感谢!
博客原址 https://medium.com/@muehler.v/node-js-face-recognition-js-simple-and-robust-face-recognition-using-deep-learning-ea5ba8e852
更多文章,关注雷锋网 (公众号:雷锋网) ,添加 雷锋字幕组 微信号(leiphonefansub)为好友
备注「我要加入」,To be an AI Volunteer !
雷锋网雷锋网
。