[Python图像处理] 换脸(face swapping)操作实践

换脸操作实践

    • 换脸 (face swapping)
    • 换脸操作实现
    • 相关链接

换脸 (face swapping)

换脸是指照片中的人脸自动替换:将一个人脸的某些部分与另一个人脸的其他部分相结合以形成新的面部图像。它可以被视为另一种类型的面部融合技术。在本节中,我们将使用面部关键点和单应性来实现换脸操作。

换脸操作实现

(1) 导入所有必需的库:

import cv2
import dlib
import numpy as np
import matplotlib.pylab as plt
import imutils

(2) 使用人脸检测器从输入面部图像中检测面部边界框,然后使用形状预测器从每个输入图像中提取 68 个面部关键点。我们需要使用除下颌线以外的所有关键点(关键点 17-68),并定义用于面部融合的的其他常量(羽化值、颜色校正模糊):

predictor_path = "models/shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)feather_amount = 11
color_correction_blur = 0.5keypoints = list(range(17,68))
left_eye_points, right_eye_points = list(range(42,48)), list(range(36,42))

可以在 GitCode 中下载 shape_predictor_68_face_landmarks.dat 文件。

(3) 定义函数 draw_convex_hull() 以在给定图像上的给定点集周围以给定颜色绘制凸包:

def draw_convex_hull(im, points, color):points = cv2.convexHull(points)cv2.fillConvexPoly(im, points, color=color)

(4) 定义函数 get_landmarks() 通过使用形状预测器返回给定图像的面部关键点:

def get_landmarks(img):    rects = detector(img, 0)if len(rects) == 0:return -1return np.array([[p.x, p.y] for p in predictor(img, rects[0]).parts()])

(5) 定义函数 get_face_mask() 返回给定面部图像和面部标志的掩码,在关键点周围绘制一个填充的凸包(用白色填充),使区域平滑,并返回结果:

def get_face_mask(im, landmarks):im = np.zeros(im.shape[:2], dtype=np.float64)for group in [keypoints]:draw_convex_hull(im, landmarks[group], color=1)im = np.array([im, im, im]).transpose((1, 2, 0))im = cv2.GaussianBlur(im, (feather_amount, feather_amount), 0) > 0im = im * 1.0im = cv2.GaussianBlur(im, (feather_amount, feather_amount), 0)return im

(6) 定义函数 correct_colours() 根据给定的第一张面部图片和关键点校正扭曲的第二张面部图像的颜色。使用第一图像中眼睛的平均色差的范数来计算模糊量,校正扭曲的第二张图像面部颜色以匹配第一张图片的面部颜色:

def correct_colours(im1, im2, landmarks1):mean_left = np.mean(landmarks1[left_eye_points], axis=0)mean_right = np.mean(landmarks1[right_eye_points], axis=0)blur_amount = color_correction_blur * np.linalg.norm(mean_left - mean_right)blur_amount = int(blur_amount)if blur_amount % 2 == 0: # make the blur kernel size oddblur_amount += 1im1_blur = cv2.GaussianBlur(im1, (blur_amount, blur_amount), 0)im2_blur = cv2.GaussianBlur(im2, (blur_amount, blur_amount), 0)# avoid division errorsim2_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))

(7) 定义函数 plot_image_landmarks() 绘制输入图像上的关键点:

def plot_image_landmarks(img, img_landmarks, swap_img, swap_img_landmarks):img = img.copy()for mark in img_landmarks.tolist():cv2.circle(img, (mark[0], mark[1]), 1, (0,0,255), 2, cv2.LINE_AA)swap_img = swap_img.copy()for mark in swap_img_landmarks.tolist():cv2.circle(swap_img, (mark[0], mark[1]), 1, (0,0,255), 2, cv2.LINE_AA)        plt.figure(figsize=(15,10))plt.subplots_adjust(0,0,1,0.95,0.01,0.01)plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.axis('off')plt.subplot(122), plt.imshow(cv2.cvtColor(swap_img.astype(np.uint8), cv2.COLOR_BGR2RGB)), plt.axis('off')plt.suptitle('Facial landmarks computed for the faces to be swapped (with dlib shape-predictor)', size=10)plt.show()

(8) 最后,定义函数 face_swap_filter() 执行换脸操作,此函数接受两个输入面部图像文件,并使用第二个图像中的面部替换第一个图像的面部。首先,提取并绘制面部关键点;使用 cv2.findHomography() 函数,使用图像中的关键点计算投影变换的单应性矩阵(用于将第二张图像的面部投影到第一张图像的面部上);使用单应性矩阵计算并扭曲来自第二张图像的面部掩码;此外,通过使用单应性矩阵将第二张图像的面部扭曲映射到到第一张图像上;最后,使用掩码组合第一张图像和扭曲后的第二张图像,并进行颜色校正:

