简单换脸、人脸对齐、关键点定位与画图
这是一个利用dlib进行关键点定位 + opencv处理的人脸对齐、换脸、关键点识别的小demo。原文来自于《Switching Eds: Face swapping with Python, dlib, and OpenCV》 该博文的github地址中有所有的code。这边我的博客地址: http://blog.csdn.net/sinat_26917383/article/details/78564416
有人将其进行中文翻译也有将其进行一定改编有以下两个案例:
因为原文里面内容丰富,我觉得可以提取出很多有用的小模块,于是乎: .
import cv2
import dlib
import numpy
import sys
import matplotlib.pyplot as plt
SCALE_FACTOR = 1 # 图像的放缩比
def read_im_and_landmarks(fname):
im = cv2.imread(fname, cv2.IMREAD_COLOR)
im = cv2.resize(im, (im.shape[1] * SCALE_FACTOR,
im.shape[0] * SCALE_FACTOR))
s = get_landmarks(im)
return im, s
def annotate_landmarks(im, landmarks):
'''
人脸关键点,画图函数
'''
im = im.copy()
for idx, point in enumerate(landmarks):
pos = (point[0, 0], point[0, 1])
cv2.putText(im, str(idx), pos,
fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
fontScale=0.4,
color=(0, 0, 255))
cv2.circle(im, pos, 3, color=(0, 255, 255))
return im
然后实践就是载入原图:
im1, landmarks1 = read_im_and_landmarks('02.jpg') # 底图
im1 = annotate_landmarks(im1, landmarks1)
%matplotlib inline
plt.subplot(111)
plt.imshow(im1)
.
需要一张模板图来作为靠拢的对象图。
# 人脸对齐函数
def face_Align(Base_path,cover_path):
im1, landmarks1 = read_im_and_landmarks(Base_path) # 底图
im2, landmarks2 = read_im_and_landmarks(cover_path) # 贴上来的图
if len(landmarks1) == 0 & len(landmarks2) == 0 :
raise ImproperNumber("Faces detected is no face!")
if len(landmarks1) > 1 & len(landmarks2) > 1 :
raise ImproperNumber("Faces detected is more than 1!")
M = transformation_from_points(landmarks1[ALIGN_POINTS],
landmarks2[ALIGN_POINTS])
warped_im2 = warp_im(im2, M, im1.shape)
return warped_im2
- 提取模板图、对齐图的landmarks;
- 通过transformation_from_points计算对齐图向模板图的转移矩阵M,变换矩阵是根据以下公式计算出来的;
- warp_im,将 im2 的掩码进行变化,使之与 im1 相符
实践的话就是:
FEATHER_AMOUNT = 19 # 匹配的时候,特征数量,现在是以11个点为基准点 11 15 17
Base_path = '01.jpg'
cover_path = '02.jpg'
warped_mask = face_Align(Base_path,cover_path)
.
主要函数:
def Switch_face(Base_path,cover_path):
im1, landmarks1 = read_im_and_landmarks(Base_path) # 底图
im2, landmarks2 = read_im_and_landmarks(cover_path) # 贴上来的图
if len(landmarks1) == 0 & len(landmarks2) == 0 :
raise ImproperNumber("Faces detected is no face!")
if len(landmarks1) > 1 & len(landmarks2) > 1 :
raise ImproperNumber("Faces detected is more than 1!")
M = transformation_from_points(landmarks1[ALIGN_POINTS],
landmarks2[ALIGN_POINTS])
mask = 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)
warped_im2 = warp_im(im2, M, im1.shape)
warped_corrected_im2 = correct_colours(im1, warped_im2, landmarks1)
output_im = im1 * (1.0 - combined_mask) + warped_corrected_im2 * combined_mask
return output_im
- 提取模板图、对齐图的landmarks;
- M,通过transformation_from_points计算对齐图向模板图的转移矩阵M;
matrix([[ 0.62876962, 0.20978991, -101.32973923],
[ -0.20978991, 0.62876962, 79.11235991],
[ 0. , 0. , 1. ]])
-
warped_mask ,warp_im函数,将 im2 的掩码进行变化,使之与 im1 相符,跟上面的mask张一样(一个鼻子)
-
combined_mask ,将二者的掩码进行连通(跟warped_mask 长一样)
-
warped_im2 ,warp_im函数,第二次,将第二幅图像调整到与第一幅图像相符(对齐图片,斜了点)
-
warped_corrected_im2 ,correct_colours函数,将 im2 的皮肤颜色进行修正,使其和 im1 的颜色尽量协调(类似下图)
-
output_im 组合图像,获得结果
实践:
FEATHER_AMOUNT = 23
Base_path = '03.jpg'
cover_path = '02.jpg'
output_im = Switch_face(Base_path,cover_path)
py代码以及相关数据地址:https://www.learnopencv.com/wp-content/uploads/2016/05/FaceAverage.zip 最初博文地址:https://www.learnopencv.com/average-face-opencv-c-python-tutorial/ 中文翻译:http://blog.csdn.net/GraceDD/article/details/51382952 中文改编地址:《手把手:用OpenCV亲手给小扎、Musk等科技大佬们做一张“平均脸”(附Python代码)》
在完成各个library的安装后。
- 第一步:将要平均的照片放入faces文档,确保图片为jpg格式。
- 第二步:在终端运行 python face_landmark_detection.py shape_predictor_68_face_landmarks.dat faces,并在程序运行结束后将所有faces文档中的文件复制到presidents文档中(如无法完成dlib安装,可略过该步骤,直接用文摘菌提供的素材)
- 第三步:在终端运行 python faceAverage.py 这样就能看到制作成功的平均脸了!
具体实现步骤: