转自:http://toutiao.com/i6311228330276291073/

1. 简介

你是否注意到 Facebook 已经开发出了一项能识别你朋友照片的神奇能力?过去,你能通过点击 Facebook 照片中的人物并输入名字为朋友上标签。现在,只要你上传一张图片,Facebook 就能非常神奇的为你标注图片中的每一个人:
Facebook 能够自动为你图片中的人物打上标签,这个人你之前要曾标注过。我不确定这是有帮助的?还是诡异的?
       这一技术被称为面部识别。Facebook 的算法能够在只被标注过数次之后识别出你朋友的面部。这是一项相当惊人的技术——Facebook 识别面部的准确率达到了 98%,这几乎与人类水平一样。
       让我们学习一下面部识别是如何工作的!但只是识别你的朋友就太过简单了。我们把这一技术的限度增加到更具挑战性的问题:区别 Will Ferrell(知名演员)和 Chad Smith(知名摇滚歌手)!
在复杂问题上如何使用机器学习
    在过去的博文中,我们曾使用机器学习解决只有一个步骤的孤立问题——估算房价、基于已有数据产生新数据、识别一张图片中是否包含特定目标。所有这些问题都能通过选择一个机器学习算法、输入数据、产生结果而解决。但面部识别却是一系列相关的问题:
    1)查看一张照片,找到里面所有的脸。
    2)聚焦于每一张脸,并且即使在这张脸的朝向诡异、光照不好的情况下也能理解这是同一张脸。
    3)能够挑选出面部的独特特征,从而区别它与其他人——像是眼睛有多大、脸有多长等。
    4)将这张脸的这些独特特征与你已经知道的所有人的脸作对比,从而决定个人的名字。
    作为人类,你的大脑能自动迅速处理这些事。事实上,人类太擅长识别人脸了,以至于能在每种东西上都「看到」人脸。
计算机就没有这种高水平的泛化能力(至少现在没有),所以我们要手把手教它们一步步该怎么做。我们需要建立一个单独解决人脸识别每一步的流水线,由这一步的结果进入下一步。换句话说,我们将连接数个机器学习算法:

2. 实现方案

人脸识别——一步一步来
    让我们依次解决这一问题。每一步,我们都将会学习一个不同的机器学习算法。我不打算详细解释每一个算法,但你将学到每一个背后的主要思想,而且你将学到如何在 Python 上使用 OpenFace 和 dlib 建立自己的面部识别系统。

2.1 第一步:找到所有的脸

第一步是面部检测。很明显,在进行面部区分之前我们需要定位照片中的每张脸。
    如果过去 10 年中你使用过照相机,你可能见过的面部检测:
面部检测是照相机的一大特征。当照相机能自动挑选面部,它可以在拍照前确保聚焦到所有的脸。但我们将使用其做不同的事——发现我们想要的图像区域,从而进入下一步。
    在刚刚进入21世纪那几年,当 Paul Viola 和 Michael Jones 创造出一种能在廉价相机上运行的快速面部检测方法时,面部检测就成为了主流。然而,如今已经有太多可靠的解决方案。所以,我们打算采用 2005 年创造的方法,名为 Histogram of Oriented Gradients,缩写也就是 HOG。
    为了找到图像中的脸,开始我们将会把图片变成黑白的,因为我们不需要颜色数据:
然后,我们将挨个查看图片中的单像素(single pixel)。对每一单像素而言,我们想要查看直接围绕着它的像素:
我们的目标是要搞清相比于直接围绕着它的这些像素,这个像素有多暗。然后,我们想要绘制一个箭头,显示图像变暗的方向:
    只查看这个像素以及围绕着它的像素,图像变暗的方向是向上。
    如果你在图片中的每个单像素重复这一过程,最终每个像素都会被箭头取代。这些箭头被称为梯度,它们显示了整张图片中由亮变暗的过程。
