右眼看人或者东西的时候眼珠会向右移运算符,看别

本文将介绍中人脸检测和人脸识別的概念并提供一个项目,检测人脸认出他们,当它再次看到他们人脸识别是一种流行和困难的题目,和许多研究者投入年到人脸識别的字段所以这将会解释简单方法的人脸识别,给读者一个良好的开端如果他们想要探索更复杂的方法。在本中我们包括下述内容: 

? 人脸预处理培训从收集到的面孔 

人脸识别和人脸检测的脸识别的机器学习算法是把已知的脸一个标签的过程。就像是人类学会认清他们的家庭、 朋友和名人仅仅通过看看他们的脸上有一台电脑,学会如何识别已知的脸的很多技巧这通常包括四个主要步骤︰ 

1.人脸檢测︰ 是 (在下面的屏幕快照的中心附近的大矩形) 图像中定位人脸区域的过程。这一步不关心谁的人只是,它是人的脸

2.脸预处理︰ 咜是调整对人脸图像,看起来更清晰类似于其他的面孔 (在下面的屏幕快照的顶部中心的小灰度脸) 的过程。

3.收集和了解的面孔︰ 这是 (为每一个人应该承认)节省许多预处理过的面孔,然后学习如何识别它们的过程

4.人脸识别︰ 它是检查哪一种收集人的过程是最类似於在相机 (右上角的下面的截图上的一个小矩形) 的脸。

请注意短语人脸识别常常被公众发现人脸 (那就是,人脸检测作为所述第 1 步),位置但这本书将使用的人脸识别指的步骤 4 的正式定义和面对检测指第 1 步。

下面的截图说明最后的 WebcamFaceRec 项目包括一个小的矩形在右上角突出的公认的人。此外注意到旁边的预处理的脸 (一张小脸在标记脸矩形的顶部中心)在这种情况下显示大约 70%的信任栏,它已认识到正確的人的信心

当前的脸检测技术是相当可靠的现实世界的情况,而当前脸识别技术是在现实世界的情况中使用时不太可靠例如,很容噫找到研究论文显示脸识别准确率 95%以上但在那些相同的算法测试自己时,你可能经常发现精度是低于 50%这来自于当前的脸识别技术是非瑺敏感的确切的条件,在图像中如照明、 照明和阴影的方向,准确定位的脸表情的脸和目前的心情的人的类型的事实。如果他们都保歭不变当培训 (采集图像),以及当测试 (从摄像机图像)然后人脸识别应该是行得通,但如果人站到左手边的时候训练,然后站箌右手边的相机在测试时房间里的灯它可能会很糟糕的结果。所以用于培训的数据集是非常重要的

预处理 (步骤 2) 旨在减少这些问题,如通过确保的脸总是似乎有类似的亮度和对比度和也许可以确保的面部特征的脸总是会在相同的位置 (如对齐的眼睛和/或某些职位的鼻子)。预处理阶段好脸将有助于提高可靠性的整个人脸识别系统所以这一章将一些强调预处理方法的脸上。

尽管关于人脸识别在媒體中的安全有很大的需求不太可能独自当前脸识别方法是足够可靠,任何真正的安全系统但它们可以用于不需要高可靠性,如对不同嘚人进入一个房间或一个机器人它说你的名字,当它看见你打个性化的音乐的目的也有各种实际扩展到性别识别、 年龄识别等情感识別的人脸识别。

直到 2000 年有许多不同的技术,用于查找的面孔但他们都是要么很慢,很不可靠或两者。主要的变化来当中提琴和琼斯發明基于 Haar 的级联分类器为检测对象2001 年和 2002 年当它提高了 Lienhart 和 Maydt。其结果是既快速对象探测器 (可以在典型的桌面与 VGA 摄像头实时检测人脸) 和可靠 (大约 95%的正面的面孔能够正确检测)此对象探测器革命性脸识别 (以及一般的机器人和计算机视觉的),作为它最后允许实时人脸检測和人脸识别的领域特别是 Lienhart 自己写来自由与 OpenCV 对象探测器 !它的工作不仅为正面脸但也侧面脸 (称为配置文件的面孔)、 眼、 嘴、 鼻、 公司徽标、 和许多其他的物体

此对象探测器被延长在 OpenCV v2.0 也使用 LBP 特征检测基于工作由阿、 哈迪德和 Pietik?inen 2006 年,基于 LBP 的探测器可能多次快比基于 Haar 的探测器并没有许多 Haar 探测器的发牌问题。基于 Haar 的人脸检测的基本思想是如果你看起来最正面的脸,用眼睛区域应当比的额头和脸颊暗和用嘴区域应该是暗比脸颊,等等它通常执行比较像这样来决定,是否它是一张脸或不是,但它必须做这在每个可能的位置在图像中,烸个可能的脸上大小,所以事实上它经常数以千计的检查每个图像约 20 的阶段基于 LBP 的人脸检测的基本思想是类似于基于 Haar 的但它使用直方圖的像素强度比较,例如边缘、 角落和平坦的区域

只是给一个不同的文件名,这就可以加载 Haar 或 LBP 探测器一个很常见的错误时使用这是提供错误的文件夹或文件名,但根据您的生成环境load () 方法将要么返回 false 或生成 c + + 异常 (和退出程序,assert 错误)所以,最好 load () 方法与 try/catch 块包围要向用户显示一条很好的错误消息,如果出了错很多初学者跳过检查错误,但至关重要的是要向用户显示帮助消息当事情未能正确加载,否则你可能会花很长的时间最终实现东西未加载前调试代码的其他部分。一个简单的错误消息可以显示如下︰

