Python + OpenCV人脸识别

问题描述 投票:1回答:1

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

我的test2.jpg是一些要检查的图像。我们需要在test2.jpg的test 1.jpg中检查面部,如果测试1.jpg中的某些面部存在于test2.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
python opencv face-detection face-recognition
1个回答
0
投票

您的代码的主要问题是,它希望面部补丁在两个不同的图像中是相同的。这几乎肯定不是这种情况 - 即使一个只是另一个的裁剪图像,如果级联分类器在一个图像中找到比另一个图像更靠左边的1个像素,则结果不相同。

级联分类器的结果是一组应该表示面的边界框(您有时会得到错误的检测)。然后,您需要在这些边界框中提取子图像,并使用某种比较技术来确定两个面部图像是否相同。我将在下面讨论这些。

你的问题实际上有两个阶段,因为有不同的技术可以解决这两个问题,所以区分它们很重要。

第1阶段:人脸检测

这是在图像中实际找到面部的问题。你的代码应该很好地处理这个问题 - 来自OpenCV的级联分类器是最常用的方法之一(另一种方法是aligned face detector in DLib)。

第二阶段:面部识别

这是更难的部分。人脸识别技术可以有很大差异,其中很多都是依赖于情境的。其中最准确的是使用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种人脸检测方法。 FisherfacesEigenfaces都依赖于查看相同面的一些示例并在较低维空间中对它们进行建模,在这些空间中可以比较它们的基础属性,而不是原始像素数据。

我不确定其中任何一个都能很好地用于你的用例,因为你只会有一个每个面的例子。

使用局部二进制模式(LBP)直方图可能会为您提供更好的起点。 LBP是一种描述图像纹理细节的方式 - 我在上面链接的教程中有更多信息。我将再次提供一些基本步骤来帮助您入门:

  • 对于每个检测到的面部,使用该面部的边界框提取小的子图像(感兴趣区域)。
  • 将图像分解为更小的“补丁” - 基本上将图像分解为均匀的网格(例如,100x100像素的ROI可能被分解为10x10像素的10x10补丁)。
  • 对于每个补丁,计算LBP直方图(基本上是一个数字列表)
  • 将这些直方图连接(连接)在一起以获得面部的表示。此连锁直方图成为表示特定面部的特征向量。
  • 然后,您可以对图像2执行相同的操作。
  • 对于图像2中的所有特征向量,将它们与图像1中的特征向量进行比较,并尝试选择距离较小的特征向量。

笔记:

使用单个图像的任何识别技术都可能容易出错。我没有测试过上面的算法,但过去使用OpenFace,Fisherfaces和LBPH进行人脸识别,遵循这些教程,并发现它们可以通过几个面部示例进行识别。

© www.soinside.com 2019 - 2024. All rights reserved.