这可能看起来像是一件做起来很随意的事,但有很好的理由解释使用梯度取代像素的原因。如果我们直接分析像素,同一个人非常暗的图片和非常亮的图片将有完全不同的像素值。但通过只考虑 亮度变化的方向,暗或亮的照片将有同样准确的表征。这解决起来问题更加的容易。
但是,保留每个单像素的梯度给了我们太多的细节。我们最终会变得只见树木不见森林。如果我们只看更高层次的亮度/暗度基础流这样会更好,我们就能看到图片的基础模式。
    为了做到这一点,我们将图片分割成 16×16 的像素方块。在每个方块下,我们将计算每个主要方向中有多少个梯度点(多少指向上、多少指向下、指向右,等等)。然后,我们将用指向最多的方向箭头取代这个方块。
最终结果是我们以一种非常简单的方式,把原始图片变成了一个能抓住面部基础结构的表征:
原始图片变为了能抓住图片主要特征的 HOG 表征,不用考虑亮度。
   为了在这个 HOG 图片中找到面部,我们所需要做的就是找到最类似于已知 HOG 模式(从其他面部训练数据中提取到的)的部分:
使用这一技术,我们能简单的发现任何图像中的脸:
如果你想要使用 Python 和 dlib 自己尝试这一不走,这是如何产生和查看图片 HOG 表征的代码:https://gist.github.com/ageitgey/1c1cb1c60ace321868f7410d48c228e1
import sys
import dlib
from skimage import io# Take the image file name from the command line
file_name = sys.argv[1]# Create a HOG face detector using the built-in dlib class
face_detector = dlib.get_frontal_face_detector()win = dlib.image_window()# Load the image into an array
image = io.imread(file_name)# Run the HOG face detector on the image data.
# The result will be the bounding boxes of the faces in our image.
detected_faces = face_detector(image, 1)print("I found {} faces in the file {}".format(len(detected_faces), file_name))# Open a window on the desktop showing the image
win.set_image(image)# Loop through each face we found in the image
for i, face_rect in enumerate(detected_faces):# Detected faces are returned as an object with the coordinates # of the top, left, right and bottom edgesprint("- Face #{} found at Left: {} Top: {} Right: {} Bottom: {}".format(i, face_rect.left(), face_rect.top(), face_rect.right(), face_rect.bottom()))# Draw a box around each face we foundwin.add_overlay(face_rect)# Wait until the user hits <enter> to close the window
dlib.hit_enter_to_continue()

2.2 第二步:姿势以及面部的突出

我们已经孤立了图片中的每张脸。但现在,我们需要处理这样一个问题:面部朝向不同方向对计算机而言看起来完全不同:

为了处理这种情况,我们将尝试打包每一个图片,以便于眼睛和嘴巴总是处于图片中的同样位置。这会使我们在下一步中更容易比较面部。
    为了做到这一点,我们打算使用一个名为面部标志估算(face landmark estimation)的算法。也有很多方式能够做到这些,但我们打算使用 Vahid Kazemi 和 Josephine Sullivan 在 2014 年创造的方法。
基础的思路是我们将提出脸上存在的 68 个特殊点(被称为 landmarks):下巴的顶部、眼睛的外沿、眉毛的内沿等等。然后,我们将训练一个机器学习算法能够在任何脸上找到这些 68 个特殊点:
我们将在每张脸上定位的这 68 个标志
    这是在我们的测试图像上定位的 68 个面部标志的结果:
你也能使用同样的技术部署自己的 Snapchat 实时 3d 面部过滤器!
    现在,我们知道了眼睛和嘴巴的位置,我们将简单的旋转、按比例放大或缩小以及修改图像,以便于眼睛和嘴巴最好能够居中。我们不会做任何精致的 3d 扭曲( 3d warps),因为这会使得图片失真。我们只打算使用基础的图像变换技巧,像是旋转(rotation)以及按比例放大或缩小(scale),从而保留平行线(这被称为仿射变换,affine transformations):
     现在,无论面部朝向如何,我们都能粗略地将眼睛和嘴巴集中到图片中的同一位置。这将使得我们的下一步更加准确。
如果你想尝试这一步,这里是寻找面部标志的代码:https://gist.github.com/ageitgey/ae340db3e493530d5e1f9c15292e5c74
import sys
import dlib
from skimage import io# You can download the required pre-trained face detection model here:
# http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
predictor_model = "shape_predictor_68_face_landmarks.dat"# Take the image file name from the command line
file_name = sys.argv[1]# Create a HOG face detector using the built-in dlib class
face_detector = dlib.get_frontal_face_detector()
face_pose_predictor = dlib.shape_predictor(predictor_model)win = dlib.image_window()# Take the image file name from the command line
file_name = sys.argv[1]# Load the image
image = io.imread(file_name)# Run the HOG face detector on the image data
detected_faces = face_detector(image, 1)print("Found {} faces in the image file {}".format(len(detected_faces), file_name))# Show the desktop window with the image
win.set_image(image)# Loop through each face we found in the image
for i, face_rect in enumerate(detected_faces):# Detected faces are returned as an object with the coordinates # of the top, left, right and bottom edgesprint("- Face #{} found at Left: {} Top: {} Right: {} Bottom: {}".format(i, face_rect.left(), face_rect.top(), face_rect.right(), face_rect.bottom()))# Draw a box around each face we foundwin.add_overlay(face_rect)# Get the the face's posepose_landmarks = face_pose_predictor(image, face_rect)# Draw the face landmarks on the screen.win.add_overlay(pose_landmarks)dlib.hit_enter_to_continue()
这里是使用这些标志转换图像的代码:
https://gist.github.com/ageitgey/82d0ea0fdb56dc93cb9b716e7ceb364b
import sys
import dlib
import cv2
import openface# You can download the required pre-trained face detection model here:
# http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
predictor_model = "shape_predictor_68_face_landmarks.dat"# Take the image file name from the command line
file_name = sys.argv[1]# Create a HOG face detector using the built-in dlib class
face_detector = dlib.get_frontal_face_detector()
face_pose_predictor = dlib.shape_predictor(predictor_model)
face_aligner = openface.AlignDlib(predictor_model)# Take the image file name from the command line
file_name = sys.argv[1]# Load the image
image = cv2.imread(file_name)# Run the HOG face detector on the image data
detected_faces = face_detector(image, 1)print("Found {} faces in the image file {}".format(len(detected_faces), file_name))# Loop through each face we found in the image
for i, face_rect in enumerate(detected_faces):# Detected faces are returned as an object with the coordinates # of the top, left, right and bottom edgesprint("- Face #{} found at Left: {} Top: {} Right: {} Bottom: {}".format(i, face_rect.left(), face_rect.top(), face_rect.right(), face_rect.bottom()))# Get the the face's posepose_landmarks = face_pose_predictor(image, face_rect)# Use openface to calculate and perform the face alignmentalignedFace = face_aligner.align(534, image, face_rect, landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE)# Save the aligned image to a filecv2.imwrite("aligned_face_{}.jpg".format(i), alignedFace)

2.3 第三步:给脸编码

面部识别的最简单方法是直接将我们在第二步中找到的未知的的脸与我们拥有的已经被标记过的照片相比较。当我们发现一个之前标记过的脸与未知的脸非常相似,它必定是同一个人。看上去是个好主意,对吧?

但这个方法有个很大的问题。一个像 Facebook 这样的网站拥有几十亿的用户,上面贴了几万亿张照片,它不可能循环检查之前每个标记过的脸,并将它与每一张新上传的图片比较。这样需要的时间太长了。他们要能够在毫秒之间识别不同的脸,而不是以小时为单位。
    我们需要的方法是从每一张脸中提取一些基础的测量数据。然后就可以用同样的方法测量未知的脸,并且找到最接近测量数据的那张已知的脸。例如,我们可以测量每个耳朵的大小、眼睛之间的距离、鼻子的长度等。如果你曾经看过一部像犯罪现场调查(CSI)那样的电视剧,你就知道我在说什么。