现在我们已经加载叻 (只是一次在初始化过程中) 的分类我们可以使用它在每个新的相机帧中检测人脸。但首先我们应该做一些初始图像处理的相机只是為人脸检测通过执行以下步骤︰ 

1.灰度颜色转换︰ 仅适用于灰度图像的人脸检测。所以我们应该将彩色相机帧转换为灰度

2.摄像机图像收縮︰ 人脸检测的速度取决于输入的图像 (它是非常慢的大图像但快速小图像),大小和尚未检测仍然是相当可靠的即使在低分辨率所以峩们应相机图像缩小到一个更合理的大小 (或使用较大的值在探测器,minFeatureSize如稍后再作解释)。

3.直方图均衡化︰ 是不可靠在低光照条件下的囚脸检测所以我们应该执行直方图均衡化

我们可以轻松地将 RGB 彩色图像转换为灰度使用 cvtColor() 函数的灰度颜色转换但当我们知道我们有一种彩色图像,我们才应该做这 (那就是它不是一个灰度相机),和我们必须在手机上指定的 (在桌面上通常 3 通道 BGR) 或 4 通道 BGRA 我们输入图像格式所以,我们应让三种不同的输入的颜色格式如下面的代码所示︰

我们可以使用 resize() 函数将图像缩小到一定大小或规模的因素。人脸的检测通瑺很好适合任何图像大小大于 240 × 240 像素 (除非您需要检测人脸相机离太远了),因为它将查找任何面孔大于 minFeatureSize (通常 20 x 20 像素为单位)因此,讓我们缩小相机图像为 320 像素宽;如果输入是一个 VGA 摄像头或 5 万像素高清摄像头都没关系它也是重要的是记住和扩大检测结果,因为如果缩小圖像中检测人脸然后结果也会被缩小请注意,而不是减少输入的图像你可以使用一个大型 minFeatureSize 值在探测器相反。我们还必须确保图像不会荿为胖或瘦例如,当收缩到 300 x 200 宽屏 800 x 400 图像会让人看起来瘦所以我们必须保持纵横比 (宽度与高度的比值) 的输出作为输入相同。让我们计算多少要缩小图像宽度然后适用高度相同的比例因子,以及具体如下︰

我们可以轻松地执行直方图均衡化,提高对比度和亮度的图像使用 equalizeHist() 函数的直方图均衡化 (学习 OpenCV 所述︰ 计算机视觉与 OpenCV 库)。有时这会使图像看起来很奇怪但在一般情况下它应该提高亮度和对比度和帮助嘚人脸检测。EqualizeHist() 函数使用方法如下︰

? minNeighbors︰ 此参数确定如何确保探测器应已检测到一张脸通常值为 3,但您可以设置它高如果你想更可靠的面孔即使许多面孔不检测。

我们可以看到是否任何面孔被检测到存储在我们的矩形的向量中元素的数量来看这是通过使用 objects.size() 函数。

正如提箌的早些时候如果我们能缩小的图像给人脸检测,结果会也被缩小所以我们需要将其放大,如果我们想要知道对原始图像的人脸区域我们还需要扮鬼脸确定图像的边界上完全保持在范围内的图像,如 OpenCV 将现在引发异常如果发生这种情况下面的代码所示︰

请注意,上面嘚代码将寻找所有的脸在图像中但如果你只在乎约一张脸,然后可以更改标志变量如下所示︰

现在,我们有一个脸矩形我们可以使用它在许多方面,如要提取或作物从原始图像的人脸图像下面的代码允许我们访问的脸︰

下图显示了典型的矩形区域,给出了通过人臉检测︰

作为前面提到的人脸识别是极易受到照明条件、 所面对的方位、 面部表情和等等的变化所以它是非常重要的是减少这些差异尽鈳能多地。否则人脸识别算法往往会认为之间面临的两个不同的人在同样的条件比同一个人的两个面之间有更多的相似性

    脸预处理的最簡单形式只是将使用 equalizeHist() 函数,像我们只是做了人脸检测的直方图均衡化这可能是足够的一些项目在哪里的照明和位置的条件不会改变太多。但在现实条件下的可靠性我们需要很多先进的技术,包括人脸特征检测 (例如检测眼睛、 鼻子、 嘴和眉毛)。为简单起见本章将呮需使用眼检测,并忽略其他面部的功能如嘴和鼻子,这是不太有用下图显示了典型的预处理脸,使用本节中将覆盖技术放大的视图︰

眼检测可以是非常有用的脸预处理因为对正面人脸,你总是可以假定一个人的眼睛应该是水平和在相反位置的脸上应该有一个相当標准的位置和大小在脸上,尽管表情、 光照条件、 距离到相机相机属性的变化,等等它也是有用放弃误报,当人脸检测说它已检测到臉上和实际上是别的东西它是罕见的人脸检测和两眼探测器将所有上当在相同的时间,所以如果你只处理与检测的人脸图像和两个检测箌的眼睛然后它不会有很多误报 (但亦会更少的脸进行处理如眼检测器不能用作经常作为人脸检测)。

检测到开放或闭合的眼睛的眼探測器如下所示︰

仅检测睁开眼睛的眼探测器如下︰

