换脸代码笔记

来源:互联网 发布:专业java培训中心 编辑:程序博客网 时间:2024/05/03 22:27

原技术文章网址

http://matthewearl.github.io/2015/07/28/switching-eds-with-python/#image_credits


在学习的过程中,用中文做笔记,便于日后复习,并共享给后来者参考,初学阶段,仅供参考,不保证正确性

dlib可用来做人脸检测(detect),与特征点定位(predict或align)


换脸过程:

1 检测人脸

2 得到人脸的特征点

PREDICTOR_PATH = "/home/matt/dlib-18.16/shape_predictor_68_face_landmarks.dat"detector = dlib.get_frontal_face_detector()predictor = dlib.shape_predictor(PREDICTOR_PATH)def get_landmarks(im):    rects = detector(im, 1)        if len(rects) > 1:        raise TooManyFaces    if len(rects) == 0:        raise NoFaces    return numpy.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()])

get_landmarks函数返回68个特征点(平面坐标)位置

3 贴图向原图仿射变换(旋转,对齐)

def warp_im(im, M, dshape):    output_im = numpy.zeros(dshape, dtype=im.dtype)    cv2.warpAffine(im,                   M[:2],                   (dshape[1], dshape[0]),                   dst=output_im,                   borderMode=cv2.BORDER_TRANSPARENT,                   flags=cv2.WARP_INVERSE_MAP)    return output_im
4  混合非特征点区域(面皮)

COLOUR_CORRECT_BLUR_FRAC = 0.6LEFT_EYE_POINTS = list(range(42, 48))RIGHT_EYE_POINTS = list(range(36, 42))def correct_colours(im1, im2, landmarks1):    blur_amount = COLOUR_CORRECT_BLUR_FRAC * numpy.linalg.norm(                              numpy.mean(landmarks1[LEFT_EYE_POINTS], axis=0) -                              numpy.mean(landmarks1[RIGHT_EYE_POINTS], axis=0))    blur_amount = int(blur_amount)    if blur_amount % 2 == 0:        blur_amount += 1    im1_blur = cv2.GaussianBlur(im1, (blur_amount, blur_amount), 0)    im2_blur = cv2.GaussianBlur(im2, (blur_amount, blur_amount), 0)    # Avoid divide-by-zero errors.    im2_blur += 128 * (im2_blur <= 1.0)    return (im2.astype(numpy.float64) * im1_blur.astype(numpy.float64) /                                                im2_blur.astype(numpy.float64))
高斯核建议设成虎瞳间距的0.6倍


5 混合特征点区域(眼睛,鼻子,嘴巴)


LEFT_EYE_POINTS = list(range(42, 48))RIGHT_EYE_POINTS = list(range(36, 42))LEFT_BROW_POINTS = list(range(22, 27))RIGHT_BROW_POINTS = list(range(17, 22))NOSE_POINTS = list(range(27, 35))MOUTH_POINTS = list(range(48, 61))OVERLAY_POINTS = [    LEFT_EYE_POINTS + RIGHT_EYE_POINTS + LEFT_BROW_POINTS + RIGHT_BROW_POINTS,    NOSE_POINTS + MOUTH_POINTS,]FEATHER_AMOUNT = 11def draw_convex_hull(im, points, color):    points = cv2.convexHull(points)    cv2.fillConvexPoly(im, points, color=color)def get_face_mask(im, landmarks):    im = numpy.zeros(im.shape[:2], dtype=numpy.float64)    for group in OVERLAY_POINTS:        draw_convex_hull(im,                         landmarks[group],                         color=1)    im = numpy.array([im, im, im]).transpose((1, 2, 0))    im = (cv2.GaussianBlur(im, (FEATHER_AMOUNT, FEATHER_AMOUNT), 0) > 0) * 1.0    im = cv2.GaussianBlur(im, (FEATHER_AMOUNT, FEATHER_AMOUNT), 0)    return immask = get_face_mask(im2, landmarks2)warped_mask = warp_im(mask, M, im1.shape)combined_mask = numpy.max([get_face_mask(im1, landmarks1), warped_mask],                          axis=0)

output_im = im1 * (1.0 - combined_mask) + warped_corrected_im2 * combined_mask

0 0
原创粉丝点击