Python进阶——网课不愁系列AI换脸技术

举报
nimo的小舔狗 发表于 2022/05/10 23:34:11 2022/05/10
【摘要】 俗话说的好:网络一线牵,珍惜这段缘! 网络的水很深,年轻人你把握不住,众所周知照片是可以P的,但是“视频”是“P”不了的(狗头保命) 谁能想到AI换脸竟然如此便捷,在Python上小小拟合就可以完成实时视频换脸。 请允许我小声介绍一下dlib库: Dlib是一个现代化的C ++工具箱,其中包含用于在C ++中创建复杂软...

俗话说的好:网络一线牵,珍惜这段缘!
网络的水很深,年轻人你把握不住,众所周知照片是可以P的,但是“视频”是“P”不了的(狗头保命)

谁能想到AI换脸竟然如此便捷,在Python上小小拟合就可以完成实时视频换脸

请允许我小声介绍一下dlib库:

Dlib是一个现代化的C ++工具箱,其中包含用于在C ++中创建复杂软件以解决实际问题的机器学习算法和工具。它广泛应用于工业界和学术界,包括机器人,嵌入式设备,移动电话和大型高性能计算环境。Dlib的开源许可证 允许您在任何应用程序中免费使用它。

Dlib有很长的时间,包含很多模块,近几年作者主要关注在机器学习、深度学习、图像处理等模块的开发。

先看看效果图: 

毫无违和感(就当作毫无违和感吧,人丑不普信别骂~🐕)

