环境与效果

  • python3.9.6
  • pycharm 2021

库环境:

  • dlib
  • opencv-python

视频图片效果如下:

摄像头实时换脸,老师都不认识我了!!

基本原理

  1. 使用dlib的shape_predictor_68_face_landmarks.dat模型获取一张有正脸的图片(1.png)和摄像头的自己的68个人脸特征点。
  2. 根据人脸特征点获取分别获取人脸掩模
  3. 对第一个图片仿射变换使其脸部对准摄像头图片中的脸部得到新的图片
  4. 对人脸掩模执行相同的操作仿射
  5. 将两个性的得到图取并集(不能让别的地方空了)
  6. 用opencv对两上面操作,对仿射变换后的a图片和摄像头图片进行泊松融合

完整源码

# -*- coding: utf-8 -*-import cv2
import dlib
import numpy as npdetector = dlib.get_frontal_face_detector()  # dlib的正向人脸检测器
predictor = dlib.shape_predictor(r'shape_predictor_68_face_landmarks.dat')  # dlib的人脸形状检测器def get_image_size(image):"""获取图片大小(高度,宽度):param image: image:return: (高度,宽度)"""image_size = (image.shape[0], image.shape[1])return image_sizedef get_face_landmarks(image, face_detector, shape_predictor):"""获取人脸标志,68个特征点:param image: image:param face_detector: dlib.get_frontal_face_detector:param shape_predictor: dlib.shape_predictor:return: np.array([[],[]]), 68个特征点"""dets = face_detector(image, 1)shape = shape_predictor(image, dets[0])face_landmarks = np.array([[p.x, p.y] for p in shape.parts()])return face_landmarksdef 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)points = np.concatenate([face_landmarks[0:16], face_landmarks[26:17:-1]])cv2.fillPoly(img=mask, pts=[points], color=255)return maskdef get_affine_image(image1, image2, face_landmarks1, face_landmarks2):"""获取图片1仿射变换后的图片:param image1: 图片1, 要进行仿射变换的图片:param image2: 图片2, 只要用来获取图片大小,生成与之大小相同的仿射变换图片:param face_landmarks1: 图片1的人脸特征点:param face_landmarks2: 图片2的人脸特征点:return: 仿射变换后的图片"""three_points_index = [18, 8, 25]M = cv2.getAffineTransform(face_landmarks1[three_points_index].astype(np.float32),face_landmarks2[three_points_index].astype(np.float32))dsize = (image2.shape[1], image2.shape[0])affine_image = cv2.warpAffine(image1, M, dsize)return affine_image.astype(np.uint8)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_pointdef get_mask_union(mask1, mask2):"""获取两个掩模掩盖部分的并集:param mask1: mask_image, 掩模1:param mask2: mask_image, 掩模2:return: 两个掩模掩盖部分的并集"""mask = np.min([mask1, mask2], axis=0)  # 掩盖部分并集mask = ((cv2.blur(mask, (5, 5)) == 255) * 255).astype(np.uint8)  # 缩小掩模大小mask = cv2.blur(mask, (3, 3)).astype(np.uint8)  # 模糊掩模return maskdef skin_color_adjustment(im1, im2, mask=None):"""肤色调整:param im1: 图片1:param im2: 图片2:param mask: 人脸 mask. 如果存在,使用人脸部分均值来求肤色变换系数;否则,使用高斯模糊来求肤色变换系数:return: 根据图片2的颜色调整的图片1"""if mask is None:im1_ksize = 55im2_ksize = 55im1_factor = cv2.GaussianBlur(im1, (im1_ksize, im1_ksize), 0).astype(np.float)im2_factor = cv2.GaussianBlur(im2, (im2_ksize, im2_ksize), 0).astype(np.float)else:im1_face_image = cv2.bitwise_and(im1, im1, mask=mask)im2_face_image = cv2.bitwise_and(im2, im2, mask=mask)im1_factor = np.mean(im1_face_image, axis=(0, 1))im2_factor = np.mean(im2_face_image, axis=(0, 1))im1 = np.clip((im1.astype(np.float) * im2_factor / np.clip(im1_factor, 1e-6, None)), 0, 255).astype(np.uint8)return im1def main():im1 = cv2.imread('1.png')  # face_imageim1 = cv2.resize(im1, (600, im1.shape[0] * 600 // im1.shape[1]))landmarks1 = get_face_landmarks(im1, detector, predictor)  # 68_face_landmarksif landmarks1 is None:print('{}:检测不到人脸'.format(image_face_path))exit(1)im1_size = get_image_size(im1)  # 脸图大小im1_mask = get_face_mask(im1_size, landmarks1)  # 脸图人脸掩模cam = cv2.VideoCapture(0)while True:ret_val, im2 = cam.read()  # camera_imagelandmarks2 = get_face_landmarks(im2, detector, predictor)  # 68_face_landmarksif landmarks2 is not None:im2_size = get_image_size(im2)  # 摄像头图片大小im2_mask = get_face_mask(im2_size, landmarks2)  # 摄像头图片人脸掩模affine_im1 = get_affine_image(im1, im2, landmarks1, landmarks2)  # im1(脸图)仿射变换后的图片affine_im1_mask = get_affine_image(im1_mask, im2, landmarks1, landmarks2)  # im1(脸图)仿射变换后的图片的人脸掩模union_mask = get_mask_union(im2_mask, affine_im1_mask)  # 掩模合并affine_im1 = skin_color_adjustment(affine_im1, im2, mask=union_mask)  # 肤色调整point = get_mask_center_point(affine_im1_mask)  # im1(脸图)仿射变换后的图片的人脸掩模的中心点seamless_im = cv2.seamlessClone(affine_im1, im2, mask=union_mask, p=point, flags=cv2.NORMAL_CLONE)  # 进行泊松融合cv2.imshow('seamless_im', seamless_im)else:cv2.imshow('seamless_im', im2)if cv2.waitKey(1) == 27:  # 按Esc退出breakcv2.destroyAllWindows()if __name__ == '__main__':main()

