import cv2
import dlib
import numpy as np
from mopi import beauty_face2
img_file = '1.jpg'
img = cv2.imread(img_file)
src = img
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
predictor_path = 'shape_predictor_68_face_landmarks.dat'
# 使用dlib自带的frontal_face_detector作为我们的特征提取器
#检测框提取器
detector = dlib.get_frontal_face_detector()
#关键点提取器
predictor = dlib.shape_predictor(predictor_path)
land_marks = []
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#获取检测框
rects = detector(img_gray, 0)
#获取所有人脸检测框的关键点
for i in range(len(rects)):
    land_marks_node = np.matrix([[p.x, p.y] for p in predictor(img_gray, rects[i]).parts()])
    land_marks.append(land_marks_node)
#绘制坐标框
def get_landmarks(img):
    rects = detector(img, 1)

    if len(rects) > 1:
        raise TooManyFaces
    if len(rects) == 0:
        raise NoFaces

    draw = img.copy()
    for _, d in enumerate(rects):
        cv2.rectangle(draw, (d.left(), d.top()), (d.right(), d.bottom()), (0, 255, 0), 3)

    return np.matrix([[p.x, p.y] for p in predictor(img, rects[0]).parts()])
#计算偏移坐标
def move_up(x):
    list = [[0 for j in range(2)] for _ in range(9)]
    for i in range (9):
        list[i][1]=x
    return list
list = np.array(move_up(100))
def get_image_size(image):
    """
    获取图片大小(高度,宽度)
    :param image: image
    :return: (高度,宽度)
    """
    image_size = (image.shape[0], image.shape[1])
    return image_size
def get_face_mask(image_size, face_landmarks):
    """
    获取人脸掩模
    :param image_size: 图片大小
    :param face_landmarks: 68个特征点
    :return: image_mask, 掩模图片
    """
    mask = np.zeros(image_size, dtype=np.uint8)
    etou_point = np.array(face_landmarks[26:17:-1])
    etou_point = etou_point - list
    points = np.concatenate([face_landmarks[0:16], etou_point])
    #print(type(points))
    cv2.fillPoly(img=mask, pts=[points], color=255)

    # mask = np.zeros(image_size, dtype=np.uint8)
    # points = cv2.convexHull(face_landmarks)  # 凸包
    # cv2.fillConvexPoly(mask, points, color=255)
    return mask
def get_eye_mask(image_size, face_landmarks):
    """
    获取人脸掩模
    :param image_size: 图片大小
    :param face_landmarks: 68个特征点
    :return: image_mask, 掩模图片
    """
    mask1 = np.zeros(image_size, dtype=np.uint8)
    #points = np.concatenate([face_landmarks[36:41], face_landmarks[42:47]])
    points = face_landmarks[36:41]
    cv2.fillPoly(img=mask1, pts=[points], color=255)
    mask2 = np.zeros(image_size, dtype=np.uint8)
    #points = np.concatenate([face_landmarks[36:41], face_landmarks[42:47]])
    points = face_landmarks[42:47]
    cv2.fillPoly(img=mask2, pts=[points], color=255)
    mask3 = np.zeros(image_size, dtype=np.uint8)
    # points = np.concatenate([face_landmarks[36:41], face_landmarks[42:47]])
    points = face_landmarks[42:47]
    cv2.fillPoly(img=mask2, pts=[points], color=255)
    # mask = np.zeros(image_size, dtype=np.uint8)
    # points = cv2.convexHull(face_landmarks)  # 凸包
    # cv2.fillConvexPoly(mask, points, color=255)
    mask3 = np.zeros(image_size, dtype=np.uint8)
    # points = np.concatenate([face_landmarks[36:41], face_landmarks[42:47]])
    points = face_landmarks[48:59]
    cv2.fillPoly(img=mask3, pts=[points], color=255)
    return mask1,mask2,mask3
#对人脸进行美颜
mopisrc = beauty_face2(src)
def get_image_size(image):
    """
    获取图片大小(高度,宽度)
    :param image: image
    :return: (高度,宽度)
    """
    image_size = (image.shape[0], image.shape[1])
    return image_size
im_size = get_image_size(src)  # 脸图大小
landmarks = get_landmarks(src)  # 68_face_landmarks
im_mask = get_face_mask(im_size, landmarks)  # 脸图人脸掩模
#points = np.concatenate([face_landmarks[0:16], face_landmarks[26:17:-1]])
  # im1(脸图)仿射变换后的图片的人脸掩模的中心点
def get_mask_center_point(image_mask):
    """
    获取掩模的中心点坐标
    :param image_mask: 掩模图片
    :return: 掩模中心
    """
    image_mask_index = np.argwhere(image_mask > 0)
    miny, minx = np.min(image_mask_index, axis=0)
    maxy, maxx = np.max(image_mask_index, axis=0)
    center_point = ((maxx + minx) // 2, (maxy + miny) // 2)
    return center_point
#获取掩膜中心点
point = get_mask_center_point(im_mask)
#人脸掩膜融合
mask1,mask2,mask3 = get_eye_mask(im_size,landmarks)
mask_face = get_face_mask(im_size,landmarks)
# mask1 = cv2.bitwise_not(mask1)
# mask2 = cv2.bitwise_not(mask2)
mask = mask_face-(mask1+mask2+mask3)
seamless_im = cv2.seamlessClone(mopisrc, src, mask=mask, p=point, flags=cv2.NORMAL_CLONE)# 进行泊松融合
seamless_im2 = cv2.seamlessClone(mopisrc, src, mask=mask_face, p=point, flags=cv2.NORMAL_CLONE)# 进行泊松融合

cv2.imshow('im',mask)
cv2.imshow('seamless_im',seamless_im)
cv2.imshow('seamless_im2',seamless_im2)
# cv2.imshow('src',src)
cv2.waitKey(0)

利用opencv生成面膜_特征点