上代码:


  
  1. # -*- coding: utf-8 -*-
  2. import cv2
  3. import dlib
  4. import numpy as np
  5. detector = dlib.get_frontal_face_detector() # dlib的正向人脸检测器
  6. predictor = dlib.shape_predictor(r'shape_predictor_68_face_landmarks.dat') # dlib的人脸形状检测器
  7. def get_image_size(image):
  8. """
  9. 获取图片大小(高度,宽度)
  10. :param image: image
  11. :return: (高度,宽度)
  12. """
  13. image_size = (image.shape[0], image.shape[1])
  14. return image_size
  15. def get_face_landmarks(image, face_detector, shape_predictor):
  16. """
  17. 获取人脸标志,68个特征点
  18. :param image: image
  19. :param face_detector: dlib.get_frontal_face_detector
  20. :param shape_predictor: dlib.shape_predictor
  21. :return: np.array([[],[]]), 68个特征点
  22. """
  23. dets = face_detector(image, 1)
  24. shape = shape_predictor(image, dets[0])
  25. face_landmarks = np.array([[p.x, p.y] for p in shape.parts()])
  26. return face_landmarks
  27. def get_face_mask(image_size, face_landmarks):
  28. """
  29. 获取人脸掩模
  30. :param image_size: 图片大小
  31. :param face_landmarks: 68个特征点
  32. :return: image_mask, 掩模图片
  33. """
  34. mask = np.zeros(image_size, dtype=np.uint8)
  35. points = np.concatenate([face_landmarks[0:16], face_landmarks[26:17:-1]])
  36. cv2.fillPoly(img=mask, pts=[points], color=255)
  37. return mask
  38. def get_affine_image(image1, image2, face_landmarks1, face_landmarks2):
  39. """
  40. 获取图片1仿射变换后的图片
  41. :param image1: 图片1, 要进行仿射变换的图片
  42. :param image2: 图片2, 只要用来获取图片大小,生成与之大小相同的仿射变换图片
  43. :param face_landmarks1: 图片1的人脸特征点
  44. :param face_landmarks2: 图片2的人脸特征点
  45. :return: 仿射变换后的图片
  46. """
  47. three_points_index = [18, 8, 25]
  48. M = cv2.getAffineTransform(face_landmarks1[three_points_index].astype(np.float32),
  49. face_landmarks2[three_points_index].astype(np.float32))
  50. dsize = (image2.shape[1], image2.shape[0])
  51. affine_image = cv2.warpAffine(image1, M, dsize)
  52. return affine_image.astype(np.uint8)
  53. def get_mask_center_point(image_mask):
  54. """
  55. 获取掩模的中心点坐标
  56. :param image_mask: 掩模图片
  57. :return: 掩模中心
  58. """
  59. image_mask_index = np.argwhere(image_mask > 0)
  60. miny, minx = np.min(image_mask_index, axis=0)
  61. maxy, maxx = np.max(image_mask_index, axis=0)
  62. center_point = ((maxx + minx) // 2, (maxy + miny) // 2)
  63. return center_point
  64. def get_mask_union(mask1, mask2):
  65. """
  66. 获取两个掩模掩盖部分的并集
  67. :param mask1: mask_image, 掩模1
  68. :param mask2: mask_image, 掩模2
  69. :return: 两个掩模掩盖部分的并集
  70. """
  71. mask = np.min([mask1, mask2], axis=0) # 掩盖部分并集
  72. mask = ((cv2.blur(mask, (5, 5)) == 255) * 255).astype(np.uint8) # 缩小掩模大小
  73. mask = cv2.blur(mask, (3, 3)).astype(np.uint8) # 模糊掩模
  74. return mask
  75. def skin_color_adjustment(im1, im2, mask=None):
  76. """
  77. 肤色调整
  78. :param im1: 图片1
  79. :param im2: 图片2
  80. :param mask: 人脸 mask. 如果存在,使用人脸部分均值来求肤色变换系数;否则,使用高斯模糊来求肤色变换系数
  81. :return: 根据图片2的颜色调整的图片1
  82. """
  83. if mask is None:
  84. im1_ksize = 55
  85. im2_ksize = 55
  86. im1_factor = cv2.GaussianBlur(im1, (im1_ksize, im1_ksize), 0).astype(np.float)
  87. im2_factor = cv2.GaussianBlur(im2, (im2_ksize, im2_ksize), 0).astype(np.float)
  88. else:
  89. im1_face_image = cv2.bitwise_and(im1, im1, mask=mask)
  90. im2_face_image = cv2.bitwise_and(im2, im2, mask=mask)
  91. im1_factor = np.mean(im1_face_image, axis=(0, 1))
  92. im2_factor = np.mean(im2_face_image, axis=(0, 1))
  93. im1 = np.clip((im1.astype(np.float) * im2_factor / np.clip(im1_factor, 1e-6, None)), 0, 255).astype(np.uint8)
  94. return im1
  95. def main():
  96. im1 = cv2.imread('1.png') # face_image
  97. im1 = cv2.resize(im1, (600, im1.shape[0] * 600 // im1.shape[1]))
  98. landmarks1 = get_face_landmarks(im1, detector, predictor) # 68_face_landmarks
  99. if landmarks1 is None:
  100. print('{}:检测不到人脸'.format(image_face_path))
  101. exit(1)
  102. im1_size = get_image_size(im1) # 脸图大小
  103. im1_mask = get_face_mask(im1_size, landmarks1) # 脸图人脸掩模
  104. cam = cv2.VideoCapture(0)
  105. while True:
  106. ret_val, im2 = cam.read() # camera_image
  107. landmarks2 = get_face_landmarks(im2, detector, predictor) # 68_face_landmarks
  108. if landmarks2 is not None:
  109. im2_size = get_image_size(im2) # 摄像头图片大小
  110. im2_mask = get_face_mask(im2_size, landmarks2) # 摄像头图片人脸掩模
  111. affine_im1 = get_affine_image(im1, im2, landmarks1, landmarks2) # im1(脸图)仿射变换后的图片
  112. affine_im1_mask = get_affine_image(im1_mask, im2, landmarks1, landmarks2) # im1(脸图)仿射变换后的图片的人脸掩模
  113. union_mask = get_mask_union(im2_mask, affine_im1_mask) # 掩模合并
  114. affine_im1 = skin_color_adjustment(affine_im1, im2, mask=union_mask) # 肤色调整
  115. point = get_mask_center_point(affine_im1_mask) # im1(脸图)仿射变换后的图片的人脸掩模的中心点
  116. seamless_im = cv2.seamlessClone(affine_im1, im2, mask=union_mask, p=point, flags=cv2.NORMAL_CLONE) # 进行泊松融合
  117. cv2.imshow('seamless_im', seamless_im)
  118. else:
  119. cv2.imshow('seamless_im', im2)
  120. if cv2.waitKey(1) == 27: # 按Esc退出
  121. break
  122. cv2.destroyAllWindows()
  123. if __name__ == '__main__':
  124. main()

要是dlib库有问题可在连接中下载:python人脸识别环境下的两个dlib适配包,一个配合python3.7,一个配合python3.8-机器学习文档类资源-CSDN下载

(已设置免费) 

全部代码资源:

链接:https://pan.baidu.com/s/1CW1wC7XtzGWKyhNlfakEPQ 
提取码:0329

文章来源: blog.csdn.net,作者:渣渣ye,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/yyfloveqcw/article/details/123828306

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。