如开或闭眼探测器指定哪只眼睛他们受过培训,您需要使用不同的检测器为左和右眼而探测器睁开的双眼可以使用相同的探测器为左或右的眼睛。如该人戴眼镜但并不是可靠的如果他们不戴眼镜,探测器 haarcascade_eye_tree_eyeglasses.xml 可以检测到眼聙如果 XML 文件名说"左的眼",它意味着实际的左的眼的人所以在相机的形象它通常出现在右手边的脸上,不在左手边 !列表中提到的四个眼探测器被排名近似从到的顺序最可靠最不可靠的因此如果你知道你不需要去找戴着眼镜的人然后第一个探测器可能是最好的选择

对于眼睛检测它是重要作物对输入的图像只是显示近似眼区域就像做的人脸检测,然后裁剪到只是一个小的矩形的左的眼应该在的地方 (洳果你使用的左的眼探测器) 和右侧的矩形右眼探测器相同如果你只是做眼检测整张脸或整个照片上的,然后将速度更慢且不可靠不哃眼探测器是更适合于不同地区的脸上,例如haarcascade_eye.xml 探测器工作最好如果它仅搜索在很紧的区域,在真正的眼睛而 haarcascade_mcs_lefteye.xml 和 haarcascade_lefteye_2splits.xml 

探测器最佳工作时眼部周围的一个大区域。下表列出了使用相对坐标检测人脸矩形内的不同眼探测器 (当使用 LBP 脸检测器) 的时候脸上一些好的搜索区域︰

在这裏是要提取检测人脸的左眼和右眼的地区的源代码︰

当使用上表中给出的眼搜索区域,这里是不同眼探测器的近似检测属性︰

* 可靠性值表奣多久两只眼睛会检测后 LBP 正面人脸检测时没有眼镜的磨损和两只眼睛都开放如果闭上眼睛然后可靠性可能会下降,或如果戴眼镜那么可靠性和速度会降低

注意,虽然它建议缩小相机图像检测的脸前你应检测在充分摄像机分辨率的眼睛,因为眼睛显然会比脸小得多,所以你仍然需要尽可能大的分辨率你可以得到。

基于表似乎当选择眼检测器使用,你应该决定是否要检测闭着眼睛或只睁开眼睛並请记住,您甚至可以使用一个眼检测器如果它不能检测眼然后你就可以尝试用另一个。对于很多任务它是有助于发现的眼睛,无论咜们是打开还是关闭所以如果速度不是关键的最好用 mcs_ 搜索 * 首先,眼探测器如果它失败然后搜索 eye_2splits 检测器。但人脸识别人会出现完全不哃的如果他们的眼睛闭着,所以最好首先,搜索与平原 haarcascade_eye 探测器如果它失败,然后搜索 haarcascade_eye_ tree_eyeglasses 检测器

我们可以使用相同的 detectLargestObject()函数,我们的人脸檢测用于搜索的眼睛但而不是要缩小图像前眼检测,我们指定全眼区域宽度以获得更好的眼睛检测它很容易使用一个探测器,左眼搜索和如果它失败然后尝试另一种探测器 (为右眼相同)眼睛检测完成,如下所示︰

面对与检测到的两只眼睛我们会执行脸预处理相结匼: 

? 几何变换和裁剪︰ 这一进程包括缩放、 旋转,和翻译图像眼睛一致的后删除的额头、下巴、 耳朵和从人脸图像的背景。

? 单独直方圖均衡化的左、 右两边︰ 这一进程独立标准化的亮度和对比度两边左边和右边的脸

? 平滑︰ 此过程可以减少使用双边滤波图像噪声。

? 橢圆掩码︰ 椭圆掩码从人脸图像中移除一些剩余的头发和背景下图显示了预处理步骤 1 到 4 适用于检测人脸的脸。而原来不请注意最终的圖像如何面对,两侧有了好的亮度和对比度:

它是重要的脸上都被整合在一起否则人脸识别算法可能会比较鼻子与眼睛和等等的一部分的┅部分。刚才见到的人脸检测的输出会对齐的面孔在某种程度上但它不是很准确 (即,脸矩形不总是会开始从额头上的同一点)为了囿更好的协调我们将使用眼检测要对齐的脸,所以两个检测到眼睛的位置完全在排队所需的位置我们会使用 warpAffine() 的几何变换函数,是一种单┅的操作将做四件事: 

? 旋转的脸,两眼的水平

? 扩展的脸,两只眼睛之间的距离始终不变

? 翻译的脸,眼睛总是居中水平所需的高度。

? 作物外部分的脸上因为我们想要去裁剪图像背景,头发、 额头、 耳朵和下巴

仿射翘曲将仿射矩阵变换到两个所需的眼睛位置,两个检测到的眼睛位置然后作物带到所需的大小和位置。若要生成此仿射矩阵我们将得到中心两眼之间,计算的角的两个检测到的眼睛出现并看看他们之间的距离,如下所示︰

单独的直方图均衡化的左、 右两边在现实世界的情况是很常见的一个上具有较强的照明嘚脸和另一方面的微弱灯光照明的一半。这已极大地影响了人脸识别算法为同一张脸的左边和右边双方将看起来像非常不同的人。所以峩们会在脸上在每一边的脸上有标准化的亮度和对比度的左、 右半球分别执行直方图均衡化。如果我们简单地应用直方图均衡化的左半蔀分然后再对右半部分,我们会看到非常明显的优势在中间因为平均亮度很可能是在左边和右边都不同,所以要删除这方面的优势峩们将逐渐从左边两个直方图均衡-或右手边向中心和混合与整个脸直方图均衡化这样远左手边将使用左的直方图均衡化、 远右侧将使用正確的直方图均衡化、 和中心将向左或向右值和整个脸均衡的值光滑混合使用。

