Python + OpenCV 人脸识别
Posted
技术标签:
【中文标题】Python + OpenCV 人脸识别【英文标题】:Python + OpenCV face recognition 【发布时间】:2019-08-10 01:18:13 【问题描述】:我有一个 test1.jpg - 它是原始图像,包含我们需要找到的面孔。
我的 test2.jpg 是一些要检查的图像。我们需要在 test2.jpg 中检查来自 test1.jpg 的人脸,如果 test1.jpg 中的某些人脸存在于 test2 .jpg 输出 true。
我之前没有在 OpenCV 和它对我来说是新技术方面的经验。
我非常简单的代码:
# faces which we need find
known_image = cv2.imread('test1.jpg')
# some random image
unknown_image = cv2.imread('test2.jpg')
gray_known = cv2.cvtColor(known_image, cv2.COLOR_BGR2GRAY)
gray_unknown = cv2.cvtColor(unknown_image, cv2.COLOR_BGR2GRAY)
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
known_faces = faceCascade.detectMultiScale(
gray_known,
scaleFactor=1.27,
minNeighbors=5,
minSize=(10, 10),
flags = cv2.CASCADE_SCALE_IMAGE
)
print("Found known 0 faces!".format(len(known_faces)))
unknown_faces = faceCascade.detectMultiScale(
gray_unknown,
scaleFactor=1.27,
minNeighbors=5,
minSize=(10, 10),
flags = cv2.CASCADE_SCALE_IMAGE
)
print("Found unknown 0 faces!".format(len(unknown_faces)))
# BELLOW NOT CORRECT CODE. I DONT KNOW HOW I CAN DO LIKE THIS:
for face in known_faces:
if face in unknown_faces:
print(TRUE)
break
【问题讨论】:
【参考方案1】:就目前而言,您的代码的主要问题是它期望面部补丁在两个不同的图像中是相同的。几乎可以肯定情况并非如此——即使一张只是另一张的裁剪图像,如果级联分类器在一张图像中发现边界框比另一张图像更左 1 个像素,则结果并不相同。
级联分类器的结果是一组应该代表人脸的边界框(您有时会得到错误检测)。然后,您需要在这些边界框中提取子图像,并使用某种比较技术来确定两个人脸图像是否相同。我将在下面讨论这些。
您的问题实际上有两个阶段,区分它们很重要,因为有不同的技术来解决这两个问题。
第 1 阶段:人脸检测
这是在图像中实际找到人脸的问题。您的代码应该可以很好地处理这个问题 - OpenCV 的级联分类器是最常见的方法之一(另一种方法是 aligned face detector in DLib)。
第 2 阶段:人脸识别
这是比较困难的部分。人脸识别技术可以有很大的不同,而且很多都取决于情况。其中最准确的使用deep learning module,因此如果您的硬件能够胜任这项任务,我建议您这样做。看起来代码实际上是一个implementation of OpenFace - 我以前用过它,它可以在很少的训练图像上获得准确的识别。我建议阅读链接的帖子,以及 DNN 示例,因为代码可能太深,无法进入此处。
主要步骤如下:
如上图 1 中的人脸检测和定位 使用预训练的 DNN 将人脸转换为可线性分离的特征向量(称为嵌入)。 如上图 2 中的人脸检测和定位 再次,使用 DNN 将人脸转换为特征向量。 比较特征向量 - 而不是原始图像,并选择欧几里得距离足够低的那些。DNN 嵌入步骤在这里是缓慢的部分,但如果您有可用的 GPU,应该仍然非常有效。
如果您不是直接进行图像-图像比较,而是寻找一组已知的面孔,您可以训练一个现成的线性分类器,例如对您要寻找的实际人的 SVM,然后在图像中找到的特征向量上使用它,看看它们是否属于任何类别。
第 2(a) 阶段:没有深度学习的人脸识别
OpenCV 还带有一个人脸识别模块,它利用了更经典的技术,这些技术往往更快、更便携,但以准确性为代价。
有一个really good tutorial on it in the OpenCV documentation。同样,代码太长,无法直接放入帖子中,但该链接描述了 3 种面部检测方法。 Fisherfaces 和 Eigenfaces 都依赖于查看同一张脸的多个示例,并在低维空间中对它们进行建模,以便比较它们的基本属性,而不是原始像素数据。
我不确定其中任何一个是否适用于您的用例,因为每张面孔只有一个示例。
使用局部二进制模式 (LBP) 直方图可能会为您提供更好的起点。 LBP 是一种描述图像纹理细节的方法——我在上面链接的教程中有更多信息。我将再次在这里提供一些基本步骤来帮助您入门:
对于每个检测到的人脸,使用该人脸的边界框提取小的子图像(感兴趣区域)。 将图像分解为更小的“块” - 实质上是将图像分解为一个统一的网格(例如,一个 100x100 像素的 ROI 可能被分解为 10x10 个 10x10 像素的块)。 对于每个补丁,计算 LBP 直方图(本质上是数字列表) 将这些直方图连接(连接)在一起,以获得人脸的表示。此串联直方图将成为您的特征向量来表示该特定人脸。 然后您可以对图像 2 执行相同操作。 对于图 2 中的所有特征向量,将它们与图 1 中的特征向量进行比较,并尝试挑选出距离较小的特征向量。注意事项:
任何使用单个图像的识别技术都可能容易出错。我没有测试过上面的算法,但是过去我使用 OpenFace、Fisherfaces 和 LBPH 进行人脸识别,按照这些教程,发现它们可以通过一些人脸示例进行识别。
【讨论】:
以上是关于Python + OpenCV 人脸识别的主要内容,如果未能解决你的问题,请参考以下文章