(1)使用 get_face_chip()方法实验结果:
import cv2
import dlib
import matplotlib.pyplot as plt
# 获取图片
image = cv2.imread('33.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# 使用特征提取器get_frontal_face_detector
detector = dlib.get_frontal_face_detector()
dets = detector(image_gray, 1)
for det in dets:
# 将框画在原图上
# cv2.rectangle 参数1:图片, 参数2:左上角坐标, 参数2:左上角坐标, 参数3:右下角坐标, 参数4:颜色(R,G,B), 参数2:粗细
my_img = cv2.rectangle(image, (det.left(), det.top()), (det.right(), det.bottom()), (0, 255, 0), 2)
cv2.imshow("image", image)
cv2.waitKey(0)
# 人脸检测器
predictor = dlib.shape_predictor(r'./shape_predictor_68_face_landmarks.dat')
#
for det in dets:
shape = predictor(image, det)
# 将关键点绘制到人脸上
for i in range(68):
cv2.putText(image, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_DUPLEX, 0.1, (0, 255,0 ), 1, cv2.LINE_AA)
cv2.circle(image, (shape.part(i).x, shape.part(i).y), 1, (0, 0, 255))
cv2.imshow("rotated", image)
cv2.waitKey(0)
# 人脸对齐
image = dlib.get_face_chip(image, shape, size = 150)
cv2.imshow("68landmarks", image)
cv2.waitKey(0)
原理参考:
(2)使用68点关键点模型方法如下:
人脸对齐思路:
实验结果如下:
import cv2
import dlib
import numpy as np
class Face_Align(object):
def __init__(self, shape_predictor_path):
self.detector = dlib.get_frontal_face_detector()
self.predictor = dlib.shape_predictor(shape_predictor_path)
self.LEFT_EYE_INDICES = [36, 37, 38, 39, 40, 41]
self.RIGHT_EYE_INDICES = [42, 43, 44, 45, 46, 47]
def rect_to_tuple(self, rect):
left = rect.left()
right = rect.right()
top = rect.top()
bottom = rect.bottom()
return left, top, right, bottom
def extract_eye(self, shape, eye_indices):
points = map(lambda i: shape.part(i), eye_indices)
return list(points)
def extract_eye_center(self, shape, eye_indices):
points = self.extract_eye(shape, eye_indices)
xs = map(lambda p: p.x, points)
ys = map(lambda p: p.y, points)
return sum(xs) // 6, sum(ys) // 6
def extract_left_eye_center(self, shape):
return self.extract_eye_center(shape, self.LEFT_EYE_INDICES)
def extract_right_eye_center(self, shape):
return self.extract_eye_center(shape, self.RIGHT_EYE_INDICES)
def angle_between_2_points(self, p1, p2):
x1, y1 = p1
x2, y2 = p2
tan = (y2 - y1) / (x2 - x1)
print("旋转角度:",np.degrees(np.arctan(tan)))
return np.degrees(np.arctan(tan))
def get_rotation_matrix(self, p1, p2):
angle = self.angle_between_2_points(p1, p2)
x1, y1 = p1
x2, y2 = p2
xc = (x1 + x2) // 2
yc = (y1 + y2) // 2
M = cv2.getRotationMatrix2D((xc, yc), angle, 1)
print("旋转矩阵:",M)
return M
def crop_image(self, image, det):
left, top, right, bottom = self.rect_to_tuple(det)
return image[top:bottom, left:right]
def __call__(self, image=None, image_path=None, save_path=None, only_one=True):
'''
Face alignment, can select input image variable or image path, when input
image format that return alignment face image crop or image path as input
will return None but save image to the save path.
:image: Face image input
:image_path: if image is None than can input image
:save_path: path to save image
:detector: detector = dlib.get_frontal_face_detector()
:predictor: predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
'''
if image is not None:
# convert BGR format to Gray
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
elif image_path is not None:
image_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
image = cv2.imread(image_path)
height, width = image.shape[:2]
print("原图形状:",image.shape) # 获取图像的形状,返回值是一个包含行数、列数、通道数的元组。
# Dector face
dets = self.detector(image_gray, 1)
# i donate the i_th face detected in image
crop_images = []
for i, det in enumerate(dets):
shape = self.predictor(image_gray, det)
left_eye = self.extract_left_eye_center(shape)
right_eye = self.extract_right_eye_center(shape)
M = self.get_rotation_matrix(left_eye, right_eye)
rotated = cv2.warpAffine(image, M, (width, height), flags=cv2.INTER_CUBIC)
cv2.imshow("xuanzhuan", rotated)
cv2.waitKey(0)
cropped = self.crop_image(rotated, det)
if only_one == True:
if save_path is not None:
cv2.imwrite(save_path, cropped)
return cropped
else:
crop_images.append(cropped)
return crop_images
if __name__ == "__main__":
image = cv2.imread('33.jpg')
cv2.imshow("image", image)
cv2.waitKey(0)
align = Face_Align("./shape_predictor_68_face_landmarks.dat")
align = align(image,image_path=None,save_path="test.jpg",only_one=True)
print(align.shape)
cv2.imshow("align", align)
cv2.waitKey(0)
原理参考:
face_utils.FaceAligner 主要代码
from imutils import face_utils
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
fa = face_utils.FaceAligner(predictor, desiredFaceWidth=256)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
dets = self.detector(gray, 1)
shape= self.predictor(gray, dets[0])
frame_align = fa.align(frame, gray, dets[0]) # align face 人脸对齐后裁剪
cv2.imshow("frame_align", frame_align)
cv2.waitKey(0)