如何使用Python检测人脸特征?实现指南

2021年11月28日04:51:20 发表评论 992 次浏览

今天我们将学习如何使用图像来检测人脸并提取面部特征,例如眼睛、鼻子、嘴巴等。我们可以将这些信息作为预处理步骤进行许多令人难以置信的事情,例如捕捉人脸用于在照片中标记人物(手动或通过机器学习),创建效果以“增强”我们的图像(类似于 Snapchat 等应用程序中的那些),对面部进行情感分析等等。

如何使用Python检测人脸特征?过去,我们已经介绍了如何使用 OpenCV 检测图像中的形状,但今天我们将通过引入 DLib 并从图像中抽象出人脸特征,将其提升到一个新的水平。

帮助你入门计算机视觉的基本 OpenCV 函数

Dlib 是一个先进的机器学习库,旨在解决复杂的现实世界问题。这个库是使用 C++ 编程语言创建的,它适用于 C/C++、Python 和 Java。

Python如何检测人脸特征?值得注意的是,本教程可能需要对OpenCV库有一定的了解,比如如何处理图像,打开相机,图像处理,一些小技巧,以及具体的Python检测人脸特征示例


它是如何工作的?

我们的面部有几个可以识别的特征,比如我们的眼睛、嘴巴、鼻子等。当我们使用 DLib 算法来检测这些特征时,我们实际上得到了围绕每个特征的点的地图。

这张由 67 个点(称为地标点)组成的地图可以识别以下特征:

点地图
点地图
  • 下颌点 = 0–16
  • 右眉点 = 17–21
  • 左眉点 = 22–26
  • 鼻子点数 = 27–35
  • 右眼点 = 36–41
  • 左眼点 = 42–47
  • 口点 = 48–60
  • 嘴唇点数 = 61–67

现在我们对我们计划如何提取特征有了一些了解,让我们开始编码。


安装要求

Python如何检测人脸特征?像往常一样,本文将展示带有代码的示例,我将逐步指导你实现一个完整的人脸特征识别示例。但在我们开始之前,你需要启动一个新的 Python 项目并安装 3 个不同的库:

  • opencv-python
  • 数据库

如果你像我一样使用 pipenv,你可以使用以下命令安装它们:

pipenv install opencv-python, dlib

如果你在 Mac 和某些版本的 Linux 上工作,则在安装 dlib 时可能会遇到一些问题,如果在安装过程中遇到编译错误,请确保检查你正在使用的 CMake 库版本。在 Mac 中,确保你有可用的 CMake 并且你可以运行正确的版本:

brew install cmake

对于其他操作系统,请在线查看特定支持。


第 1 步:加载和呈现图像

如何使用Python检测人脸特征?我们将从小的开始,并在代码的基础上构建,直到我们有一个完整的示例。

通常我喜欢使用绘图来渲染图像,但由于我们为后面的文章准备了一些很酷的东西,我们将做一些不同的事情,我们将创建一个窗口,我们将在其中显示我们的工作结果。

让我们跳入代码

import cv2

# read the image
img = cv2.imread("face.jpg")

# show the image
cv2.imshow(winname="Face", mat=img)

# Wait for a key press to exit
cv2.waitKey(delay=0)

# Close all windows
cv2.destroyAllWindows()

很简单,对吧?我们只是用 imread 加载图像,然后告诉 OpenCV 在 winname 中显示图像,这将打开窗口并给它一个标题。

之后,我们需要暂停执行,因为脚本停止时窗口会被销毁,所以我们使用 cv2.waitKey 来保持窗口直到按下某个键,然后我们销毁窗口并退出脚本。

如果你使用代码并将名为 face.jpg 的图像添加到代码目录,你应该得到如下内容:

如何使用Python检测人脸特征?实现指南
原图

第二步:人脸识别

到目前为止,除了将图像呈现到窗口中之外,我们还没有对图像做任何事情,这很无聊,但是现在我们将开始编写好东西,我们将从识别图像中的人脸位置开始。

为此,我们将使用名为 的 Dlib 函数get_frontal_face_detector(),非常直观。不过有一个警告,这个函数只适用于灰度图像,所以我们必须首先使用 OpenCV 来做到这一点。

get_frontal_face_detector()会返回一个detector就是我们可以用它来获取脸信息的功能。每张脸都是一个包含可以找到图像的点的对象。

Python检测人脸特征示例:但是让我们更好地在代码中看到它:

import cv2
import dlib

# Load the detector
detector = dlib.get_frontal_face_detector()

# read the image
img = cv2.imread("face.jpg")

# Convert image into grayscale
gray = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2GRAY)

# Use detector to find landmarks
faces = detector(gray)

for face in faces:
    x1 = face.left() # left point
    y1 = face.top() # top point
    x2 = face.right() # right point
    y2 = face.bottom() # bottom point
    # Draw a rectangle
    cv2.rectangle(img=img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0), thickness=4)

# show the image
cv2.imshow(winname="Face", mat=img)

# Wait for a key press to exit
cv2.waitKey(delay=0)

# Close all windows
cv2.destroyAllWindows()

如何使用Python检测人脸特征?上面的代码将从图像中检索所有的人脸,并在每个人脸上渲染一个矩形,产生如下所示的图像:

如何使用Python检测人脸特征?实现指南

到目前为止,我们在寻找人脸方面做得很好,但我们仍然需要做一些工作来提取所有特征(地标)。接下来让我们继续努力。


第 3 步:识别面部特征

你喜欢魔法吗?到目前为止,DLib 的工作方式非常神奇,只需几行代码我们就可以实现很多功能,现在我们遇到了一个全新的问题,它会继续如此简单吗?

