OpenCV 人脸识别

Ammar Ali 2024年2月15日
  1. 在 OpenCV 中使用 face_recognition 库识别图像中的人脸
  2. 在 OpenCV 中使用 putText() 函数将文本放的图像顶部
OpenCV 人脸识别

本教程将讨论使用 OpenCV 中的 face_recognition 库识别图像中存在的人脸。

在 OpenCV 中使用 face_recognition 库识别图像中的人脸

人脸识别用于识别图像或视频中存在的人脸。例如,Facebook 使用面部识别来标记帖子中的人。

如果我们在图片中标记我们的朋友,Facebook 算法将识别该人的姓名,并在我们下次上传该人的照片时自动标记他。我们还可以使用 face_recognition 库构建类似的算法。

人脸识别库分多个步骤工作以识别人脸。第一步,我们需要传递已知人的图片来训练模型,库将使用 HOG 或定向梯度直方图来查找给定图像中存在的人脸。

在人脸识别中,我们只需要一张人脸的图片,不需要任何其他数据,因为数据量大,会使算法变得更慢、更复杂。

HOG 算法将每个像素与其相邻像素进行比较,以找到强度方向,并在强度级别增加的方向上用梯度标记它。

该算法已经有一张平均人脸的梯度图像。该算法将梯度图像与人脸的已知梯度进行比较,以确定图像的哪个部分包含人脸。

例如,让我们使用人脸识别库的 face_locations() 函数查找图像中存在的人脸。请参阅下面的代码。

import cv2
import dlib
import face_recognition

img = cv2.imread("tom1.jpg")
known_img = face_recognition.load_image_file("tom1.jpg")

loc = face_recognition.face_locations(known_img)
cv2.rectangle(img, (loc[0][0], loc[0][3]), (loc[0][1], loc[0][2]), (255, 0, 0), 3)
print(loc)

cv2.imshow("locations", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:

图像中的人脸检测

正如我们在上面的输出中看到的,在上面的图像中使用 HOG 算法检测到人脸。我们使用两个函数导入了相同的图像,因为 imread() 函数读取 BGR 色标中的图像,而 load_image_file() 函数读取 RGB 颜色空间中的图像。

人脸识别库使用 RGB 图像,而 OpenCV 使用 BGR 图像,我们在上面的代码中都需要。我们使用 OpenCV 的 rectangle() 函数在检测到的面部周围绘制一个矩形。

face_locations() 函数返回矩形的点或角位置,我们可以在 rectangle() 函数中使用它们来绘制矩形。face_locations() 函数还有两个可选参数,number_of_times_to_upsamplebatch_size

计算机将图像存储为数字数组,因此如果人脸图像被旋转或图像中的光照发生变化,即使是同一张脸,计算机也会将其视为另一张图像。该库在第二步中使用人脸界标估计解决了这个问题。

在人脸界标估计中,我们使用机器学习算法来获得 68 个对人脸识别很重要的面部界标,例如眼睛和鼻子周围的界标。

使用这些地标,我们可以旋转和共享我们的图像,以创建一个完美居中的图像,眼睛和鼻子位于图像的中心。

我们不必担心面部的方向或角度。第三步,我们必须训练一个模型来进行预测。

我们不能简单地将未知图像与所有已知图像进行比较来识别人,因为这需要时间。

我们可以使用每张图像的一些特征,例如耳朵、眼睛和鼻子大小之间的距离,并将它们与未知的人脸图像进行比较,而不是使用整个人脸图像。

但是,我们不知道哪些特征最适合识别人脸。因此,我们将使用深度卷积神经网络从每个已知图像中找到 128 个测量值或面部特征。

为了训练模型,我们必须提供两张已知人的图像和一张未知人的图像,神经网络将通过比较给定的图像来找到 128 个测量值。训练一个模型也需要很多时间,因此人脸库使用 OpenFace 的预训练模型来获取所有已知人脸的 128 个测量值。

在最后一步,我们必须使用分类器来检查未知人脸是否与任何已知人脸相似。人脸识别库使用 SVM 或空间向量机分类器进行预测。

例如,让我们使用 Tom Cruise 的一张图像进行训练,另一张图像用于测试。请参阅下面的代码。

import cv2
import dlib
import face_recognition

known_img = face_recognition.load_image_file("tom1.jpg")
unknown_img = face_recognition.load_image_file("tom2.jpg")

known_en = face_recognition.face_encodings(known_img)[0]
unknown_en = face_recognition.face_encodings(unknown_img)[0]

result = face_recognition.compare_faces([known_en], unknown_en)
print(result)

cv2.imshow("Known Image", known_img)
cv2.imshow("Un_Known Image", unknown_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:

[True]

输出结果为,这意味着未知图像是汤姆克鲁斯。我们在上面的代码中使用了人脸识别库的 face_encodings() 函数来查找 128 个测量值。

face_encodings() 函数的第一个参数是输入图像。第二个参数 known_face_locations 是可选的,它用于设置每个人脸的边界框,默认情况下,它的值设置为 none

第三个参数 num_jitters 也是可选的,它用于设置用于查找编码的重采样值,默认设置为 1。第四个参数 model 也是可选的,用于设置用于查找编码的模型类型,默认设置为 small

小模型速度快但精度较低,大模型速度慢但精度更高。我们使用 compare_faces() 将未知面孔与已知面孔进行比较。

compare_faces() 函数的第一个参数包含已知人脸的编码,第二个参数包含未知人脸的编码。第三个参数 tolerance 是可选的,用于设置面之间的距离,默认情况下,其值设置为 0.6

在 OpenCV 中使用 putText() 函数将文本放的图像顶部

我们还可以使用 OpenCV 的 putText() 函数在图像上放置与已知人脸相似的文本。例如,让我们使用 Tom Cruise 图像来训练模型,然后使用 Dwayne Johnson 的图像来测试模型。

请参阅下面的代码。

import cv2
import dlib
import face_recognition

img = cv2.imread("rock1.jpg")
known_img = face_recognition.load_image_file("tom2.jpg")
unknown_img = face_recognition.load_image_file("rock1.jpg")

known_en = face_recognition.face_encodings(known_img)[0]
unknown_en = face_recognition.face_encodings(unknown_img)[0]

result = face_recognition.compare_faces([known_en], unknown_en)

loc = face_recognition.face_locations(unknown_img)
cv2.rectangle(img, (loc[0][0], loc[0][3]), (loc[0][1], loc[0][2]), (255, 0, 0), 3)

if result[0]:
    text = "Tom Cruise"
else:
    text = "Unknown"
cv2.putText(
    img,
    text,
    (loc[0][0], loc[0][3] - 20),
    cv2.FONT_HERSHEY_SIMPLEX,
    1.2,
    (0, 0, 255),
    2,
    cv2.LINE_AA,
)

cv2.imshow("locations", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:

人脸检测和文本

上面这张脸不像汤姆克鲁斯的脸。我们还可以使用不同人的多张图像来训练模型,我们还可以在视频中找到人脸。

对于视频,我们必须单独处理每一帧。查看此链接了解有关人脸识别库的更多详细信息。

作者: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

相关文章 - OpenCV Image