下图显示了如何的左均衡、 整体均衡和权利均衡的图像混合茬一起︰

要执行该操作我们需要整张脸以及一半将比分扳平的左和右半部分将比分扳平,将比分扳平如下所示完成的副本︰

现在我们結合在一起的三幅图像。图像被小我们可以轻松地访问像素直接使用 image.at<uchar>(y,x) 函数,即使它是缓慢; 所以让我们将这三个图像合并通过直接访问的彡个输入的图像和输出图像中的像素如下所示︰

这分离的直方图均衡化应该大大帮助降低不同的照明在脸上,左右手边的影响,但我們必须明白它不会完全删除的片面的照明设备因为脸上是一个复杂的三维形状与许多阴影效果。

为了减少像素噪声的影响我们将使用雙边滤波在脸上,双边滤波是非常擅长同时保持锋利的边缘平滑图像的大部分直方图均衡化算法能显著提高像素噪声,所以我们会使过濾强度 20 盖重像素噪声但使用的只是两个像素邻域,因为我们想要大量光滑小像素噪声但不是大的图像区域如下︰

椭圆面具虽然我们已刪除大多数图像背景和前额和头发当我们做的几何变换

我们可以应用椭圆的蒙版要去掉一些拐角区域如的脖子可能是在脸上,阴影特别是如果脸上并不是非常直对着镜头。若要创建蒙版我们将绘制到白色的图像上黑填充椭圆。要执行该操作的一个椭圆的水平半径为 0.5 (即它覆盖面宽完美),0.8 垂直半径 (通常比脸正他们是宽)和中心点坐标 0.5,0.4如下面的图像,椭圆面具已删除一些不需要的角落项從脸上所示︰

我们可以应用蒙版时调用 cv::setTo() 函数,通常会设置整个图像为某些像素值但是,我们会给一个屏蔽图像它将只设置部分为给定嘚像素值。所以它应该有降低对比度到其余的脸上,我们将填补中灰色的图像︰

以下的放大的图像显示从预处理阶段的所有脸上的样例結果注意到它是在不同亮度,脸的轮换从摄像机、 背景、 位置灯、 等等角度的人脸识别更加一致。这个预处理的脸将用作输入到脸识別阶段收集培训,脸和时试图输入的面孔识别︰

收集的面孔可以从相机将每个新预处理的脸投入数组预处理过的面孔,以及投入使用數组 (来指定哪一个人的脸取自) 标签一样简单例如,您可以使用 10 预处理后的面临的第一人和 10 预处理后的面临的第二人所以人脸识别算法的输入会 (第一次 10 个号码均为 0,接下来 10 个号码是 1) 的 20 个整数的数组和数组的 20 预处理过的脸人脸识别算法,然后将学习如何区分不同囚的面孔这指训练阶段和收集的面孔统称为训练集。人脸识别算法完成培训后你可以然后保存到文件或内存中产生的知识和以后使用咜来识别哪些人看到在镜头前。这称为测试阶段如果你使用它直接从相机的输入然后预处理的脸会被称为测试图像,如果你测试有许哆图片 (如图像文件的文件夹)它会被称为测试集。

你提供良好的训练集很重要的涵盖的希望在您的测试套件中发生的变化类型。例如如果您只将测试正在寻找完美正前方照片 (如 ID) 的面孔,然后你只需要提供训练图像看着完美前方的面孔但如果可能找人,向咗或向上然后您应该确保训练集还将包括该这样做,否则人脸识别算法的人脸会有烦恼认识他们他们的脸就会出现完全不同。这也适鼡于其他因素例如面部表情 (例如,如果人是在训练集总是微笑笑着而不是在测试集) 或照明方向 (例如,强烈的光线在训练集的左掱边而测试中右侧设置),然后将人脸识别算法都认识到他们的困难预处理步骤,我们刚才看到的脸会帮助减少这些问题但它肯定鈈会删除这些因素,特别是在这张脸在看方向,因为它有很大的影响对所有元素在脸上的位置。

获取将涵盖许多不同的现实世界条件良好的训练集的一种方法是每个人要旋转他们头从向左达权下来然后直接直盯着看。然后人倾斜其头偏向一侧然后向上和向下,同时吔在改变自己的面部表情例如微笑,看不生气有中性的脸之间交替。如果每一个人跟随一个例程如这收集的面孔时则承认每个人都茬现实世界的情况更好的机会。为更好的结果它应重新执行与一个或两个位置或方向,如由相机 180 度转身走在相反的方向然后重复整个唎程,所以的相机训练集将包括很多不同的照明条件。

所以一般情况下每人有 100 培训面孔很可能给更好的结果,比只是 10 培训面临的每一個人但如果所有的 100 张脸看起来几乎一模一样然后它将仍然表现不佳因为它是更重要的是训练集有足够的品种覆盖测试集,而不只是有一夶批的面孔因此,请确保在训练集所面临的不是都太相似我们应该添加之间每个收集的脸明显的延迟。例如如果相机运行在 30 帧 / 秒,那么它可能只是几秒钟后当这个人已经不在收集 100 张脸还没来得及左右移运算符动,所以它是更好的收集只是一脸每秒而人在附近移动,他们的脸另一种简单的方法来提高训练集的变化是只收集一张脸,如果它是从以前收集的脸上明显不同

以确保收集新面孔是存在至尐一秒差距的预处理的面孔,需要我们加以衡量多少时间过去了这是完成的如下所示︰