2.3.1 测量一张脸的最可靠方法

OK,所以我们需要从每张脸中测量些什么来建立已知脸的数据库?耳朵的大小?鼻子的长度?眼睛的颜色?或者其它的东西?
    事实上,那些对人类而言来说非常明显的测量(像眼睛的颜色)对计算机来说没啥意义,因为计算机只看图像中的单个像素。研究人员已经发现最精确的方法是让计算机自己去测量它要收集的数据。深度学习要比人类更善于搞清楚面部什么部位测量起来更重要。
解决方案是训练一个深度卷积神经网络。但并不是训练这它去识别照片中的目标,而是要训练它产生每张脸的 128 个测量。
    这个训练过程是同时看 3 张人脸照片:
    1)加载一张已知人的训练面部图像
    2)加载另一张同一人的照片
    3)加载一张完全不同的人的照片
    然后这个算法检查它当前为这三张人脸照片生成的测量数据。然后略微调整一下这个神经网络,确保#1 和#2的测量结果稍稍接近,而 #2 和 #3 的测量结果稍稍相远:

数千人的几百万张照片需要重复这个步骤几百万次,之后这个神经网络学习可靠地为每个人生成 128 个测量。对于任何一个人的十张不同的图片,它都应该给出大致相同的测量。
机器学习人士将这每张脸的 128 项测量称为一个嵌入。这个减少复杂原始数据(如图片插入计算机生成数字列表)的想法在机器学习中出现过很多(尤其是在语言翻译中)。我们使用的面部提取的方法是谷歌研究员在 2015 年发明的,但也存在很多相似的方法。

2.3.2 为人脸图像编码

训练一个卷积神经网络输出面部嵌入的方法需要大量数据和强大的计算能力。在自己的计算机上做这个有点不切实际,除非你有 8 个 NVIDIA Telsa 视频显卡或者你愿意租用亚马逊的计算机服务。
但是一旦这个网络训练好了,它就能为任何一张脸生成测量数据,即便这张脸它从来没见过!所以,这一步只需要做一次就行了。我们很幸运,有人已经在 OpenFace 上做了,并公开了一些训练好的网络,我们可以直接使用 。

所以我们只需要用他们预先训练好的网络运行我们的人脸图像,来获得每张脸的 128 个测量数据。
那么这 128 个测量数据到底是什么?其实我们也不知道。这对我们来说真的不重要。我们所关心的是,这个神经网络在看同一个人的两个不同的图片时,产生了几乎相同测量数据。
    如果你想自己尝试这个步骤,OpenFace 提供了一个 lua 脚本,将生成的所有图像嵌入在一个文件夹,把它们写成 CSV 文件。这里是步骤:https://gist.github.com/ageitgey/ddbae3b209b6344a458fa41a3cf75719

2.4 第四步:从编码中找到这个人的名字

最后一步是整个过程中最简单的一步。我们所做的都是为了在已知人的数据库中找到这个人,这个人的测量数据要最接近我们的测试图像。

你可以用任何基本的机器学习分类算法来做这个事情,不需要什么花哨的深度学习技巧。我们将使用一个简单的线性 SVM 分类器 ,但其他很多分类算法也都可以拿来用。
    我们要做的就是训练一个分类器,它能吸收新测试图像的测量数据,并在已知的人中分辨出哪一个是最匹配的。运行这一分类器需要数毫秒。分类的结果就是这个人的名字。
    所以让我们试试我自己的系统。首先 ,我用 Will Ferrell、Chad Smith 和 Jimmy Falon 三人每人 20 张照片来训练一个分类器。
