在人脸识别项目中,如果图片中人脸的方向各不一样且相差很大,这样会影响人脸识别的准确率。所以在实际人脸检测项目中,在人脸识别的前一步往往会先进行人脸对齐。人脸对齐可以看作是数据normalization的一种形式。正如我们可以在训练机器学习模型之前通过对一组特征向量进行零中心化或缩放到单位范数来normalization一样,在训练人脸识别模型之前我们往往会先对齐数据集中的人脸。

对齐人脸有很多种方法,今天我们尝试使用OpenCV中的仿射变换来人脸对齐。

使用OpenCV进行人脸对齐

主函数代码

# USAGE
# python align_faces.py --shape-predictor shape_predictor_68_face_landmarks.dat --image images/example_01.jpg# 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())# 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)# 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)# 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)import uuidf = str(uuid.uuid4())cv2.imwrite("foo/" + f + ".png", faceAligned)# display the output imagescv2.imshow("Original", faceOrig)cv2.imshow("Aligned", faceAligned)cv2.waitKey(0)

dlib.get_frontal_face_detector是dlib预训练好的的人脸检测器,可以检测到图片中人脸的外接矩形,dlib.shape_predictor是人脸的面部标志检测模型,详细介绍和应用可以参看:

小糊糊:使用dlib进行睡意检测​zhuanlan.zhihu.com

上面的代码对输入图片检测人脸后,再使用FaceAligner中的align方法来对齐检测到的人脸,然后再将对齐的人脸可视化,然后存入foo文件夹中。

人脸对齐算法主要是由FaceAligner类实现的,FaceAligner的代码如下:

# import the necessary packages
from .helpers import FACIAL_LANDMARKS_68_IDXS
from .helpers import FACIAL_LANDMARKS_5_IDXS
from .helpers import shape_to_np
import numpy as np
import cv2class 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 + heightself.predictor = predictorself.desiredLeftEye = desiredLeftEyeself.desiredFaceWidth = desiredFaceWidthself.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.desiredFaceWidthdef align(self, image, gray, rect):# convert the landmark (x, y)-coordinates to a NumPy arrayshape = self.predictor(gray, rect)shape = shape_to_np(shape)#simple hack ;)if (len(shape)==68):# extract the left and right eye (x, y)-coordinates(lStart, lEnd) = FACIAL_LANDMARKS_68_IDXS["left_eye"](rStart, rEnd) = FACIAL_LANDMARKS_68_IDXS["right_eye"]else:(lStart, lEnd) = FACIAL_LANDMARKS_5_IDXS["left_eye"](rStart, rEnd) = FACIAL_LANDMARKS_5_IDXS["right_eye"]leftEyePts = shape[lStart:lEnd]rightEyePts = shape[rStart:rEnd]# compute the center of mass for each eyeleftEyeCenter = leftEyePts.mean(axis=0).astype("int")rightEyeCenter = rightEyePts.mean(axis=0).astype("int")# compute the angle between the eye centroidsdY = rightEyeCenter[1] - leftEyeCenter[1]dX = rightEyeCenter[0] - leftEyeCenter[0]angle = np.degrees(np.arctan2(dY, dX)) - 180# compute the desired right eye x-coordinate based on the# desired x-coordinate of the left eyedesiredRightEyeX = 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* imagedist = np.sqrt((dX ** 2) + (dY ** 2))desiredDist = (desiredRightEyeX - self.desiredLeftEye[0])desiredDist *= self.desiredFaceWidthscale = desiredDist / dist# compute center (x, y)-coordinates (i.e., the median point)# between the two eyes in the input imageeyesCenter = ((leftEyeCenter[0] + rightEyeCenter[0]) // 2,(leftEyeCenter[1] + rightEyeCenter[1]) // 2)# grab the rotation matrix for rotating and scaling the faceM = cv2.getRotationMatrix2D(eyesCenter, angle, scale)# update the translation component of the matrixtX = self.desiredFaceWidth * 0.5tY = self.desiredFaceHeight * self.desiredLeftEye[1]M[0, 2] += (tX - eyesCenter[0])M[1, 2] += (tY - eyesCenter[1])# apply the affine transformation(w, h) = (self.desiredFaceWidth, self.desiredFaceHeight)output = cv2.warpAffine(image, M, (w, h),flags=cv2.INTER_CUBIC)# return the aligned facereturn output

align函数首先提取原脸中眼睛的位置,计算每只眼睛的中心,然后计算眼睛中心连线与水平线的夹角angle ,然后计算对齐后目标图像中左右眼坐标(默认左眼中心距离图像左边界0.35图像宽度),从而可以得到对齐后图像需要缩放的比例scale (默认对齐后图像宽为256),然后计算原图中两眼连线中心坐标,以此中心为旋转中心,angle 为旋转角,scale 为缩放尺度计算出旋转矩阵M。由于图像旋转我们要将对齐后的人脸输出到256X256的图像里,所以要将对齐后的人脸图像的眉心平移到新图像256X256的合适位置,将此平移量加到矩阵M里面。最后使用新的变换矩阵来进行仿射变换。

关于仿射变换和矩阵旋转原理可以参看:

小糊糊:正确的实现图像旋转​zhuanlan.zhihu.com

结果展示

拿一张老詹热火时期的图测试一下,命令行运行:

python align_faces.py --shape-predictor shape_predictor_68_face_landmarks.dat --image images/example_01.jpg

结果如下,可以看到很好的对齐了老詹的脸。

参考

https://www.pyimagesearch.com/2017/05/22/face-alignment-with-opencv-and-python/​www.pyimagesearch.com

opencv中mean函数耗时_使用OpenCV进行人脸对齐相关推荐

  1. OpenCV中initUndistortRectifyMap函数存在bug原因探究

    原文首发于公众号「3D视觉工坊」:OpenCV中initUndistortRectifyMap函数存在bug原因探究. 最近在运行如下一段代码时,生成的mapx和mapy有点异常. 代码片段如下: # ...

  2. 转载:opencv中imshow函数运行中断的解决办法

    OpenCV中 imshow函数运行中断的解决方法 羊和咩咩 2017-03-10 16:00:49 5919 收藏 最后发布:2017-03-10 16:00:49首发:2017-03-10 16: ...

  3. 关于opencv中cvtcolor函数的code参数用CV_BGR2YUV与CV_BGR2YCrCb的了解

    根据Opencv中cvtcolor函数的源码描述,,参数CV_BGR2YCrCb用的系数为[1868, 9617, 4899, 11682, 9241], 而参数CV_BGR2YUV对应的系数只是将C ...

  4. 关于Opencv中Filter2D函数的补全方式

    目录 关于Opencv中Filter2D函数的补全方式 环境 验证 C++举例 Python举例 关于Opencv中Filter2D函数的补全方式 环境 OpenCV3.4.16(C++) openc ...

  5. imfilter c语言,opencv中cvFilter2D( ) 函数filter2D()函数与MATLAB中imfilter()函数的差异...

    出处: 1:cvFilter2D() 函数为opencv中c语言函数 2:filter2D()函数为opencv中c++函数 3:imfilter()函数为matlab版本函数 计算结果的异同: 2( ...

  6. Opencv中直方图函数calcHist

    Opencv中直方图函数calcHist calcHist函数在Opencv中是极难理解的一个函数,一方面是参数说明晦涩难懂,另一方面,说明书给出的实例也不足以令人完全搞清楚该函数的使用方式.最难理解 ...

  7. OpenCV中flip函数实现

    一.flip()函数原型介绍 void cv::flip(InputArray src,OutputArray dst, int flipCode) 各参数含义 src:输入图像. dst:输出图像. ...

  8. 分段线性插值c语言程序_【短道速滑】OpenCV中cvResize函数使用双线性插值缩小图像长宽大小一半时速度飞快(比最近邻还快)之异象解析和自我实现。...

    点击上方↑↑↑"OpenCV学堂"关注我 作者网名:laviewpbt 是图像处理,算法实现与加速优化方面的大神!其开发的imageshop软件大小只有1MB,却实现了非常丰富与复 ...

  9. OpenCV中resize函数五种插值算法的实现过程

    最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻.双线性.双三次.基于像素区域关系.兰索斯插值.下面用for循环代替cv::resize函数来说明其详细的插值实现过程,其 ...

最新文章

  1. windows下的eclipse运行hdfs程序时报错 (null) entry in command string: null chmod 0644【笔记自用】
  2. nmon安装为什么重启mysql_Nmon的安装及使用
  3. 安装Ubuntu nginx及其配置安装Php
  4. Django module学习之模板
  5. python计算excel crc_python实现计算资源图标crc值的方法
  6. labview与单片机正弦信号_LabVIEW小白入门——低通滤波器
  7. 百度起诉今日头条;腾讯云超 8000 名员工获 iPhone 11 Pro 奖励;PHP 7.4.1 发布 | 极客头条...
  8. Java 学习笔记(官方不推荐写法篇)
  9. WORD中使用类似苹果手机的字体Lucida Sans
  10. 压缩(minify)
  11. Intellij Idea 主题下载(Eclectide Monokai)
  12. linux php 集成安装,1.2.2 XAMPP-Linux版PHP集成化安装包
  13. 2021-2027全球与中国IPA干燥机市场现状及未来发展趋势
  14. 奥西450的服务器系统,奥西TDS450驱动
  15. android m4a播放器,如何在android上解码m4a音频
  16. pygame中blit()的参数的说明以及脏矩形动画形成的简要说明
  17. 微软相关网站和软件无法上网的解决办法
  18. Javascript 脚本语言
  19. javaWeb课程设网上报名系统
  20. 洛谷p5740最厉害的学生 C语言

热门文章

  1. 大数据开发笔记(九):Flink基础
  2. C++第五章课后习题13
  3. 用商业智能BI软件的好处有哪些
  4. 物联网卡不能使用的情况有哪些
  5. plsql查询不显示结果_管理NVivo的查询结果
  6. php项目打不开DNS,电脑无法打开网页显示错误代码dns_probe_possible怎么解决?
  7. 团队协助 开源项目_5分钟了解 Vtiger CRM-国际知名开源客户管理软件
  8. 埋石图根点lisp代码_GPS测量作业流程.doc
  9. wxWidgets第十七课 采用AGG渲染库
  10. 移动大数据时代:无线网络的挑战与机遇