人脸检测实战终极之OpenCV+Python实现人脸对齐

目录
  • 前言
  • 实现面部矫正器
  • 导入必要的包
  • 对齐人脸
  • 展示结果

前言

这篇博文的目的是演示如何使用 OpenCV、Python 和面部标志对齐人脸。

给定一组面部标志(输入坐标),我们的目标是将图像扭曲并转换为输出坐标空间。

在这个输出坐标空间中,整个数据集中的所有面都应该:

  • 在图像中居中。
  • 旋转,使眼睛位于水平线上(即,旋转面部,使眼睛位于相同的 y 坐标上)。
  • 进行缩放,使面的大小大致相同。

为此,我们将首先调用一个实现的 Python 类FaceAligner ,以使用仿射变换对齐人脸。

注意:仿射变换用于旋转、缩放、平移等。我们可以将上述所有三个要求打包到一个 cv2.warpAffine 调用中; 诀窍是创建旋转矩阵 M 。

然后,我们将创建一个示例驱动程序 Python 脚本来接受输入图像、检测人脸并对齐它们。

最后,我们将回顾我们使用 OpenCV 过程进行人脸对齐的结果。

实现面部矫正器

面部对齐算法本身基于 Mastering OpenCV with Practical Computer Vision Projects (Baggio, 2012) 的第 8 章,如果您有 C++ 背景或兴趣,我强烈推荐它。 本书在 GitHub 上提供了开放访问的代码示例。

新建facealigner.py实现FaceAligner类。

# import the necessary packages
from imutils.face_utils.helpers import FACIAL_LANDMARKS_68_IDXS
from imutils.face_utils.helpers import FACIAL_LANDMARKS_5_IDXS
from imutils.face_utils.helpers import shape_to_np
import numpy as np
import cv2
class FaceAligner:
    def __init__(self, predictor, desiredLeftEye=(0.35, 0.35),
        desiredFaceWidth=256, desiredFaceHeight=None):
        # store the facial landmark predictor, desired output left
        # eye position, and desired output face width + height
        self.predictor = predictor
        self.desiredLeftEye = desiredLeftEye
        self.desiredFaceWidth = desiredFaceWidth
        self.desiredFaceHeight = desiredFaceHeight
        # if the desired face height is None, set it to be the
        # desired face width (normal behavior)
        if self.desiredFaceHeight is None:
            self.desiredFaceHeight = self.desiredFaceWidth

导入必要的包

定义的构造函数开始我们的 FaceAligner 类。

我们的构造函数有 4 个参数:

  • predictor :面部标志性预测器模型。
  • requiredLeftEye :一个可选的 (x, y) 元组,显示默认值,指定所需的输出左眼位置。对于此变量,通常会看到 20-40% 范围内的百分比。这些百分比控制对齐后人脸的可见程度。使用的确切百分比将因应用程序而异。使用 20% 时,您基本上会获得“放大”的脸部视图,而使用较大的值时,脸部会显得更“缩小”。
  • requiredFaceWidth :另一个可选参数,以像素为单位定义我们想要的人脸。我们将此值默认为 256 像素。
  • requiredFaceHeight :最后一个可选参数,以像素为单位指定我们所需的人脸高度值。

接下来,让我们决定是想要一张方形的人脸图像还是矩形的图像。检查 requiredFaceHeight 是否为 None ,如果是,我们将其设置为 desiredFaceWidth ,这意味着面部是方形的。方形图像是典型情况。或者,我们可以为 desiredFaceWidth 和 desiredFaceHeight 指定不同的值以获得感兴趣的矩形区域。

现在我们已经构建了我们的 FaceAligner 对象,接下来我们将定义一个对齐人脸的函数。

这个函数有点长,所以我把它分成了 5 个代码块,让它更容易理解:

 def align(self, image, gray, rect):
        # convert the landmark (x, y)-coordinates to a NumPy array
        shape = self.predictor(gray, rect)
        shape = shape_to_np(shape)
        # extract the left and right eye (x, y)-coordinates
        (lStart, lEnd) = FACIAL_LANDMARKS_IDXS["left_eye"]
        (rStart, rEnd) = FACIAL_LANDMARKS_IDXS["right_eye"]
        leftEyePts = shape[lStart:lEnd]
        rightEyePts = shape[rStart:rEnd]

定义了 align 函数,它接受三个参数:

image : RGB 输入图像。

gray :灰度输入图像。

rect :由 dlib 的 HOG 人脸检测器生成的边界框矩形。

应用 dlib 的面部标志预测器并将标志转换为 NumPy 格式的 (x, y) 坐标。

