百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Python摄像头换脸,现实版“易容术”重现江湖

toyiye 2024-06-21 11:55 11 浏览 0 评论

环境与效果

  • python3.9.6
  • pycharm 2021

库环境:

  • dlib
  • opencv-python

视频图片效果如下:

基本原理

使用dlib的shape_predictor_68_face_landmarks.dat模型获取一张有正脸的图片(1.png)和摄像头的自己的68个人脸特征点。

根据人脸特征点获取分别获取人脸掩模

对第一个图片仿射变换使其脸部对准摄像头图片中的脸部得到新的图片

对人脸掩模执行相同的操作仿射

将两个性的得到图取并集(不能让别的地方空了)

用opencv对两上面操作,对仿射变换后的a图片和摄像头图片进行泊松融合

完整源码

# -*- coding: utf-8 -*-
import cv2
import dlib
import numpy as np
detector = 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_size
def 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_landmarks
def 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 mask
def 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_point
def 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 mask
def 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 = 55
im2_ksize = 55
im1_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 im1
def main():
im1 = cv2.imread('1.png') # face_image
im1 = cv2.resize(im1, (600, im1.shape[0] * 600 // im1.shape[1]))
landmarks1 = get_face_landmarks(im1, detector, predictor) # 68_face_landmarks
if 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_image
landmarks2 = get_face_landmarks(im2, detector, predictor) # 68_face_landmarks
if 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退出
break
cv2.destroyAllWindows()
if __name__ == '__main__':
main()


完整项目文件私信回复“333”,可直接分享

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码