用Python检测人脸特征

做者|Juan Cruz Martinez
编译|Flin
来源|towardsdatasciencejava

今天,咱们将学习如何检测图像中的人脸并提取面部特征,如眼睛、鼻子、嘴巴等。咱们能够将这些信息做为一个预处理步骤来完成,例如捕捉照片中人物的人脸(手动或经过机器学习),建立效果来“加强”咱们的图像(相似于Snapchat等应用程序中的效果),对人脸进行情感分析等等。python

过去,咱们已经讨论过如何使用OpenCV来检测图像中的形状,可是今天咱们将经过引入DLib和从图像中提取面部特征来将其提高到一个新的水平。算法

  • 相关阅读:

https://towardsdatascience.co...shell

Dlib是一个高级的机器学习库,它是为解决复杂的现实世界问题而建立的。这个库是用C++编程语言建立的,它与C/C++、Python和java一块儿工做。编程

值得注意的是,本教程可能须要对OpenCV库有必定的了解,例如如何处理图像、打开相机、图像处理和一些小技巧。windows

它是如何工做的?

咱们的脸有几个能够识别的特征,好比眼睛、嘴巴、鼻子等等。当咱们使用DLib算法检测这些特征时,咱们实际上获得了每一个特征的点的映射。
该映射由67个点(称为地标点)组成,可识别如下特征:网络

  • 颚点= 0–16
  • 右眉点= 17–21
  • 左眉点= 22–26
  • 鼻点= 27–35
  • 右眼点= 36–41
  • 左眼点= 42–47
  • 口角= 48–60
  • 嘴唇分数= 61–67

如今让咱们来了解如何提取特征。机器学习

安装要求

与往常同样,本文将用代码演示示例,并将逐步指导你实现一个完整的人脸特征识别示例。可是在开始以前,你须要启动一个新的Python项目并安装3个不一样的库:编程语言

  • opencv python
  • dlib

若是像我同样使用pipenv,可使用如下命令安装全部这些文件:ide

pipenv install opencv-python, dlib

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

brew install cmake

对于其余操做系统,请在线检查以得到特定支持。

步骤1:载入并显示图片

咱们将从小处着手并以代码为基础,直到有一个能够正常工做的示例为止。

一般,我喜欢使用绘图来渲染图像,可是因为咱们在稍后的文章中准备了一些很酷的东西,所以咱们将作一些不一样的事情,而且将建立一个窗口来展现咱们的工做结果。

让咱们一块儿看看代码吧!

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的图像,你应该获得以下内容:

原始图像:

步骤2:人脸识别

到目前为止,咱们尚未对图像作任何处理,只是把它呈如今一个窗口中,很是无聊,可是如今咱们将开始编码好的内容,咱们将从识别图像中哪里有一张脸开始。

为此,咱们将使用名为get_frontial_face_detector()的Dlib函数,很是直观。可是有一个警告,这个函数只适用于灰度图像,因此咱们必须首先使用OpenCV。

get_frontial_face_detector()将返回一个检测器,该检测器是一个咱们能够用来检索人脸信息的函数。每一个面都是一个对象,其中包含能够找到图像的点。

但咱们最好在代码上看看:

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()

上面的代码将从图像中检索全部面部,并在每一个面部上渲染一个矩形,从而产生以下图像:

到目前为止,咱们在发现人脸方面作得很好,可是咱们仍然须要一些工做来提取全部特征(地标)。接下来让咱们开始吧。

步骤3:识别人脸特征

你喜欢魔术吗?到目前为止,DLib的工做方式至关神奇,只需几行代码咱们就能够实现不少,而如今咱们遇到了一个全新的问题,它还会继续这么简单吗?

回答是确定的!原来DLib提供了一个名为shape_predictor()的函数,它将为咱们提供全部的魔法,可是须要一个预先训练的模型才能工做。

有几种模型能够与shape_predictor一块儿工做,我正在使用的模型能够在这里下载,也能够尝试其余模型。

让咱们看看新代码如今是什么样子

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

咱们的预测函数将返回一个包含全部68个点的对象,根据咱们以前看到的图片,若是你注意到的话,会发现点27正好在眼睛之间,因此若是全部的计算正确,你应该看到一个绿点在眼睛之间,以下图所示:

咱们已经很接近了,如今让咱们渲染全部的点,而不是只渲染一个:

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()

可是若是你对全部的点都不感兴趣呢?实际上,你能够调整你的范围间隔来得到上面术语表中指定的任何特征,就像我在这里作的那样:

太棒了,但咱们能作点更酷的事吗?

步骤4:实时检测

是的,你没看错!这可能就是你想要的效果!下一步是链接咱们的网络摄像头,从你的视频流中进行实时地标识别。

你能够经过使用相机遍历视频帧或使用视频文件来对面部进行实时面部地标检测。

若是要使用本身的摄像机,请参考如下代码,若是使用的是视频文件,请确保将数字0更改成视频路径。

若是要结束窗口,请按键盘上的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()

最后的结果是:

在弱光条件下,尽管上面的图像中有一些错误,但其结果也至关准确,若是照明效果好的话结果会更加准确。

结论

OpenCV和DLib是两个功能很是强大的库,它们简化了ML和计算机视觉的工做,今天咱们只是触及了最基本的东西,还有不少东西须要从中学习。

很是感谢你的阅读!

原文连接:https://towardsdatascience.co...

欢迎关注磐创AI博客站:
http://panchuang.net/

sklearn机器学习中文官方文档:
http://sklearn123.com/

欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/

相关文章
相关标签/搜索