接下来,从 helpers.py 脚本中找到的 FACIAL_LANDMARK_IDXS 字典中读取 left_eye 和 right_eye 区域。 这些 2 元组值存储在左/右眼开始和结束索引中。

提取leftEyePts 和 rightEyePts 。

接下来,计算每只眼睛的中心以及眼睛质心之间的角度。

这个角度是对齐我们的图像的关键组成部分。

眼睛之间的绿线夹角,如下图所示,是我们比较关心的。

接下来是角度计算:

		# compute the center of mass for each eye
        leftEyeCenter = leftEyePts.mean(axis=0).astype("int")
        rightEyeCenter = rightEyePts.mean(axis=0).astype("int")
        # compute the angle between the eye centroids
        dY = rightEyeCenter[1] - leftEyeCenter[1]
        dX = rightEyeCenter[0] - leftEyeCenter[0]
        angle = np.degrees(np.arctan2(dY, dX)) - 180

分别通过平均每只眼睛的所有 (x, y) 点来计算每只眼睛的质心,也称为质心。

给定眼睛中心,我们可以计算 (x, y) 坐标的差异并取反正切以获得眼睛之间的旋转角度。

这个角度将允许我们校正旋转。

为了确定角度,我们首先计算 y 方向的增量 dY 。 这是通过在第 38 行找到 rightEyeCenter 和 leftEyeCenter 之间的差异来完成的。

类似地,我们计算 dX ,即第 39 行 x 方向的增量。

接下来,我们计算面部旋转的角度。 我们使用带有参数 dY 和 dX 的 NumPy 的 arctan2 函数,然后转换为度数,同时减去 180 以获得角度。

在以下代码块中,我们计算所需的右眼坐标(作为左眼位置的函数)并计算新结果图像的比例。

 		# compute the desired right eye x-coordinate based on the
        # desired x-coordinate of the left eye
        desiredRightEyeX = 1.0 - self.desiredLeftEye[0]
        # determine the scale of the new resulting image by taking
        # the ratio of the distance between eyes in the *current*
        # image to the ratio of distance between eyes in the
        # *desired* image
        dist = np.sqrt((dX ** 2) + (dY ** 2))
        desiredDist = (desiredRightEyeX - self.desiredLeftEye[0])
        desiredDist *= self.desiredFaceWidth
        scale = desiredDist / dist

根据所需的左眼 x 坐标计算所需的右眼。从 1.0 中减去 self.desiredLeftEye[0] 因为所需的RightEyeX 值应该与图像的右边缘等距,因为相应的左眼 x 坐标与其左边缘的距离相同。

然后可以通过获取当前图像中眼睛之间的距离与所需图像中眼睛之间的距离的比率来确定人脸的比例

首先,计算欧几里得距离比 dist 。

接下来,使用左右眼 x 值之间的差异,计算所需的距离,desiredDist。

通过在第 52 行乘以所需的面宽来更新所需的距离。这实质上是根据所需的宽度缩放的眼睛距离。

最后,比例是通过将 desiredDist 除以我们之前计算的 dist 来计算的。