def face_swap_filter(img_file, swap_img_file):img = imutils.resize(cv2.imread(img_file), width=400)swap_img = imutils.resize(cv2.imread(swap_img_file), width=400)img_landmarks = get_landmarks(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))swap_img_landmarks = get_landmarks(cv2.cvtColor(swap_img, cv2.COLOR_BGR2GRAY))plot_image_landmarks(img, img_landmarks, swap_img, swap_img_landmarks)Hmat, status = cv2.findHomography(swap_img_landmarks[keypoints], img_landmarks[keypoints])mask = get_face_mask(swap_img, swap_img_landmarks)warped_mask = cv2.warpPerspective(mask, Hmat, (img.shape[1], img.shape[0]))combined_mask = np.max([get_face_mask(img, img_landmarks), warped_mask], axis=0)    warped_swap = cv2.warpPerspective(swap_img, Hmat, (img.shape[1], img.shape[0]))output_img = np.clip(img * (1.0 - combined_mask) + warped_swap * combined_mask, 0, 255)warped_corrected_swap = correct_colours(img, warped_swap, img_landmarks)output_img_corrected = np.clip(img * (1.0 - combined_mask) + warped_corrected_swap * combined_mask, 0, 255)return (output_img, output_img_corrected)

(9) 绘制输出图像,即用第二张图像中的面部替换的第一张图像中的面部:

output_img, output_img_corrected = face_swap_filter('1.png', '2.png')plt.figure(figsize=(15,10))
plt.subplots_adjust(0,0,1,0.925,0.01,0.01)
plt.subplot(121), plt.imshow(cv2.cvtColor(output_img.astype(np.uint8), cv2.COLOR_BGR2RGB)), plt.axis('off')
plt.title('Before color correction', size=10)
plt.subplot(122), plt.imshow(cv2.cvtColor(output_img_corrected.astype(np.uint8), cv2.COLOR_BGR2RGB)), plt.axis('off')
plt.title('After color correction', size=10)
plt.suptitle('Face Swapping Output', size=12)
plt.show()

关键点检测
换脸结果

相关链接

Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊
Python图像处理【12】基于小波变换执行图像去噪
Python图像处理【13】使用PIL执行图像降噪
Python图像处理【14】基于非线性滤波器的图像去噪
Python图像处理【15】基于非锐化掩码锐化图像
Python图像处理【16】OpenCV直方图均衡化
Python图像处理【17】指纹增强和细节提取
Python图像处理【18】边缘检测详解
Python图像处理【19】基于霍夫变换的目标检测
Python图像处理【20】图像金字塔
Python图像处理【21】基于卷积神经网络增强微光图像
Python图像处理【22】基于卷积神经网络的图像去雾
Python图像处理【23】分布式图像处理
Python图像处理【24】面部变形(face morphing)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计网】TCP中的滑动窗口

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 正文 工作原理如下&#xff1a; 结语 我的其他博客 正文 TCP&#xff08;传输控制协议&#xff09;中的滑动窗口是一种用于流量控制和拥…

数学建模——线性回归模型

目录 1.线性回归模型的具体步骤和要点&#xff1a; 1.收集数据&#xff1a; 2.探索性数据分析&#xff1a; 3.选择模型&#xff1a; 4.拟合模型&#xff1a; 5.评估模型&#xff1a; 1.R平方&#xff08;R-squared&#xff09;&#xff1a; 2.调整R平方&#xff08;Ad…

【教程向】从零开始创建浏览器插件(四)探索Chrome扩展的更多常用API

探索Chrome扩展的更多常用API 在Chrome扩展开发中&#xff0c;除了最基础的API外&#xff0c;Chrome还提供了一系列强大的API&#xff0c;允许开发者与浏览器的各种功能进行交互。本文将介绍其中几个常用的API&#xff0c;并提供详细的示例代码帮助您开始利用这些API。 书签…

JavaScript进阶——05-迭代器和生成器【万字长文,感谢支持】

迭代器 概念 迭代器&#xff08;Iterator&#xff09;是 JavaScript 中一种特殊的对象&#xff0c;它提供了一种统一的、通用的方式遍历个各种不同类型的数据结构。可以遍历的数据结构包括&#xff1a;数组、字符串、Set、Map 等可迭代对象。我们也可以自定义实现迭代器&…

【class8】人工智能初步(图像识别-----卷积神经网络)

上节回顾 上节课&#xff0c;我们简单了解了图像识别和深度学习的相关知识。 快速回顾一下吧&#xff5e; A图像识别是以图像的主要特征为基础的。B. 图像分辨率决定图像的质量。 C&#xff0e; 像素是图像中的最小单位D. 在图像识别的原理上&#xff0c;计算机和人类在本质…

面试加分项:精通Java高并发下的锁优化策略

1. 问题背景与挑战 1.1 并发编程中的挑战 在现代软件开发中&#xff0c;高并发已成为衡量系统质量的一项关键因素&#xff0c;特别是对于那些需要同时处理数以万计甚至百万级用户请求的服务。并发编程的挑战在于如何有效地同步多个线程&#xff0c;确保数据的一致性和系统的稳…

3ds Max与Maya不同之处?两者哪个更适合云渲染?

3ds Max 和 Maya 都是知名的3D软件&#xff0c;各有其特色。3ds Max 以直观的建模和丰富的插件生态闻名&#xff1b;Maya 则在动画和角色创作方面更为出色。两者都支持云渲染技术&#xff0c;能帮助用户在云端高效完成项目。 一、3ds Max和Maya之间的主要区别&#xff1a; 3ds…

