一般来说,使用 mtcnn 网络检测到人脸后,都需要进行矫正。而对于人脸矫正,最简单的可以通过使用仿射变换来实现。

思路:

  • 通过 mtcnn 模型检测到人脸的 5 个特征点:左眼,右眼,鼻子,左嘴角,右嘴角;
bounding_boxes = {
'box': [int(bounding_box[0]), int(bounding_box[1]),
int(bounding_box[2]), int(bounding_box[3])],
'confidence': bounding_box[-1],
'keypoints': {
'left_eye': (int(keypoints[0]), int(keypoints[5])),
'right_eye': (int(keypoints[1]), int(keypoints[6])),
'nose': (int(keypoints[2]), int(keypoints[7])),
'mouth_left': (int(keypoints[3]), int(keypoints[8])),
'mouth_right': (int(keypoints[4]), int(keypoints[9])),
}
}

bounding_box = bounding_boxes['box']
keypoints = bounding_boxes['keypoints']
  • 计算双眼中心点的位置 eye_center 和双眼连线的倾斜角度 angle
  • 通过 eye_centerangle 得到仿射变换矩阵 rot_matrix
  • 将整张图片进行仿射变换得到 align_image
def align_face(image, keypoints, scale=1.0):
eye_center = (
(keypoints['left_eye'][0] + keypoints['right_eye'][0]) * 0.5,
(keypoints['left_eye'][1] + keypoints['right_eye'][1]) * 0.5,
)
dx = keypoints['right_eye'][0] - keypoints['left_eye'][0]
dy = keypoints['right_eye'][1] - keypoints['left_eye'][1]

angle = cv2.fastAtan2(dy, dx)
rot_matrix = cv2.getRotationMatrix2D(eye_center, angle, scale=scale)
rot_image = cv2.warpAffine(image, rot_matrix, dsize=(image.shape[1], image.shape[0]))
return rot_image

align_image = align_face(image, keypoints)
  • 根据从 原图检测的 2D 框align_image 图片中抠出人脸并保存。
xmin = bounding_box[0]
ymin = bounding_box[1]
xmax = bounding_box[2]
ymax = bounding_box[3]
crop_image = align_image[ymin:ymax, xmin:xmax, :]
cv2.imwrite("align_face.jpg", crop_image)