现在有了旋转角度和比例,需要在计算仿射变换之前采取一些步骤。这包括找到眼睛之间的中点以及计算旋转矩阵并更新其平移分量:

		# compute center (x, y)-coordinates (i.e., the median point)
        # between the two eyes in the input image
        eyesCenter = (int((leftEyeCenter[0] + rightEyeCenter[0]) // 2),
                      int((leftEyeCenter[1] + rightEyeCenter[1]) // 2))
        # grab the rotation matrix for rotating and scaling the face
        M = cv2.getRotationMatrix2D(eyesCenter, angle, scale)
        # update the translation component of the matrix
        tX = self.desiredFaceWidth * 0.5
        tY = self.desiredFaceHeight * self.desiredLeftEye[1]
        M[0, 2] += (tX - eyesCenter[0])
        M[1, 2] += (tY - eyesCenter[1])

计算 eyeCenter ,即左右眼之间的中点。 这将用于我们的旋转矩阵计算。 本质上,这个中点位于鼻子的顶部,是我们将面部旋转的点:

为了计算旋转矩阵 M ,我们使用 cv2.getRotationMatrix2D 指定 eyeCenter 、角度和比例。这三个值中的每一个都先前已计算过,因此请根据需要返回。

cv2.getRotationMatrix2D 的参数说明如下:

  • eyeCenter :眼睛之间的中点是我们将围绕面部旋转的点。
  • angle:我们将面部旋转到的角度,以确保眼睛位于同一水平线上。
  • scale :我们将放大或缩小图像的百分比,确保图像缩放到所需的大小。

现在必须更新矩阵的平移分量,使人脸在仿射变换后仍然在图像中。

取所需面宽的一半并将值存储为 tX,即 x 方向的平移。

为了计算 tY ,y 方向的平移,将所需的面部高度乘以所需的左眼 y 值,desiredLeftEye[1]。

使用 tX 和 tY ,通过从它们对应的眼睛中点值(第 66 行和第 67 行)中减去每个值来更新矩阵的平移分量。

然后应用仿射变换来对齐人脸:

		# apply the affine transformation
        (w, h) = (self.desiredFaceWidth, self.desiredFaceHeight)
        output = cv2.warpAffine(image, M, (w, h),
            flags=cv2.INTER_CUBIC)
        # return the aligned face
        return output

为方便起见,将 desiredFaceWidth 和 desiredFaceHeight 分别存储到 w 和 h 中(第 70 行)。

然后调用 cv2.warpAffine 执行最后一步。 此函数调用需要 3 个参数和 1 个可选参数:

  • image : 人脸图像。
  • M :平移、旋转和缩放矩阵。
  • (w, h) :输出面所需的宽度和高度。
  • flags :用于扭曲的插值算法,在本例中为 INTER_CUBIC 。 要了解其他可能的标志和图像转换,请参阅 OpenCV 文档。

最后,对齐的脸面。

对齐人脸

开始编写人脸对齐脚本,将其命名为Now let's put this alignment class to work with a simple driver script. Open up a new file, name it align_faces.py:

# import the necessary packages
from imutils.face_utils import FaceAligner
from imutils.face_utils import rect_to_bb
import argparse
import imutils
import dlib
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
help="path to facial landmark predictor")
ap.add_argument("-i", "--image", required=True,
help="path to input image")
args = vars(ap.parse_args())

如果您的系统上没有安装 imutils 和/或 dlib,请确保通过 pip 安装/升级它们:

pip install --upgrade imutils
pip install --upgrade dlib

win10安装dlib参考:如何安装dlib gpu版本

# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor and the face aligner
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
fa = FaceAligner(predictor, desiredFaceWidth=256)

使用 dlib 的 get_frontal_face_detector 初始化我们的检测器对象。

使用 --shape-predictor 来实例化我们的面部标志预测器,这是 dlib 的预训练预测器的路径。

通过在第 21 行初始化一个对象 fa 来利用刚刚在上一节中构建的 FaceAligner 类。我们指定了 256 像素的人脸宽度。

接下来,加载图像并为人脸检测做准备:

# load the input image, resize it, and convert it to grayscale
image = cv2.imread(args["image"])
image = imutils.resize(image, width=800)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# show the original input image and detect faces in the grayscale
# image
cv2.imshow("Input", image)
rects = detector(gray, 2)

加载由命令行参数 --image 指定的图像。 调整图像的大小,保持第 25 行的纵横比,使其宽度为 800 像素。 然后将图像转换为灰度。

处理输入图像中的人脸检测,我们在其中应用了 dlib 的人脸检测器。 此函数返回 rects ,这是我们检测器发现的人脸周围的边界框列表。

在下一个块中,我们遍历 rects ,对齐每个人脸,并显示原始和对齐的图像。

# loop over the face detections
for rect in rects:
	# extract the ROI of the *original* face, then align the face
	# using facial landmarks
	(x, y, w, h) = rect_to_bb(rect)
	faceOrig = imutils.resize(image[y:y + h, x:x + w], width=256)
	faceAligned = fa.align(image, gray, rect)
	# display the output images
	cv2.imshow("Original", faceOrig)
	cv2.imshow("Aligned", faceAligned)
	cv2.waitKey(0)

开始循环。

对于 dlib 预测的每个边界框 rect,我们将其转换为格式 (x, y, w, h)。

随后,将框的大小调整为 256 像素的宽度,保持纵横比。将这个原始但调整大小的图像存储为 faceOrig 。

对齐图像,指定图像、灰度图像和矩形。

最后,将原始和对应的对齐人脸图像显示到各自窗口的屏幕上。

在显示下一个原始/对齐图像对之前,等待用户在任一窗口处于焦点时按下一个键。

对所有检测到的人脸重复上面的过程,然后脚本退出。

展示结果

输入命令:

python align_faces.py --shape-predictor shape_predictor_68_face_landmarks.dat --image 11.jpg

到此这篇关于人脸检测实战终极之OpenCV+Python实现人脸对齐的文章就介绍到这了,更多相关Python OpenCV人脸对齐内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python+Opencv实战之人脸追踪详解

    目录 前言 人脸追踪技术简介 使用基于 dlib DCF 的跟踪器进行人脸跟踪 使用基于 dlib DCF 的跟踪器进行对象跟踪 小结 前言 人脸处理是人工智能中的一个热门话题,人脸处理可以使用计算机视觉算法从人脸中自动提取大量信息,例如身份.意图和情感:而目标跟踪试图估计目标在整个视频序列中的轨迹,其中只有目标的初始位置是已知的,将这两者进行结合将产生许多有趣的应用.由于外观变化.遮挡.快速运动.运动模糊和比例变化等多种因素,人脸追踪非常具有挑战性. 人脸追踪技术简介 基于判别相关滤波器 (d

  • Python基于pyopencv人脸识别并绘制GUI界面

    目录 项目介绍 采集人脸: 识别功能: 项目思路 项目模块 1.人脸采集 2.数据训练 3.人脸识别 4.GUI界面 项目代码 人脸采集 数据训练 人脸识别 合并GUI 项目总结 项目介绍 我们先来看看成果: 首先写了一个能够操作的GUI界面. 其中两个按钮对应相应的功能: 采集人脸: 识别功能: 我可是牺牲了色相五五五五...(电脑像素不是很好大家将就一下嘿嘿嘿) 项目思路 本项目是借助于python的一个cv2图像识别库,通过调取电脑的摄像头进行识别人脸并保存人脸图片的功能,然后在通过cv2

  • Python+OpenCV进行人脸面部表情识别

    目录 前言 一.图片预处理 二.数据集划分 三.识别笑脸 四.Dlib提取人脸特征识别笑脸和非笑脸 前言 环境搭建可查看Python人脸识别微笑检测 数据集可在https://inc.ucsd.edu/mplab/wordpress/index.html%3Fp=398.html获取 数据如下: 一.图片预处理 import dlib # 人脸识别的库dlib import numpy as np # 数据处理的库numpy import cv2 # 图像处理的库OpenCv import os

  • python基于Opencv实现人脸口罩检测

    一.开发环境 python 3.6.6 opencv-python 4.5.1 二.设计要求 1.使用opencv-python对人脸口罩进行检测 三.设计原理 设计流程图如图3-1所示, 图3-1 口罩检测流程图 首先进行图片的读取,使用opencv的haar鼻子特征分类器,如果检测到鼻子,则证明没有戴口罩.如果检测到鼻子,接着使用opencv的haar眼睛特征分类器,如果没有检测到眼睛,则结束.如果检测到眼睛,则把RGB颜色空间转为HSV颜色空间.进行口罩区域的检测.口罩区域检测流程是首先把

  • 基于python3+OpenCV实现人脸和眼睛识别

    基于python3+OpenCV的人脸和眼睛识别,供大家参考,具体内容如下 一.OpenCV人脸检测的xml文件下载 人脸检测和眼睛检测要用到haarcascade_eye.xml和haarcascade_frontalface_default.xml这两个文件,这两个文件可以在OpenCV的官网下载,具体下载方法如下: 1.打开要下载的xml文件,如下图: 2.点击Raw: 3.在新打开的网页中右击,选择另存为,最后保存就可以了. 二.人脸检测文件的导入以及图片的处理 接下来就可以在代码中载入

  • 人脸检测实战终极之OpenCV+Python实现人脸对齐

    目录 前言 实现面部矫正器 导入必要的包 对齐人脸 展示结果 前言 这篇博文的目的是演示如何使用 OpenCV.Python 和面部标志对齐人脸. 给定一组面部标志(输入坐标),我们的目标是将图像扭曲并转换为输出坐标空间. 在这个输出坐标空间中,整个数据集中的所有面都应该: 在图像中居中. 旋转,使眼睛位于水平线上(即,旋转面部,使眼睛位于相同的 y 坐标上). 进行缩放,使面的大小大致相同. 为此,我们将首先调用一个实现的 Python 类FaceAligner ,以使用仿射变换对齐人脸. 注

  • Python人脸检测实战之疲劳检测

    目录 使用 OpenCV 构建犯困检测器 测试疲劳检测器 今天我们实现疲劳检测. 如果眼睛已经闭上了一段时间,我们会认为他们开始打瞌睡并发出警报来唤醒他们并引起他们的注意.我们测试一段视频来展示效果.同时代码中保留开启摄像头的的代码,取消注释即可使用. 使用 OpenCV 构建犯困检测器 要开始我们的实现,打开一个新文件,将其命名为 detect_drowsiness.py ,并插入以下代码: # import the necessary packages from scipy.spatial

  • 详解如何用OpenCV + Python 实现人脸识别

    下午的时候,配好了OpenCV的Python环境,OpenCV的Python环境搭建.于是迫不及待的想体验一下opencv的人脸识别,如下文. 必备知识 Haar-like 通俗的来讲,就是作为人脸特征即可. Haar特征值反映了图像的灰度变化情况.例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等. opencv api 要想使用opencv,就必须先知道其能干什么,怎么做.于是API的重要性便体现出来了.就本例而言,使用到的函数

  • 人脸识别实战之Opencv+SVM实现人脸识别

    目录 前言 项目结构 编码 训练人脸识别模型 识别图像中的人脸 摄像头识别人脸 前言 在本文中,您将学习如何使用 OpenCV 进行人脸识别.文章分三部分介绍: 第一,将首先执行人脸检测,使用深度学习从每个人脸中提取人脸量化为128位的向量. 第二, 在嵌入基础上使用支持向量机(SVM)训练人脸识别模型. 第三,最后使用 OpenCV 识别图像和视频流中的人脸. 项目结构 编码 新建face_embeddings.py脚本,写入如下代码: # import the necessary packa

  • OpenCV实现人脸检测

    前段日子,写了个人脸检测的小程序,可以检测标记图片.视频.摄像头中的人脸.效果还行吧,用的是opencv提供人脸库.至于具体的人脸检测原理,找资料去啃吧. 环境:VS2013+OPENCV2.4.10+Win8.1 一.基于对话框的MFC 首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消"安全开发周期(SDL)检查"勾选,我自己习惯取消这个). 放置Button,设置Button的ID和Caption. 图片按钮--ID:IDC_FACEDETECT 视频

  • opencv实现图片与视频中人脸检测功能

    本文实例为大家分享了opencv实现人脸检测功能的具体代码,供大家参考,具体内容如下 第一章:反思与总结 上一篇博客我相信自己将人脸检测中的AdaBoost算法解释的非常清晰了,以及如何训练人脸检测的强分类器:人脸检测中AdaBoost算法详解.事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的.做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,非常感谢这位博主,我学到了很

  • python实现人脸识别经典算法(一) 特征脸法

    近来想要做一做人脸识别相关的内容,主要是想集成一个系统,看到opencv已经集成了三种性能较好的算法,但是还是想自己动手试一下,毕竟算法都比较初级. 操作环境:python2.7 第三方库:opencv for python.numpy 第一种比较经典的算法就是特征脸法,本质上其实就是PCA降维,这种算法的基本思路是,把二维的图像先灰度化,转化为一通道的图像,之后再把它首尾相接转化为一个列向量,假设图像大小是20*20的,那么这个向量就是400维,理论上讲组织成一个向量,就可以应用任何机器学习算

  • Android动态人脸检测的示例代码(脸数可调)

    人脸检测 这里的人脸检测并非人脸识别,但是却可以识别出是否有人,当有人时候,你可以将帧图进行人脸识别(这里推荐Face++的sdk),当然我写的demo中没有加入人脸识别,有兴趣的朋友可以追加.face++ android自带的人脸检测 这里我们用到了人脸检测类为 FaceDetector.这个类提供了强大的人脸检测功能,可以方便我们进行人脸的侦测,因此我们使用他来进行动态的人脸检测,实现原理,其实也挺简单,主要是通过Carmen的回调PreviewCallback 在其中对帧图进行操作,并通过

  • JavaCV调用百度AI实现人脸检测方法详解

    目录 本篇概览 注册百度账号 登录百度智能云 实名认证 创建应用 拿到API Key和Secret Key 编码 使用限制 本篇概览 在检测人脸数量.位置.性别.口罩等场景时,可以考虑使用百度开放平台提供的web接口,一个web请求就能完成检测得到结果,本篇记录了从申请到真实调用的完整过程,由以下步骤组成: 注册百度账号 按照您的实际情况,注册个人或者企业账号,这个不多说了 登录百度智能云 使用刚才注册号的账号登录,地址是:https://login.bce.baidu.com/ 实名认证 打开

  • python中使用OpenCV进行人脸检测的例子

    OpenCV的人脸检测功能在一般场合还是不错的.而ubuntu正好提供了python-opencv这个包,用它可以方便地实现人脸检测的代码. 写代码之前应该先安装python-opencv: 复制代码 代码如下: $ sudo apt-get install python-opencv 具体原理就不多说了,可以参考一下这篇文章.直接上源码. 复制代码 代码如下: #!/usr/bin/python# -*- coding: UTF-8 -*- # face_detect.py # Face De

随机推荐