我只有一个 test1.jpg -它是原始图像,其中包含我们需要查找的面孔。

我的 test2.jpg 是要检查的图像。我们将需要在 test2.jpg 中检查 test1.jpg 的面孔,如果 test2.jpg 输出输出 true 中是否存在 test1.jpg 的面孔。

我还没有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:人脸检测

这是实际上在图像中找到面部的问题。您的代码应该可以很好地处理-OpenCV的级联分类器是执行此操作的最常用方法之一(aligned face detector in DLib替代方法)。

阶段2:人脸识别

这是比较困难的部分。人脸识别技术可能相差很大,并且很多取决于情况。其中最准确的方法是使用deep learning module,因此,如果您的硬件可以完成任务,我建议您这样做。似乎代码实际上是implementation of OpenFace-我以前使用过它,并且有可能在很少的训练图像上获得准确的识别。我建议阅读链接的文章,以及DNN示例,因为代码可能太深而无法在此处介绍。

主要步骤如下:

  • 像上面的
  • 一样检测并定位图像1中的人脸
  • 使用预训练的DNN将人脸转换为线性可分离的特征 vector (称为嵌入)。
  • 像上面的
  • 一样检测并定位图像2中的人脸
  • 再次使用DNN将人脸转换为特征 vector 。
  • 比较特征 vector -而不是原始图像,并选择欧氏距离足够低的特征 vector 。

  • DNN嵌入步骤是此处的较慢部分,但是如果您有GPU可用,它仍然应该非常高效。

    如果您不是在进行直接的图像-图像比较,而是在寻找一组已知的面孔,而是可以训练一个现成的线性分类器(例如在您要寻找的实际人员上使用SVM),则可以使用此分类器您可以在图像中找到的特征 vector 上查看它们是否属于任何类别。

    阶段2(a):无需深度学习的人脸识别

    OpenCV还带有面部识别模块,该模块使用了更为经典的技术,这些技术往往更快,更便携,但会降低准确性。

    有一个really good tutorial on it in the OpenCV documentation。同样,该代码太长了,无法直接发布到帖子中,但是该链接描述了3种面部检测方法。 FisherfacesEigenfaces都依赖于查看同一张面孔的多个示例,并在较低维度的空间中对其进行建模,可以在其中比较它们的基本属性,而不是原始像素数据。

    我不确定这两种方法中的哪一种都适合您的用例,因为每张脸只有一个示例。

    使用本地二进制模式(LBP)直方图可能会为您提供更好的起点。 LBP是描述图像纹理细节的一种方法-在上面链接的教程中有更多信息。我将在这里再次给出一些基本步骤来帮助您入门:
  • 对于每个检测到的脸部,使用该脸部的边界框提取小子图像(感兴趣区域)。
  • 将图像分解为较小的“补丁”-本质上将图像分解为均匀的网格(例如,将100x100像素的ROI分解为10x10的10x10像素的补丁)。
  • 对于每个补丁,计算LBP直方图(基本上是数字列表)
  • 将这些直方图连接(合并)在一起以获取人脸的表示。此级联直方图成为您代表特定脸部的特征 vector 。
  • 然后,您可以对图像2做同样的操作。
  • 对于图像2中的所有特征 vector ,将它们与图像1中的特征 vector 进行比较,并尝试选择距离较小的特征 vector 。

  • 注意:

    使用单个图像的任何识别技术都容易出错。我还没有测试上述算法,但是在遵循这些教程之后,过去曾使用OpenFace,Fisherfaces和LBPH进行人脸识别,并发现它们可以很好地识别一些人脸示例。

    关于python - Python + OpenCV人脸识别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55242252/

    10-12 21:16