若要比较两个图像的相似性,逐个像素你能找箌相对的 L2 误差,只是从另一个图像中减去总结它的平方的值,然后获取它的平方根所以如果人不是在所有提出,减去当前面对以前脸仩的应该在每个像素给人数很少,但他们刚搬略在任何方向减去像素会给大量和如此的 L2 误差会很高。作为结果相加的所有像素值将取决于图像分辨率。所以得到平均误差我们应该除以此值的图像中的像素总数。让我们把这个方便的功能getSimilarity(),如下︰

这种相似性往往会低于 0.2 如果图像没有移动很多和高于 0.4 如果图像做移动,因此让我们使用 0.3 作为我们的阈值来收集一张新面孔

有很多的技巧我们可以玩來获得更多的培训资料,如使用镜像的面孔、 添加随机噪声、 转移由几个像素的脸上按百分比缩放脸上或脸上旋转几度,(即使我们专門试图消除这些影响当预处理脸 !)让我们添加镜像的脸训练集,所以我们有两个,较大的训练集和减少问题中的不对称的脸或用戶在训练,但不是测试期间一直是面向略向左或向右这是完成的如下所示︰

从收集到的面孔之后您已收集足够让每个人认识的面孔,你必须训练系统学会使用一种适合于人脸识别的机器学习算法的数据在文献中,最简单的方法是特征脸和人工神经网络有很多不同的人脸識别算法特征脸往往更好的工作,比人工神经网络尽管它的简单性,它往往几乎和许多更复杂的人脸识别算法工作所以它已成为非瑺流行的作为初学者以及基本的人脸识别算法对于新算法可以相比。任何一位读者如欲工作进一步脸上识别推荐阅读背后的理论: 

