换脸步骤:
文章图片
# coding=utf-8
import cv2
import dlib
import os
import numpy as np
import globclass NoFace(Exception):
pass
class Facechanger(object):def __init__(self,which_predictor = '68',windowname = ' exchange face'):
self.current_path = os.getcwd()
self.predictor_68_path = self.current_path + "\shape_predictor_68_face_landmarks.dat"
self.predictor_5_points_path = self.current_path + "\shape_predictor_5_face_landmarks.dat"
self.detector = dlib.get_frontal_face_detector()
self.predictor= dlib.shape_predictor(self.predictor_68_path)self.SCALE_FACTOR = 1
self.FEATHER_AMOUNT = 11
self.COLOUR_CORRECT_BLUR_FRAC = 0.6self.FACE_POINTS = list(range(17, 68))
self.MOUTH_POINTS = list(range(48, 61))
self.RIGHT_BROW_POINTS = list(range(17, 22))
self.LEFT_BROW_POINTS = list(range(22, 27))
self.RIGHT_EYE_POINTS = list(range(36, 42))
self.LEFT_EYE_POINTS = list(range(42, 48))
self.NOSE_POINTS = list(range(27, 35))
self.JAW_POINTS = list(range(0, 17))
self.ALIGN_POINTS = (self.LEFT_BROW_POINTS + self.RIGHT_EYE_POINTS + self.LEFT_EYE_POINTS +
self.RIGHT_BROW_POINTS + self.NOSE_POINTS + self.MOUTH_POINTS)
self.OVERLAY_POINTS = [self.LEFT_BROW_POINTS + self.RIGHT_EYE_POINTS + self.LEFT_EYE_POINTS +
self.RIGHT_BROW_POINTS + self.NOSE_POINTS + self.MOUTH_POINTS]cv2.namedWindow(windowname,cv2.WINDOW_AUTOSIZE)self.windowname = windownameself.cap = cv2.VideoCapture(0)def det_landmark(self):
#dets = self.detector(self.frame,1)
face1 = self.dets[0]
face2 = self.dets[1]
return face1, face2def matrix(self,image,face):
return np.matrix([[p.x, p.y] for p in self.predictor(image, face).parts()])def transformation_from_points(self,points1,points2):
points1 = points1.astype(np.float64)
points2 = points2.astype(np.float64)c1 = np.mean(points1, axis=0)
c2 = np.mean(points2, axis=0)
points1 -= c1
points2 -= c2s1 = np.std(points1)
s2 = np.std(points2)
points1 /= s1
points2 /= s2U, S, Vt = np.linalg.svd(points1.T * points2)
R = (U * Vt).Treturn np.vstack([np.hstack(((s2 / s1) * R, c2.T - (s2 / s1) * R * c1.T)), np.matrix([0., 0., 1.])])def warp_image(self, image, M, dshape):
output_image = np.zeros(dshape, dtype=image.dtype)
cv2.warpAffine(image, M[:2], (dshape[1], dshape[0]), dst=output_image, flags=cv2.WARP_INVERSE_MAP,
borderMode=cv2.BORDER_TRANSPARENT)
return output_imagedef correct_colours(self, im1, im2, landmarks1):#颜色调整
blur_amount = self.COLOUR_CORRECT_BLUR_FRAC * np.linalg.norm(
np.mean(landmarks1[self.LEFT_EYE_POINTS], axis=0) -
np.mean(landmarks1[self.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)im2_blur += (128 * (im2_blur <= 1.0)).astype(im2_blur.dtype)return (im2.astype(np.float64) * im1_blur.astype(np.float64) /
im2_blur.astype(np.float64))def draw_convex_hull(self, img, points, color):
points = cv2.convexHull(points)
cv2.fillConvexPoly(img, points, color)def get_face_mask(self, img, landmarks):#获取掩膜
img = np.zeros(img.shape[:2], dtype=np.float64)
for group in self.OVERLAY_POINTS:
self.draw_convex_hull(img, landmarks[group], color=1)img = np.array([img, img, img]).transpose((1, 2, 0)) #变成 图片的原来格式(最后一维是三通道的)img = (cv2.GaussianBlur(img, (self.FEATHER_AMOUNT, self.FEATHER_AMOUNT), 0) > 0) * 1.0
img = cv2.GaussianBlur(img, (self.FEATHER_AMOUNT, self.FEATHER_AMOUNT), 0)return imgdef run(self):
while True:
ret,self.frame1 = self.cap.read()if ret is True:
b, g, r = cv2.split(self.frame1)# 分离色道 opencv读入的色道是B,G,R
self.frame = cv2.merge([r, g, b])# 合成R,G,B
self.dets = self.detector(self.frame, 1)
if len(self.dets) ==1:
cv2.imshow(self.windowname, self.frame1)
k = cv2.waitKey(5)
if k & 0XFF == ord('q'):
breakelif len(self.dets) ==2:self.face1,self.face2 = self.det_landmark()
self.point1 = self.matrix(self.frame1,self.face1)
self.point2 = self.matrix(self.frame1,self.face2)
self.mask1 = self.get_face_mask(self.frame1,self.point1)
self.mask2 = self.get_face_mask(self.frame1,self.point2)self.tran1 = self.transformation_from_points(self.point1[self.ALIGN_POINTS],self.point2[self.ALIGN_POINTS])
self.tran2 = self.transformation_from_points(self.point2[self.ALIGN_POINTS],self.point1[self.ALIGN_POINTS])
self.warped_mask1 = self.warp_image(self.mask2,self.tran1,self.frame1.shape)
self.warped_mask2 = self.warp_image(self.mask1, self.tran2, self.frame1.shape)
self.conbined_mask1 = np.max([self.mask1,self.warped_mask1],axis=0)
self.conbined_mask2 = np.max([self.mask2,self.warped_mask2],axis=0)
self.warped_img2 = self.warp_image(self.frame1,self.tran1,self.frame1.shape)
self.warped_img1 = self.warp_image(self.frame1, self.tran2, self.frame1.shape)
self.warped_corrected_img2 = self.correct_colours(self.frame1,self.warped_img2,self.point1)
self.warped_corrected_img2_temp = np.zeros(self.warped_corrected_img2.shape,dtype=self.warped_corrected_img2.dtype)
self.warped_corrected_img1 = self.correct_colours(self.frame1, self.warped_img1, self.point2)
self.warped_corrected_img1_temp = np.zeros(self.warped_corrected_img1.shape,
dtype=self.warped_corrected_img1.dtype)
#cv2.normalize(self.warped_corrected_img2, self.warped_corrected_img2_temp, 0, 1, cv2.NORM_MINMAX)
#cv2.normalize(self.warped_corrected_img1, self.warped_corrected_img1_temp, 0, 1, cv2.NORM_MINMAX)
self.output = self.frame1*(1.0-self.conbined_mask1) + self.warped_corrected_img2*self.conbined_mask1
self.output = self.output * (
1.0 - self.conbined_mask2) + self.warped_corrected_img1 * self.conbined_mask2
cv2.normalize(self.output,self.output,0,1,cv2.NORM_MINMAX)
cv2.imshow(self.windowname,self.output.astype(self.output.dtype))
k = cv2.waitKey(5)
if k & 0XFF == ord('q'):
break
self.cap.release()
cv2.destroyAllWindows()if __name__ == '__main__':
corrrent = Facechanger(which_predictor = '68',windowname = ' exchange face')
corrrent.run()
大部分代码参考原PO:https://blog.csdn.net/hongbin_xu/article/details/78878745
transformation_from_points(self,points1,points2):普什分析,仿射变换得到矩阵可以参考:
https://en.wikipedia.org/wiki/Orthogonal_Procrustes_problem
https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations
文章图片
【python+opencv|python dlib实现小程序(4)实现换脸】
文章图片
推荐阅读
- 人脸识别|【人脸识别系列】| 实现自动化妆
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