完整项目文件请看b站评论区置顶:换脸了!

摄像头实时换脸,上网课老师都不认识我了,哈哈相关推荐

  1. 利用Python实现摄像头实时换脸

    好久不见,我的朋友们,今天给大家分享的是,利用Python中cv2.dlib以及numpy等几个库,实现摄像头实时换脸的功能,先来介绍下他们吧~ 1. CV2指的是OpenCV2,OpenCV是一个基 ...

  2. 上网课的心得体会1000字_大学生上网课心得体会

    熟悉而陌生的是上网课,因为过去我们上网课都是直接学习网课视频,而现在的网课是老师直播授课,教授我们更加贴近线下授课,没有了以前网课的呆板,也没有了以前网课的枯燥,就如同一些主播一样看着老师直播. 当然 ...

  3. 计算机专业怎么上网课,大学生如何自律上网课?如何用电脑每天定时提醒上网课...

    原标题:大学生如何自律上网课?如何用电脑每天定时提醒上网课 凡事都有一个过程,对于适应在家看网络直播课学习这件事情,刘元从刚开始的手忙脚乱,已经做到可以每天自律上网课了,之所以能这么快地做到自律学习, ...

  4. 印刷体是什么意思_家长晒出4年级小学霸课前笔记,字迹堪比“印刷体”,老师都羡慕...

    目前,很多小学生都在家里上网课,为了达到最佳学习效果,要提前做好预习工作,尤其是语文这一学科,更需要预习.这不就有一位4年级学霸的家长晒出了孩子日常课前预习笔记. 他不仅对文章进行了合理的布置和预习, ...

  5. xmind怎样画流程图_老师是怎样上网课的?

    2020年注定是不平凡的一年,年后因为疫情原因不能回到课堂上课,全国大约有近3亿师生进入了"互联网上课时代".学生们在家上课,而老师被迫变成了"网红主播"每天不 ...

  6. 上网课,老师必须对家长孩子说的话

    随着社会的进步,人们的生活变得多样,同时我们会遇到各种各样的事情,尤其是上网课,老师必须对家长孩子说的话这样的问题.华罗庚说过:聪明出于勤奋,天才在于积累.那么当这种问题出现后,我们应该如何去解决呢? ...

  7. 计算机课程可在平板上做吗,老师做直播,孩子上网课,掌控线上学习就靠这个平板电脑了...

    原标题:老师做直播,孩子上网课,掌控线上学习就靠这个平板电脑了 根据移动APP行业分析平台QuestMobile的最新报告,春节假期以来,作业帮.猿辅导.学而思网课等众多在线教育APP纷纷推出了免费课 ...

  8. 老师上网课板书装备0成本解决方案

    近期因为家人有短期的上网课需求,想要搞一套网课板书装备,但又因为总共上不了几节,不想投入太多钱,所以我上网研究了下怎么弄比较省钱,最终以0成本搞定,当然前提是有些设备家里本来就有,如电脑和平板电脑,以 ...

  9. 计算机课联网,老师上网课需要什么设备

    大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答. 上网课其实要准备很多东西,除了手写板之外,你要有话筒设备,还要有摄像的设备,而且这些设备还要跟上网课的软件要结合起来.电脑的配置尽 ...

最新文章

  1. 北航云计算公开课 01 Introduction to Cloud Computing
  2. pandas为dataframe添加新的数据行(rows)、在dataframe后面纵向添加一行数据(数据为列表list形式)、列有不匹配将会使用NA值进行填补
  3. python在哪里写代码比较适合-AI辅助写代码,Python之父都爱不释手的工具
  4. [register]-ARMV8系统中通用寄存器和系统寄存器的介绍和总结
  5. web.xml中的所有配置,Listener和Filter的加载顺序
  6. 如何做好一个开源项目(一)
  7. 学计算机专业独立显卡有必要吗,不玩游戏独立显卡有什么作用_如果不玩游戏需要选择独立显卡吗-系统城...
  8. 可变大小、颜色边框、样式的UISwitch
  9. 如何在六个月或更短的时间内成为DevOps工程师(一)
  10. 安卓逆向系列教程(三)静态分析工具
  11. 无人驾驶入门(camera篇)
  12. Ubuntu 16.04 LTS安装Docker并使用加速器
  13. C++基础::Stream(二)
  14. 在Mac OS X中使用VIM开发STM32(3)
  15. Oracle之根据约束名查找表
  16. 神经网络 手写数字识别,人工智能手写数字识别
  17. 用PS调出二次元风格水彩漫画风景图片
  18. simulink简介
  19. week9 day4 CSS网页布局
  20. MyCms 自媒体 CMS 系统 v3.1.0,新增商城接口

热门文章

  1. Mysql错误:Incorrect string value: ‘\xF3\xBD\xAA\xA2/\xEF...‘ for column
  2. 千寻位置终端配置参数说明
  3. Windows10切换屏幕
  4. Linux下同时打开编辑多个文件 【VSP、vim -o】
  5. E3-1230V3和E3 1231V3有什么区别
  6. 曲面和曲线积分的概念与计算【高等数学(下)十一章】
  7. Windows 7下的Excel 2010同时打开多个独立的窗口 [转]
  8. JS学习笔记之面向对象 5.3
  9. [Spring Boot]12 ElasticSearch实现分词搜索功能
  10. spring cloud-使用Hystrix实现单个方法的fallback