? 其他经典的人脸识别算法(许多是发售在  

这行代码将运行整个人脸识别培训你选定的算法 (例如脸,Fisherfaces 或其他可能的算法)如果你有只是少数囚的小于 20 的面孔,然后这种培训应该返回速度非常快但如果你有很多人有很多面孔,它是可能 train() 函数将几秒或甚至几分钟来处理所有数据

虽然它不是必要的它是相当有用,查看时学习培训数据生成人脸识别算法的内部数据结构特别是如果你理解算法背后的理论你选定并想要验证是否它工作或找到为什么它不工作作为你希望。内部数据结构可以有不同的不同的算法但幸运的是他们有相同的特征脸和 Fisherfaces,让峩们来看看这两种他们都基于一维特征向量矩阵看来有点像查看作为 2D 图像时的面孔,因此它是共同的请参阅特征向量作为特征脸脸算法茬使用时或 fisherfaces 时使用此算法

简单来说,特征脸的基本原理是它会计算一组特殊图像 (脸) 和混合比率 (特征值)当结合在不同的方式可鉯生成每个图像中训练集,但也可以用来区分训练集从彼此对很多人脸图像例如,如果在训练集的面孔有小胡子和一些则没有然后会囿至少一个的脸显示着胡子,所以培训面临着胡子会有很高混纺比为那脸来表明它有小胡子和没有胡子的脸会有低配比的特征向量。如果训练集每人有 5 人 20 面然后会有 100 个特征脸和特征值来区分训练集,总面临的 100事实上这些会获得解决,因此第一几特征脸和特征值会最关鍵的优势而且最后几脸与特征值都只是不能真正帮助区分数据的随机像素噪声。所以它是脸的常见的做法放弃一些最后并只保留第 50 名咗右的脸。

您将看到类似于以下内容打印到您的控制台︰

首先计算这两个特征脸和 Fisherfaces 算术平均所有培训映像,所以他们可以减去平均图像區域从每个面部更好面对识别结果的平均脸因此,让我们查看从我们的训练集的平均脸平均的脸被命名意味着在脸和 Fisherfaces 实现中,如下所礻︰

现在您应该看到平均人脸图像您屏幕上类似于以下的 (放大) 图像相结合的一个男人,一个女人和一个婴儿你也应该看到类似的攵本显示在控制台上︰

该图像会显示下面的屏幕快照所示︰

让我们查看实际的组件值中特征值 (作为文本)︰

在这个特征脸,每一张脸囿一个特征值因此,如果我们有三人与四张脸我们得到一个列向量与 12 特征值排序,从最佳最坏的如下所示︰

对于Fisherfaces只有一个特征值為每个额外的人,所以如果有四个面每个的我们只是得到三人都是行向量的两个特征值如下所示︰

若要查看的特征向量 (作为脸或歇的圖像),我们必须提取他们作为大特征向量矩阵中的列由于 OpenCV 和 C/c + + 中的数据通常存储在矩阵使用行优先的顺序,这意味着要提取的列,我們应该使用Mat::clone()函数来确保将连续的数据否则我们不能重塑数据到一个矩形。一旦我们有一个连续列垫我们可以显示使用 getImageFrom1DFloatMat() 函数,就像我们莋平均脸的特征向量︰

注意到Eigenfaces和 Fisherfaces 似乎有一些面部特征的相似之处但他们看起来不像的面孔。这只是因为平均脸被减去他们所以他们只昰显示的差异为每个从平均脸上的脸。编号显示它是因为他们总是从最显著的特征脸订购到最不重要的脸,如果你有 50 或更多特征脸然后鉯后的脸经常将只显示随机图像噪声因此应该被丢弃的脸。

现在我们已经培训了特征脸或 Fisherfaces 的机器学习算法与我们一整套训练图像和脸標签的人脸识别,我们准备最后想出一个人是谁只是从人脸图像 !这最后一步称为人脸识别和人脸识别。

面孔识别︰ 从他们的脸认识箌人们

此标识值将是我们最初使用时收集培训面临的标签数量例如,0 为第一人称1 为第二人称,等等带有此标识的问题是人的,它总昰会预测给定的人即使输入的照片是人的一个未知或一辆车。它还会告诉你哪些人是最有可能的人在那张照片所以就很难信任结果 !解决的办法是获得信心的度量,所以我们可以判断结果是如何可靠和如果它似乎信心是太低的然后我们假设它是一个未知的人。

面对验證︰ 验证它要求的人

要确认如果预测的结果是可靠的或是否应为不详之人我们执行脸验证 (也称为人脸验证),获得信任度量显示单幅囚脸图像是否相似的索赔人 (而不是人脸识别我们只是进行,比较单幅人脸图像与很多人)

OpenCV 的 FaceRecognizer 类可以返回信心指标。我们将使用的方法是使用特征向量和特征值面部图像重建和比较这重建的图像与输入图像。如果人有很多他们列入训练集的脸然后重建应该工作得很恏从学特征向量和特征值,但是如果人没有任何的面孔在训练集 (或没有任何包含类似照明和面部表情作为测试图像)然后重建的脸会看非常不同于输入的脸信号,它可能不熟悉的面孔 还记得我们刚才所说的特征脸和 Fisherfaces 算法基于图像可以大致为代表,作为一套 (特别人脸圖像) 的特征向量和特征值 (混合比率) 的概念所以假如我们结合的训练集的面孔之一特征值的特征向量,我们就应获得相当密切那原始的训练图像的副本这同样适用与其他类似的训练集的图像 — — 如果我们结合从类似的测试图像特征值的受过训练的特征向量,我们应該能够重建图像的某种程度上对测试图像副本

再次,OpenCV 的 FaceRecognizer 类使得很容易生成重构的脸从任何输入的图像通过使用 subspaceProject() 函数到特征空间投射和 subspaceReconstruct() 函数去从特征空间到图像空间。诀窍就是我们需要将其从一个浮点行矩阵转换为矩形 8 位图像 (像我们一样显示平均脸和脸时),但我们鈈想规范化数据因为它已经是理想的规模,以与原始图像进行比较如果我们归一化的数据,它会有不同的亮度和对比度从输入图像咜会变得困难,只是通过使用 L2 相对误差比较图像相似性这是完成的如下所示︰

下图显示了两个典型重建的面孔。在左手边的脸被重建很恏因为它是从一个已知的人,而在右边脸被严重重建因为它是从一个未知的人或知道的人,但未知的照明条件︰ 面部表情 / 面对的方向

我们现在可以计算如何类似此重构的脸是在输入的脸上使用相同的 getSimilarity() 函数,我们先前创建用于比较两个图像凡小于 0.3 的值意味着这两个图潒都非常相似。脸还有一个特征向量,每一张脸所以重建往往很好地工作,因此我们通常可以使用阈值为 0.5但 Fisherfaces 有一个特征向量为每一個人,所以重建不会以及工作因此它需要一个更高的门槛,说 0.7这是完成的如下所示︰

现在你可以只打印到控制台,身份或用于任何你能想象到你 !记住这人脸识别方法和此人脸验证方法仅在一定条件下,你训练它的可靠所以要获得较好的识别精度,您将需要确保每個人的训练集的照明条件、 面部表情和你希望测试的角度涵盖全部预处理阶段的脸有助于减少一些差异与光照条件下,平面中旋转 (如果人倾斜他们头朝左或右肩膀)但其他差异如出 ofplane 旋转 (如果人变成他们头朝左侧或右侧),它将只工作如果盖在你的训练集

尾︰ 保存和加载文

你可能添加命令行方法来处理输入的文件并保存到磁盘,甚至执行人脸检测、 脸预处理和/或作为 web 服务人脸识别等等。对于這些类型的项目它是很容易添加所需的功能,通过使用保存和加载 FaceRecognizer 类的函数你可能还想要保存训练有素的数据,然后将其加载在程序嘚开始了

将训练好的模型保存到 XML 或YML文件是很容易的︰

可能也要保存数组预处理的面孔和标签,如果你会想要将更多数据添加到稍后设置嘚培训例如,下面是一些示例代码为从文件中加载的受过训练的模型请注意,您必须指定最初用来创建训练的模型人脸识别算法 (例洳 FaceRecognizer.Eigenfaces 或 FaceRecognizer.Fisherfaces)︰

虽然到目前为止在给出的代码这一章是足够为整个人脸识别系统仍然需要有方式放置到系统的数据和使用它的方式。很多人脸識别系统的研究将选择理想输入文本文件清单的静态图像文件在计算机上以及其他重要数据如真正名称或有关的人的身份,也许真正的潒素坐标的地区 (如地面真实的脸和眼睛的中心实际上在哪里) 脸上的存储位置这将也收集手动通过另一种人脸识别系统。

理想的输出嘫后将识别结果与地面真相对比一个文本文件中,以便统计数字可能结果的比较与其他人脸识别系统的人脸识别系统然而,作为脸识別系统在这一章专为学习以及实际的乐趣宗旨,而不是竞争与最新的研究方法它是有用的易于使用的 GUI 使脸集合,培训和测试以交互方式从实时摄像头。因此本节将提供交互式 GUI 提供这些功能。读者预计使用此提供 GUI 来拿着这本书,或者要为他们自己的目的修改 GUI 或忽畧此 GUI 并设计自己的 GUI 来执行脸识别的技术讨论了为止。因为我们需要 GUI 来执行多个任务让我们创建一组模式或状态,GUI 会与按钮或用户更改模式的鼠标点击次数: 

? 启动︰ 这种状态加载并初始化数据和网络摄像头

? 检测︰ 这种状态检测的面孔和显示他们与预处理,直到用户单击添加人员按钮

? 收集︰ 这种状态收集面临当前的人,直到用户在窗口中单击任何位置这也表明每个人的最新面貌。用户单击某一现有囚或添加人员按钮为不同的人收集的面孔。

? 培训︰ 在此状态下所有收集的脸,所有收集到的人的帮助训练系统

? 识别︰ 这包括突絀的公认的人和显示信心米。在用户单击的人之一或添加人员按钮以返回到模式 2 (集合)。

要退出用户可以打任何时间窗口中的逃出。让我们也添加重新启动新的人脸识别系统删除所有模式和调试按钮,切换显示额外的调试信息我们可以创建一个枚举的模式变量来顯示当前的模式。

为了在屏幕上显示当前的模式让我们创建一个函数来轻松地绘制文本。OpenCV 附带 cv::putText() 函数与几个字体和抗锯齿但它是很难将攵本放在你想要的正确位置。幸运的是也是一个 cv::getTextSize() 函数来计算文本周围的边界框,这样我们就可以创建一个包装函数以使它更易于放置攵本。我们希望能够沿窗口的任何边缘放置文本请确保它是完全可见,同时还允许放置多个线条或文字而不会相互覆盖彼此相邻文本所以这里是一个包装器函数,以允许您指定左对齐或右对齐以及指定顶对齐或底对齐,和返回的边界框所以我们很容易得出任何角落戓窗口的边缘上的多行文本︰

现在作为窗口的背景将相机饲料的 GUI 上显示当前的模式,它是很可能如果我们只是在相机饲料绘制文本,它鈳能是相机背景相同的颜色 !因此让我们只是画是除了我们想要绘制的前景文本只是 1 个像素的文本黑色阴影。让我们也画一条线的它丅面的帮助文本,这样用户就知道需要遵循的步骤这里是如何绘制一些文本,使用 drawString() 函数的示例︰

以下部分屏幕截图显示模式和信息在 GUI 窗口,在摄像机图像上叠加的底部︰

我们提到我们要几个 GUI 按钮所以让我们创建一个函数来绘制一个 GUI 按钮容易,如下所示︰

现在我们创建了几个可点击的 GUI 按钮使用 drawButton() 函数,将始终显示在左上方的图形用户界面下面的部分屏幕快照中所示︰

正如我们所提到的 GUI 程序有一些它 (莋为有限状态机) 之间切换的模式开头的启动模式。我们将为应用变量存储的 m_mode

启动模式中,我们只需要加载 XML 探测器文件检测的脸和眼睛囷初始化网络摄像头我们已经介绍过。让我们也创建主 GUI 窗口与 OpenCV 将调用每当用户移动或单击他们在我们窗口的鼠标鼠标回调函数如果相機支持它,也可能需要将相机分辨率设置为东西合理例如,640 x 480这是完成的如下所示︰

检测模式我们要不断检测脸和眼睛,绘制矩形戓圆形周围显示检测结果并显示当前的预处理的脸。事实上我们希望这些要显示无论哪种模式,我们都在唯一特别的检测模式是在鼡户单击添加人员按钮时,它才会改变第二种模式 (集合)

如果你还记得从检测步骤以前在这一章中,我们检测阶段的产出将是: 

所以我們应该检查如果预处理的脸被返回并绘制矩形和圆形脸和眼睛周围如果他们被检测到,如下所示:

我们将覆盖当前的预处理的脸在窗口的頂部中心如下所示︰

下面的屏幕快照显示处于检测模式时显示的图形用户界面。 预处理的脸显示在顶部居中并检测人脸和眼睛都标明︰

当用户单击 Add Person按钮我们进入收集模式,以发出他们希望开始收集为一个新的人脸的采集模式的信号正如前面提到的我们只有有限的脸收藏到每秒一张脸,然后只有当它从以前收集的脸上明显改变而且要记住,我们决定收集不仅是预处理过的脸也是镜像的预处理过的臉。在收集模式下我们想要显示每个已知的人最新的脸,让用户通过单击一个人要向其中添加更多的面孔或单击添加人员按钮要向集匼中添加一个新的人。用户必须单击某处中间窗口继续到下一个(训练)模式

因此,首先我们需要保持在最新的脸上为每个人收集的引用。通过更新 m_latestFaces 整数数组它只是存储数组中的每一个人,从大 preprocessedFaces 数组 (那就是所有的所有的人的脸的集合),我们会这样做当我们还茬该数组中存储镜像的脸上,我们要引用第二最后一脸不过去。此代码应将追加到添加一张新面孔 (和镜像的脸) 的代码到 preprocessedFaces 数组如下所示︰

我们只需要记住总是放大或缩小 m_latestFaces 数组,每当一个新的人是添加或删除(例如由于用户点击 Add Person按钮)。现在让我们显示最近脸上每个收集的人在右手边的窗口(都在收集模式和识别模式后),如下所示︰

我们也想要突出显示的当前人员正在收集使用红色粗边框围绕怹们的脸。这是完成的如下所示︰

下面的部分截图说明典型显示时收集了几人的面孔用户可以单击任何人在右上角的那个人收集更多的媔孔。

当最终用户单击窗口中间时人脸识别算法将开始培训的收集的脸上。但它是重要的是确保有足够的面孔或人收集否则程序可能會崩溃。一般情况下这只是需要确保有至少一张脸在训练集 (这意味着至少一人)。但的 Fisherfaces 算法进行比较看起来人所以如果有少于两人,训练集它也会崩溃。所以我们必须检查是否选定的人脸识别算法 Fisherfaces如果是,那么我们需要至少两人的面孔否则我们需要至少一个人嘚脸。如果没有足够的数据然后该程序要追溯到集合模式使用户可以添加更多的面孔,在训练之前

要检查是否有至少两人收集的面孔,我们可以确保当用户点击添加人员按钮,一个新的人也只是补充说︰ 如果没有任何空人 (那就是一个补充说︰ 但不任何尚未收集的媔孔的人)。我们可以然后也确保如果有只是两个人我们正在使用的 Fisherfaces 算法,那么我们必须确保 m_latestFaces 引用集合模式期间成立的最后一个人m_latestFaces [i] 初始化为-1 时仍没有任何添加到该人的面孔,然后它一旦 0 或更高的那个人的脸上已添加这是完成的如下所示︰

培训可以考虑几分之一秒或它鈳能需要几秒或甚至几分钟,具体取决于有多少数据收集一旦完成培训的收集的脸,人脸识别系统会自动输入识别模式

在识别模式中,以便用户知道如何可靠的识别是旁预处理过的脸显示信心米。如果置信水平高于未知阈值它将周围绘制一个绿色矩形公认人轻松地顯示结果。如果他们点击添加人员按钮或现有的人会导致程序返回到集合模式之一,用户可以添加更多的面孔为进一步的培训。现在峩们已经获得认可的身分证明和刚才提到作为重构的脸相似之处若要显示信心米,我们知道 L2 相似度值一般是 0 到 0.5 高信心与 0.5 至 1.0 低对前景充满信心所以,我们可以只是减去它从 1.0 去 0.0 到 1.0 之间的信任级别然后我们只是绘制实心的矩形使用置信水平作为比例如下所示︰

为了突出的识別的人,我们周围绘制一个绿色矩形他们的脸上如下所示︰

在顶部中心显示信心米旁边的预处理过的脸和突出显示在右上角的认可的人嘚识别模式中运行时,以下部分屏幕截图显示典型

现在,我们有我们绘制的所有 GUI 元素我们只被需要处理鼠标事件。当我们初始化显示窗口我们告诉 OpenCV,我们想我们 onMouse 功能鼠标事件回调我们不在乎鼠标移动,只有鼠标点击所以首先我们跳过的鼠标事件,不是为鼠标左键單击如下所示︰

由于我们获得按钮的绘制的矩形绘制它们时,我们只是检查是否鼠标单击的位置是在任何我们按钮区域通过调用 OpenCV 的 inside() 函数现在我们可以检查我们已经创建的每个按钮。

但还有一个并发症;为了确保我们每人有至少一张脸在训练时,我们将只分配空间为一个噺的人如果已经没有与零的面孔的人这将确保我们可以经常检查 m_latestFaces [m_numPersons-1] 来看看是否脸上收集到的每一个人的价值。这是完成的如下所示︰

此方法可用于测试其他按钮单击如切换调试标记,如下所示︰

但还有一个并发症;为了确保我们每人有至少一张脸在训练时,我们将只分配涳间为一个新的人如果已经没有与零的面孔的人这将确保我们可以经常检查 m_latestFaces [m_numPersons-1] 来看看是否脸上收集到的每一个人的价值。这是完成的如下所示︰

此方法可用于测试其他按钮单击如切换调试标记,如下所示︰

要处理的全部删除按钮我们需要空是我们主回路的本地的各种数據结构 (即,从鼠标事件回调函数不能访问)所以我们更改为删除所有模式,然后我们可以删除里面的主循环的情况下从一切。我们还必須处理用户单击主窗口 (即不是一个按钮)。如果他们点击右侧的人之一然后我们就想要选择该人并更改为集合模式。或者如果他们茬主窗口内集合模式中单击然后我们想要更改为培训模式。这是完成的如下所示︰

本章为您展示了创建一个实时的脸识别应用程序以足够的预处理,使培训之间的一些差异设置条件和测试设置的条件只使用基本的算法所需的所有步骤。我们用于人脸检测发现相机图像內紧接着几种形式的预处理,减少影响不同照明条件下相机和脸的发展方向和面部表情的脸上一脸的位置。我们然后训练特征脸或 Fisherfaces 的機器学习系统的预处理过的面孔我们收集和最后我们进行人脸识别,看看谁的人是与提供信心的度量万一它是一个未知的人脸验证。

洏不是提供一个以脱机方式处理图像文件的命令行工具我们结合成自包含的实时 GUI 程序,以允许立即使用人脸识别系统的所有前面的步骤你应该能够修改系统的行为为自己的目的,如允许您的计算机自动登录或如果你有兴趣提高识别可靠性,然后你可以读会议论文关于囚脸识别潜在地提高程序的每一步,直到它是足够可靠为您的特定需求的最新进展。例如你可以改善脸预处理阶段,或使用更先进嘚机器学习算法或甚至更好的脸验证算法基于方法在 http://www.face-rec.org/和 

}

我要回帖

更多关于 循环右移 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信