短视频的拍摄方式有哪些:四川京之华锦信息技术公司

创意与技术并存的艺术之旅 在数字媒体高速发展的今天&#xff0c;短视频已经成为人们获取信息、表达情感、展示才艺的重要窗口。从社交平台到新闻资讯&#xff0c;再到教育娱乐&#xff0c;短视频无处不在&#xff0c;其独特的魅力和广泛的传播力让人们对它的拍摄方式产生了浓…

全像宇宙投影第三部时间与空间(全文)下载

当这个人向空中凝视时&#xff0c;他所在的房间渐渐变得透明而朦胧&#xff0c;空中渐渐浮现一个久远前景像。突然他觉得自己在皇宫中庭内&#xff0c;他面前站著一位年轻女士非常美丽&#xff0c;有著橄榄色的皮肤。他可以见到她的颈项、手腕、脚踝上都挂著金饰&#xff0c;还…

df 中的 NoneType、空和 None

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 目录 简介什么是 NoneType&#xff1f;什么是空&#xff08;Empty&#xff09;&#xff1f;什么是 None&#xff1f;Python 中如何判断 NoneType&#xff1f;Pandas DataFrame 中的 NoneType、空和 None实操&#x…

HIVE大数据平台SQL优化分享

相信很多小伙伴在面试的时候&#xff0c;必然跳不过去的一个问题就是SQL脚本的优化&#xff0c;这是很多面试官爱问的问题&#xff0c;也是可以证明你实力进阶的一个重要的能力。 下面给大家分享一个重量级的大数据行业sql技能---hive大数据平台SQL优化。 此文章是大数据平台…

TimesFM: 预训练的时间序列基础模型

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在阅读过程中有些知识点存在盲区&#xff0c;可以回到如何优雅的谈论大模型重新阅读。另外斯坦福2024人工智能报告解读为通识性读物。若对于如果…

Ajax额

原生Ajax xml 已被json取代 http 请求方法urlhttp版本号 network 谷歌浏览器查看请求报文和响应报文 F12 network header里面有 请求头 响应头 点击view source 可以查看请求响应行 请求体在请求行头下面 get请求有url参数&#xff0c;请求体变为query String…

网络传输,请每次都开启 TCP_NODELAY

原文&#xff1a;Marc Brooker - 2024.05.09 &#xff08;注&#xff1a;不必过于担心这个问题&#xff0c;大部分现代库&#xff0c;语言&#xff08;如 Go&#xff09;&#xff0c;代理&#xff08;如 Envoy&#xff09;&#xff0c;都默认设置了 TCP_NODELAY。如果遇到网络…

AIGC数字人视频创作平台,赋能企业常态化制作数字内容营销

随着数字人技术不断发展&#xff0c;AIGC、元宇宙等相关产业迅速发展&#xff0c;企业通过3D虚拟数字人定制&#xff0c;打造出专属的数字人作为企业与用户沟通的新桥梁。 作为3D、AI数字人技术服务商及方案提供商&#xff0c;广州虚拟动力一直致力于为各领域企业通过3D虚拟数字…

Franz Electron + React 源码启动运行填坑指南

环境要求 安装miniconda python 环境electron/rebuild用得着&#xff0c;miniconda 默认自带的 python 是 3.11 版本&#xff0c;比较新&#xff1b; 安装virsual studio 2019 要把C桌面相关的都安装了&#xff0c;大概需要20G&#xff0c;不要安装到 C 盘&#xff0c;都安装到…

【C++】认识C++(上)

目录 从C到C命名空间同名冲突命名空间的定义命名空间的使用 C的输入和输出缺省参数&#xff08;默认参数&#xff09; 从C到C C语言的出现是计算机科学和工程史上的一个重要里程碑&#xff0c;许多现代计算机语言都受C语言的影响。C语言是面向过程的&#xff0c;结构化和模块化…

力扣HOT100 - 279. 完全平方数

解题思路&#xff1a; 动态规划 class Solution {public int numSquares(int n) {int[] dp new int[n 1];// 初始化dp数组&#xff0c;默认最坏情况是每个数都是由1相加得到的for (int i 1; i < n; i) {dp[i] i;}for (int i 1; i < n; i) {for (int j 1; j * j &…

Python Twisted库:异步网络编程的利器

更多Python学习内容&#xff1a;ipengtao.com 在现代网络应用开发中&#xff0c;异步编程已经成为一种必备的技能。Python Twisted库是一款强大的异步网络编程框架&#xff0c;它提供了丰富的工具和功能&#xff0c;使得开发者可以轻松地构建高性能的网络应用。 基本概念 Twist…

在虚机VirtualBox7.0.8安装Androidx86_64系统详细步骤要点

最近需要用到安卓系统蓝牙功能做测试&#xff0c;就选择了Virtualboxandroidx86方案&#xff0c;先把系统安装好&#xff0c;后面看是否可以比较好的完成蓝牙功能测试。如果可以的话&#xff0c;我会再发文分享下的&#xff0c;敬请期待。 1.准备材料 &#xff08;1&#xff…