简短的回答是肯定的!事实证明,DLib 提供了一个名为的函数shape_predictor(),它可以为我们做所有的魔法,但需要注意的是,它需要一个预先训练的模型才能工作。

有几种模型可以使用shape_predictor,我正在使用的模型可以在此处下载 ,但你可以随意尝试其他模型。

Python如何检测人脸特征?让我们看看新代码现在的样子

import cv2
import dlib

# Load the detector
detector = dlib.get_frontal_face_detector()

# Load the predictor
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# read the image
img = cv2.imread("face.jpg")

# Convert image into grayscale
gray = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2GRAY)

# Use detector to find landmarks
faces = detector(gray)

for face in faces:
    x1 = face.left() # left point
    y1 = face.top() # top point
    x2 = face.right() # right point
    y2 = face.bottom() # bottom point

    # Look for the landmarks
    landmarks = predictor(image=gray, box=face)
    x = landmarks.part(27).x
    y = landmarks.part(27).y

    # Draw a circle
    cv2.circle(img=img, center=(x, y), radius=5, color=(0, 255, 0), thickness=-1)

# show the image
cv2.imshow(winname="Face", mat=img)

# Wait for a key press to exit
cv2.waitKey(delay=0)

# Close all windows
cv2.destroyAllWindows()

像以前一样,我们总是建立在相同的代码上,现在使用我们的预测函数为每个人脸找到地标。现在我还在做一些奇怪的事情,比如那里的数字 27 在做什么?

landmarks = predictor(image=gray, box=face)
x = landmarks.part(27).x
y = landmarks.part(27).y

Python检测人脸特征示例 - 根据我们之前看到的图表,我们的预测器函数将返回一个包含符合人脸的所有 68 个点的对象,如果你注意它,点 27 正好在眼睛之间,所以如果一切正确,你应该在脸上的眼睛之间看到一个绿点,如下所示:

如何使用Python检测人脸特征?实现指南

我们已经非常接近了,现在让我们渲染所有点而不是一个点:

import cv2
import numpy as np
import dlib

# Load the detector
detector = dlib.get_frontal_face_detector()

# Load the predictor
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# read the image
img = cv2.imread("face.jpg")

# Convert image into grayscale
gray = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2GRAY)

# Use detector to find landmarks
faces = detector(gray)
for face in faces:
    x1 = face.left() # left point
    y1 = face.top() # top point
    x2 = face.right() # right point
    y2 = face.bottom() # bottom point

    # Create landmark object
    landmarks = predictor(image=gray, box=face)

    # Loop through all the points
    for n in range(0, 68):
        x = landmarks.part(n).x
        y = landmarks.part(n).y

        # Draw a circle
        cv2.circle(img=img, center=(x, y), radius=3, color=(0, 255, 0), thickness=-1)

# show the image
cv2.imshow(winname="Face", mat=img)

# Delay between every fram
cv2.waitKey(delay=0)

# Close all windows
cv2.destroyAllWindows()

多田!魔法:

如何使用Python检测人脸特征?实现指南

但是如果你对所有的点都不感兴趣怎么办?嗯……你实际上可以调整你的range间隔以获得上面词汇表中指定的任何特征,就像我在这里做的那样:

如何使用Python检测人脸特征?实现指南

太棒了,但我们能做些更酷的事情吗?


第四步:实时检测

是的,你没有看错!是的,这可能就是你的想法!下一步是连接我们的网络摄像头并从你的视频流中进行实时地标识别。

如何使用Python检测人脸特征?你可以通过使用相机迭代视频帧或使用视频文件,对你的面部进行实时面部标志检测。如果你想使用自己的相机,请参考下面的代码,但对于视频文件,请确保将数字 0 更改为视频路径。

Python检测人脸特征示例 - 如果要结束窗口,请按键盘上的 ESC 键:

import cv2
import dlib

# Load the detector
detector = dlib.get_frontal_face_detector()

# Load the predictor
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# read the image
cap = cv2.VideoCapture(0)

while True:
    _, frame = cap.read()
    # Convert image into grayscale
    gray = cv2.cvtColor(src=frame, code=cv2.COLOR_BGR2GRAY)

    # Use detector to find landmarks
    faces = detector(gray)

    for face in faces:
        x1 = face.left()  # left point
        y1 = face.top()  # top point
        x2 = face.right()  # right point
        y2 = face.bottom()  # bottom point

        # Create landmark object
        landmarks = predictor(image=gray, box=face)

        # Loop through all the points
        for n in range(0, 68):
            x = landmarks.part(n).x
            y = landmarks.part(n).y

            # Draw a circle
            cv2.circle(img=frame, center=(x, y), radius=3, color=(0, 255, 0), thickness=-1)

    # show the image
    cv2.imshow(winname="Face", mat=frame)

    # Exit when escape is pressed
    if cv2.waitKey(delay=1) == 27:
        break

# When everything done, release the video capture and video write objects
cap.release()

# Close all windows
cv2.destroyAllWindows()

Python如何检测人脸特征?最终结果在这里:

如何使用Python检测人脸特征?实现指南
从原始视频创建的 GIF,我必须剪切帧才能使 GIF 大小合适。

从原始视频创建的 GIF,我必须剪切帧才能使 GIF 大小合适。即使在光线不足的情况下,结果也非常准确,尽管上图中存在一些错误,但更好的照明效果很好。


结论

OpenCV 和 DLib 是功能强大的库,可简化机器学习和计算机视觉的工作。今天我们只接触非常基础的东西,还有很多东西要从他们身上学到。

非常感谢你的阅读!

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: