利用dlib、imutils、opencv实现脸部剪裁旋转

  • Post author:
  • Post category:其他

【环境搭建】
1.安装cmake
pip install cmake
2.安装dlib
pip install dlib
注1:python3.7之前的版本如果不能直接下载,可以去豆瓣源的dlib区下载http://pypi.doubanio.com/simple/dlib/
注2:pythoh3.7的dlib包如在此处下载 链接:https://pan.baidu.com/s/1SOYzGexGxUrFwTDgq93gNA 
提取码:z3db

3.安装Imutils

pip install imutils

如果不行就用豆瓣源http://pypi.doubanio.com/simple/imutils/

4、安装opencv(若未安装请自行安装)

【实现功能:人脸对齐、旋转、裁剪】

【与模型人脸对齐函数(分5个关键点和68个关键点两种方法,本文采用5个关键点,取眼睛和鼻子作为参考。68个关键点的原理类似)】

【代码如下】

import numpy as np 
import cv2 
from collections import OrderedDict#排序
import argparse
import dlib 
import matplotlib.pyplot as plt
import imutils
#加载模型
p = 'shape_predictor_5_face_landmarks.dat'
#p = 'shape_predictor_68_face_landmarks.dat'
#FACIAL_LANDMARKS_5_IDXS = OrderedDict([("right_eye", (2, 3)),("left_eye", (0, 1)),("nose", (4))])#定义人脸区域的字典和坐标
#FACIAL_LANDMARKS_68_IDXS = OrderedDict([("mouth", (48, 68)),("right_eyebrow", (17, 22)),("left_eyebrow", (22, 27)),("right_eye", (36, 42)),("left_eye", (42, 48)),("nose", (27, 36)),("jaw",(0,17))])#定义人脸区域的字典和坐标
#人脸对齐
class FaceAligner:
    #初始化人脸框
	def __init__(self, predictor, desiredLeftEye=(0.42, 0.42), desiredFaceWidth=224, desiredFaceHeight=None):#0.35,0.35
		self.predictor = predictor 
		self.desiredLeftEye = desiredLeftEye 
		self.desiredFaceWidth = desiredFaceWidth 
		self.desiredFaceHeight = desiredFaceHeight 
		if self.desiredFaceHeight is None:
			self.desiredFaceHeight = self.desiredFaceWidth

	def align(self, image, gray, rect):
		for i in range(len(rects)):
			landmarks = np.matrix([[p.x, p.y] for p in predictor(image,rects[i]).parts()])
		for idx, point in enumerate(landmarks):
			if(idx==0):
				p0x = (point[0, 0])
				p0y = (point[0, 1])
			elif(idx==1):
				p1x = (point[0, 0])
				p1y = (point[0, 1])
			elif(idx==2):
				p2x = (point[0, 0])
				p2y = (point[0, 1])
			elif(idx==3):
				p3x = (point[0, 0])
				p3y = (point[0, 1])
		lefteyex=(p2x+p3x)/2
		lefteyey=(p2y+p3y)/2
		righteyex=(p0x+p1x)/2
		righteyey=(p0y+p1y)/2
		centerx=(lefteyex+righteyex)/2
		centery=(lefteyey+righteyey)/2
		dX=(righteyex-centerx)
		dY=(righteyey-centery)
		angle = np.degrees(np.arctan2(dY, dX))
        
        # 根据所需的x坐标计算所需的右眼x坐标
		desiredRightEyeX = 1.0 - self.desiredLeftEye[0]

        # 通过获取当前图像中眼睛之间的距离与所需图像中眼睛之间的距离的比率来确定新结果图像的比例
		dist = np.sqrt((dX ** 2) + (dY ** 2))
		desiredDist = (desiredRightEyeX - self.desiredLeftEye[0])
		desiredDist *= self.desiredFaceWidth
		scale = desiredDist / dist

        # 使用旋转矩阵旋转和缩放脸
		M = cv2.getRotationMatrix2D((centerx,centery), angle, scale)

        # 更新矩阵的旋转量
		tX = self.desiredFaceWidth * 0.5
		tY = self.desiredFaceHeight * self.desiredLeftEye[1]
		M[0, 2] += (tX - centerx)
		M[1, 2] += (tY - centery)

        # 应用仿射变换
		(w, h) = (self.desiredFaceWidth, self.desiredFaceHeight)
		output = cv2.warpAffine(image, M, (w, h),
			flags=cv2.INTER_CUBIC)

        # 返回对齐脸
		return output

#获取人脸关矩阵的坐标
def rect_to_bb(rect):
	# take a bounding predicted by dlib and convert it
	# to the format (x, y, w, h) as we would normally do
	# with OpenCV
	x = rect.left()
	y = rect.top()
	w = rect.right() - x
	h = rect.bottom() - y

	# return a tuple of (x, y, w, h)
	return (x, y, w, h)
    
image = cv2.imread('test5.jpg')#读图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#灰度化
detector = dlib.get_frontal_face_detector()#创建预测器
predictor = dlib.shape_predictor(p)#读模型
fa = FaceAligner(predictor, desiredFaceWidth=224)
print(fa)
#检测面部,得到左上、右下坐标
rects = detector(gray, 1)#2
#提取感兴趣部分并对齐
FaceAligned = fa.align(image, gray, rects)
cv2.imshow('faceorig',image)
cv2.imshow('alin', FaceAligned)
cv2.waitKey(0)
cv2.destroyAllWindows()

模型百度云链接:https://pan.baidu.com/s/1AjMhKl3R-iU2cYiGJ1ptBw 
提取码:smvs


版权声明:本文为qq_37249793原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。