OpenCV教程-OpenCV人脸识别与人脸检测
人脸识别是一种从数字图像或视频帧中识别或验证人脸的技术。人类可以在不费力的情况下迅速识别人脸。这对我们来说是一项轻松的任务,但对于计算机来说却是一项困难的任务。存在各种复杂性,如低分辨率、遮挡、照明变化等。这些因素极大地影响计算机更有效地识别人脸的准确性。首先,有必要了解人脸检测和人脸识别之间的区别。
人脸检测: 通常被认为是在图像中找到面部(位置和大小)并可能提取它们以供人脸检测算法使用。
人脸识别: 人脸识别算法用于查找图像中唯一描述的特征。面部图像已经被提取、裁剪、调整大小,并通常转换为灰度。
有各种各样的人脸检测和人脸识别算法。在这里,我们将学习使用HAAR级联算法进行人脸检测。
HAAR级联算法的基本概念
HAAR级联是一种机器学习方法,其中从许多正面和负面图像中训练出一个级联函数。正面图像是包含面部的图像,负面图像是没有面部的图像。在人脸检测中,图像特征被视为从图片中提取出的可以区分一张图片与另一张图片的数字信息。
我们将算法的每个特征应用于所有训练图像。每个图像在开始时都被赋予相等的权重。它找到最佳阈值,该阈值将面部分类为正面和负面。可能会出现错误和误分类。我们选择具有最小错误率的特征,这意味着这些特征最好地分类了面部和非面部图像。
使用每个内核的所有可能的大小和位置来计算大量特征。
在OpenCV中使用HAAR-Cascade检测
OpenCV提供了训练器以及检测器。我们可以使用OpenCV为任何对象(如汽车、飞机和建筑物)训练分类器。级联图像分类器的两个主要状态是训练和检测。
OpenCV提供了两个应用程序来训练级联分类器opencv_haartraining和opencv_traincascade。这两个应用程序将分类器存储在不同的文件格式中。
为了训练,我们需要一组样本。有两种类型的样本:
- 负样本: 与非对象图像相关。
- 正样本: 与检测对象相关的图像。
必须手动准备一组负样本,而正样本的收集则使用opencv_createsamples实用程序。
负样本
负样本取自任意图像。负样本添加到文本文件中。文件的每一行包含一个负样本的图像文件名(相对于描述文件目录)。此文件必须手动创建。定义的图像可能具有不同的大小。
正样本
正样本是使用opencv_createsamples实用程序创建的。可以从带有对象的单个图像或从之前的集合中创建这些样本。请记住,在将其提供给上述实用程序之前,我们需要一个正样本的大数据集,因为它只应用透视变换。
在这里我们将讨论检测。OpenCV已经包含了用于人脸、眼睛、微笑等的各种预训练分类器的XML文件。这些XML文件存储在opencv/data/haarcascades/文件夹中。让我们了解以下步骤:
步骤-1
首先,我们需要加载必要的XML分类器,并以灰度模式加载输入图像(或视频)。
步骤-2
在将图像转换为灰度之后,我们可以对图像进行操作,如果需要,可以对图像进行调整大小、裁剪、模糊和锐化。接下来是图像分割;识别单个图像中的多个对象,使分类器能够快速检测图像和人脸中的对象。
步骤-3
使用Haar-Like特征算法在帧或图像中找到人脸的位置。所有人脸都具有一些通用的面部特性,例如眼睛区域的像素较暗,而鼻子区域的亮度比眼睛区域更高。
步骤-4
在这一步中,我们从图像中提取特征,借助边缘检测、线检测和中心检测。然后提供x、y、w、h的坐标,这在图像中形成一个矩形框,显示了检测到的人脸的位置。在检测到人脸的所需区域中创建一个矩形框。
使用OpenCV进行人脸识别
人脸识别对人类来说是一项简单的任务。成功的人脸识别往往能够有效识别内部特征(眼睛、鼻子、嘴巴)或外部特征(头部、脸部、发际线)。在这里的问题是,人脑是如何对其进行编码的?
David Hubel 和 Torsten Wiesel 表明我们的大脑有专门对场景的独特局部特征作出响应的神经元,比如线条、边缘角度或运动。我们的大脑将来自不同信息源的信息结合到有用的模式中;我们不会看到视觉上是散乱的。如果我们用简单的话来定义人脸识别,“自动人脸识别就是从图像中提取这些有意义的特征并将其放入有用的表示中,然后对其进行一些分类”。
人脸识别的基本思想是基于人脸的几何特征。这是一种可行且最直观的人脸识别方法。第一个自动人脸识别系统是根据眼睛、耳朵、鼻子的位置来描述的。这些定位点称为特征向量(点之间的距离)。
人脸识别通过计算探针和参考图像的特征向量之间的欧几里德距离来实现。由于其性质,该方法对于光照变化来说是有效的,但它有一个显著的缺点。标记的正确注册非常困难。
人脸识别系统基本上可以以两种模式运行:
- 人脸图像的身份验证或验证-
它将输入的人脸图像与用户相关的人脸图像进行比较,需要验证。这是一个1x1的比较。
- 识别或面部识别
它基本上是将数据集中的输入面部图像与输入的面部图像进行比较,以找到与该输入面相匹配的用户。这是一个1xN的比较。
有各种类型的人脸识别算法,例如:
- 特征脸(Eigenfaces)(1991)
- 局部二进制模式直方图(LBPH)(1996)
- Fisherfaces(1997)
- 尺度不变特征变换(SIFT)(1999)
- 速度稳健特征(SURF)(2006)
每种算法都遵循不同的方法来提取图像信息并与输入图像进行匹配。在这里,我们将讨论其中一种最古老和流行的算法,即局部二进制模式直方图(LBPH)算法。
LBPH的介绍
局部二进制模式直方图算法是一种简单的方法,它通过对每个像素的邻域进行二进制编码来标记图像的像素。换句话说,LBPH通过将每个像素与其邻域进行比较并将结果转换为二进制数来总结图像中的局部结构。它于1994年首次被定义(LBP),自那时以来被发现是用于纹理分类的强大算法之一。
此算法通常专注于从图像中提取局部特征。基本思想不是将整个图像视为高维向量;它只关注对象的局部特征。
在上图中,以一个像素为中心并对其进行阈值处理的方式使用LBP计算。在进一步的步骤中,将参数radius和neighbors用于滑动窗口的概念。
注意: 上述参数可能稍微令人困惑。在后续步骤中将更加清晰。
1. 选择参数: LBPH接受四个参数:
- 半径(Radius): 表示中心像素周围的半径。通常设置为1。用于构建圆形局部二进制模式。
- 邻居数(Neighbors): 用于构建圆形二进制模式的采样点的数量。
- 网格X(Grid X): 在水平方向上的单元格数。更多的单元格和更细的网格表示结果特征向量的更高维度。
- 网格Y(Grid Y): 在垂直方向上的单元格数。更多的单元格和更细的网格表示结果特征向量的更高维度。
2. 训练算法: 第一步是训练算法。它需要具有要识别的人的面部图像的数据集。每个图像都应附有唯一的ID(可以是数字或人的姓名)。然后,算法使用此信息来识别输入图像并返回结果。具有相同ID的特定人的图像必须具有相同的ID。在下一步中了解LBPH计算。
3. 使用LBP操作: 在此步骤中,使用LBP计算创建一个中间图像,通过突出原始图像的特定方式来描述它。使用半径和邻居参数在滑动窗口概念中执行LBP计算。
为了更具体地了解,请将其分解为几个小步骤:
- 假设输入的面部图像是灰度的。
- 我们可以将这个图像的一部分作为3x3像素的窗口。
- 我们可以使用包含每个像素强度(0-255)的3x3矩阵。
- 然后,我们需要以中心值作为阈值,用于定义8个邻域的新值。
- 对于中心值(阈值)的每个邻域,我们设置一个新的二进制值。如果大于或等于阈值,则将值设置为1,如果小于阈值,则将值设置为0。
- 现在矩阵将仅包含二进制值(跳过中心值)。我们需要将来自矩阵的每个位置的每个二进制值注意到(按行逐个跳过)并将其转换为新的二进制值(10001101)。还有其他连接二进制值的方法(顺时针方向),但最终结果是相同的。
- 我们将此二进制值转换为原始图像的像素矩阵的中心值。在完成LBP过程后,我们得到了新的图像,它更好地表示原始图像的特征。
4. 从图像中提取直方图: 在上一步生成了图像之后,我们可以使用网格X和网格Y参数将图像分成多个网格,例如以下图像:
- 我们有一个灰度图像;每个直方图(从每个网格中)将只包含256个位置,表示每个像素强度的出现。
- 需要通过连接每个直方图来创建一个新的更大的直方图。
5. 执行人脸识别: 现在,算法已经训练好了。从提取的直方图中使用Grid X和Grid Y参数来表示训练数据集中每个图像。对于新图像,我们再次执行步骤,并创建一个新的直方图。为了找到与给定图像匹配的图像,我们只需匹配两个直方图并返回与最接近直方图的图像。
- 有各种比较直方图的方法(计算两个直方图之间的距离),例如:欧几里得距离、卡方、绝对值等。我们可以使用基于以下公式的欧几里德距离:
- 该算法将返回与最接近直方图的图像相对应的ID。该算法还应该返回计算得出的距离,可以称之为置信度测量。如果置信度低于阈值,那么意味着算法已成功识别了面部。
我们已经讨论了人脸检测和人脸识别。Haar级联算法用于人脸检测。有各种人脸识别算法,但LBPH是其中一种易于理解和流行的算法。它通常专注于图像的局部特征。