然后我在这个分类器上运行了 YouTube 上 Will Ferrell 和 Chad Smith 在 Jimmy Falon 秀上相互模仿的那个视频的每一帧 :
结果成功了!  看看这些脸的不同姿势 —— 甚至是侧脸,都被它抓到了
自己来试试
让我们回顾一下这个步骤:
1)用 HOG 算法编码每一张照片,创建出这张照片的一个简单图像版本。然后用这个简单的图像找到图像的一部分,这部分看起来要像一张脸的通用 HOG 编码。
2)通过寻找脸的主要特征,找出脸的姿势。一旦我们发现这些特征,就用它们来弯曲图像,让眼睛和嘴巴都集中在一起。
3)利用一个知道如何测量面部特征的神经神经网络穿过这一集中的面部图像,保留这些 128 项测量。
4)查看我们过去已经测量的所有人脸,看哪一张与我们要测量的面部最为接近。这就是匹配项。
既然已知道了它是怎么做出来的,这里有一个在自己电脑上使用 OpenFace 运行整个人脸识别过程的指导:
1)要做的准备
确保你已经安装了 Python、OpenFace 和 dlib 。你也可以在 https://cmusatyalab.github.io/openface/setup/ 这个网站上手动安装,或者使用一个已经将所有东西都安装好了的预先设定的Docker 图象:
docker pull bamos/openface
docker run -p 9000:9000 -p 8000:8000 -t -i bamos/openface /bin/bashcd /root/openface

贴士:如果你正在 OSK 上使用 Doker,你能使你的 OSK/Users/folder 在一个 docker 图像中可见,像这样:

docker run -v /Users:/host/Users -p 9000:9000 -p 8000:8000 -t -i bamos/openface
/bin/bash
cd /root/openface

然后你就能获取你在/host/Users/...的docker 图像里的所有 OSX 文件

ls /host/Users/

    2)第一步

在 openface 文件中建立一个名为./training-images/的文件夹
mkdir training-images

为你想识别的每个人建立一个子文件夹。例如:

mkdir ./training-images/will-ferrell/
mkdir ./training-images/chad-smith/
mkdir ./training-images/jimmy-fallon/

    3)第二步
    将每个人的所有图像拷贝进对应的子文件夹。确保每张图像上只出现一张脸。不需要裁剪脸部周围的区域。OpenFace 会自己裁剪。

    4)第三步
从这个 OpenFace 的根目录中运行这个 OpenFace 脚本。
    (1)进行姿势检测和校准:
./util/align-dlib.py ./training-images/ align outerEyesAndNose ./aligned-images/ --size 96

这将创建一个新./aligned-images/子文件夹,带有每一个测试图像的裁剪过的并且对齐的版本。
(2)从对齐的图像中生成表征:

./batch-represent/main.lua -outDir ./generated-embeddings/ -data ./aligned-images/

运行完后,这个./aligned-images/子文件夹会包含一个带有每张图像的嵌入的 csv 文件
(3)训练自己的面部检测模型:

./demos/classifier.py train ./generated-embeddings/

这将产生名为./generated-embeddings/classifier.pkl的新文件名。这个文件有你将用来识别新面部的 SVM 模型。
到了这,你应该有一个可用的面部识别器。

(4)识别面部!
    获取一张未知脸的新照片。把它像这样传递给分类器脚本:

./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 脚本 做任何你想做的。
    重要提示:
     (1)如果你得到了坏的结果,请尝试在第三步中为每个人添加更多一些照片(尤其是不同姿势的照片)。
(2)这个脚本总是会给出一个预测,即便是一张它不知道的脸。在真实的应用中,你会看到信度得分,并抛除低信度的预测,因为它们很可能是错误的。

如何掌握Facebook自动人脸识别技术?相关推荐

  1. 删除10亿人脸数据,Meta关闭了Facebook的人脸识别系统

    来源:机器之心 本文约1700字,建议阅读5分钟 本文为你介绍了Meta在人脸识别系统上的最新动态. 选择一劳永逸,Meta 再不想为 Facebook 的人脸识别系统「买单」了. 在近期召开的 Fa ...

  2. 人脸识别技术离滥用仅一步之遥?

    1. "老大哥正在看着你" 进入人工智能产业落地期,人脸识别技术已成为安防.金融.医疗.教育.智慧城市等领域应用最广的技术.在国内,学校利用人脸识别,监督上课不专心的学生:公厕利用 ...

  3. 刷脸时代来临,深度解析人脸识别技术市场

    刷脸时代来临,深度解析人脸识别技术市场 编者按:iPhone X带动更多智能手机集成3D人脸识别,公共场所日益增长的监控需求.刷脸时代来临,人脸识别技术巨大的市场需求与广阔的应用前景,盈利模式多变,消 ...

  4. [图文]解读《碟中谍4》中的人脸识别技术

    转自:http://www.shengwushibie.com/Article/Doc/201202/747.shtml 在茫茫人海的火车站走来走去,只要一眨眼的功夫已经被认出,随即被特工盯梢:迎面相 ...

  5. 人脸识别(7)---国内人脸识别技术 十大算法公司排名

    国内人脸识别技术 十大算法公司排名 科技特讯11月18日讯:1.云从科技 背靠"计算机视觉之父",中科院实验室创业团队创立云从科技 云从科技团队成员除了来自中科大的校友外,还来自中 ...

  6. 大数据早报:路桥率先利用“人脸识别”技术监管医保 亚马逊与微软联合开发人工智能,打造服务大众的AI(10.19)

    数据早知道,上乐投网看早报! 『数据安全』微软内部Windows漏洞数据库曾被入侵:后果可怕 作为这个星球上覆盖率最高的操作系统,Windows的一举一动都影响着大家的使用体验,对于它的安全微软也是相 ...

  7. 人脸识别技术的优缺点

    面部识别曾被视为未来文明进步的象征,尤其是在<星际迷航>(StarTrek)或<2001:太空漫游>(2001:SpaceOdyssey)等科幻作品中,它已迅速成为我们日常生活 ...

  8. 人脸识别技术及其应用领域

    2019-10-05 16:11:18 人口安全保障网今日公布一条重要信息.据中科蓝海报道:人脸识别技术及其应用领域 接下来让我们看看具体报道内容: 自20世纪下半叶,机器视觉技术逐渐地发展壮大.同时 ...

  9. 一文看懂人脸识别技术发展脉络

    来源:InfoQ 人脸识别可以说是人工智能领域中成熟较早.落地较广的技术之一,从机场.火车站的安检闸机,到平常用户手机中的"刷脸"支付,人脸识别技术已经深入到我们的生活当中. 为了 ...

最新文章

  1. 加速mysql导入时间_加快mysql导入导出速度
  2. SuperSocket .net服务框架
  3. 极致进化-敏捷进化型企业的未来畅想
  4. SpringCloud之Hystrix
  5. Java黑皮书课后题第5章:*5.48(处理字符串)编写一个程序,提示用户输入一个字符串,显示奇数位置的字符
  6. jQuery+pjax简单示例汇总
  7. 闲来无事,仿了一个百度杀毒主界面
  8. WinForm 下实现一个自动关闭的MessageBox
  9. c++中list用法
  10. sql子查询示例_学习SQL:SQL查询示例
  11. STM32F103mini教程学习总结与心得(五)---->通用定时器
  12. 基于java的小额支付管理平台
  13. linux自定义自动补全命令
  14. 程序开发,也要匠心独运
  15. Node.js 实现登录校验 + 选项卡(改进版)
  16. Kafka学习整理三(borker(0.9.0及0.10.0)配置)
  17. 用谷歌浏览器检查功能实现精灵图
  18. 使用Unity制作游戏AI
  19. element的formatter失效的解决方案
  20. 【SWT】创建自己的SWT组件

热门文章

  1. DWORD类型与16进制字符串之间的相互转换
  2. 大数据平台常见面试题
  3. APCAD三维开发平台简介
  4. IDEA编译器快捷键
  5. 数字图像处理 tofloat函数说明
  6. python微信机器人pc端
  7. Keil C51与ARM兼容安装
  8. 手机上怎么压缩视频?教你两个手机压缩视频小技巧
  9. 关于光纤传播速度比铜线快的误解
  10. web项目部署到服务器上出现验证码乱码问题解决方案