[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.hqwc.cn/news/702165.html

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

相关文章

[HUBUCTF 2022 新生赛]ezsql

测试无结果 扫描目录&#xff0c;得到源码 找到注入点 思路&#xff1a;更新资料的时候可以同时更新所有密码 我们需要知道密码的字段名 爆库 nicknameasdf&age111,description(select database())#&descriptionaaa&token31ad6e5a2534a91ed634aca0b27c14a9 爆表…

C# OpenCvSharp Demo - 最大内接圆

C# OpenCvSharp Demo - 最大内接圆 目录 效果 项目 代码 下载 效果 项目 代码 using OpenCvSharp; using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Windows.Forms; namespace OpenCvSh…

美国站群服务器如何提高企业网站的负载均衡能力?

美国站群服务器如何提高企业网站的负载均衡能力? 美国站群服务器是企业提高网站负载均衡能力的重要工具之一。随着网络流量的增加和用户需求的多样化&#xff0c;如何有效地管理和分配流量成为了企业面临的挑战。通过采用美国站群服务器&#xff0c;企业可以实现流量的智能分…

什么是BI看板?选择BI看板制作工具时一定要考虑这些方面

BI看板也称为商业智能仪表板&#xff0c;是一种直观的数据可视化工具&#xff0c;它将关键业务指标&#xff08;KPIs&#xff09;和数据以图表、图形和表格的形式集中展示&#xff0c;使用户能够快速获取企业运营的实时概览。 这种数据可视化方式不仅使得复杂的数据信息易于理…

A股股息率最高的十个行业,哪些高股息可持续?

2023年以来&#xff0c;银行不断调低存款利率。目前&#xff0c;六大行5年定期存款&#xff08;整存整取&#xff09;挂牌利率约为2%。随着存款收益下降&#xff0c;那些股息率较高的上市公司和行业受到了关注。 数据分析显示&#xff0c;一部分行业的高股息可以持续&#xff…

Mysql-几何类型-POINT

在MySQL中&#xff0c;地理空间数据类型和功能被称为GIS&#xff08;Geographic Information System&#xff0c;地理信息系统&#xff09;。MySQL支持几种不同的空间数据类型&#xff0c;包括点&#xff08;POINT&#xff09;、线&#xff08;LINESTRING&#xff09;、多边形&…

如何安全高效地进行4S店文件分发,保护核心资产?

4S店与总部之间的文件分发是确保双方沟通顺畅、信息共享和决策支持的重要环节。4S店文件分发涉及到以下文件类型&#xff1a; 销售报告&#xff1a;4S店需要定期向总部提交销售报告&#xff0c;包括销售数量、销售额、市场份额等关键指标。 库存管理文件&#xff1a;包括车辆库…

探索设计模式的魅力:机器学习赋能,引领“去中心化”模式新纪元

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 探索设计模式的魅力&#xff1a;机器学习赋能&#xff0c;引领“去中心化”模式新纪元 ✨欢迎加入…

合合信息:TextIn文档解析技术与高精度文本向量化模型再加速

文章目录 前言现有大模型文档解析问题表格无法解析无法按照阅读顺序解析文档编码错误 诉求文档解析技术技术难点技术架构关键技术回根溯源 文本向量化模型结语 前言 随着人工智能技术的持续演进&#xff0c;大语言模型在我们日常生活中正逐渐占据举足轻重的地位。大模型语言通…

Go-Zero定义API实战:探索API语法规范与最佳实践(五)

前言 上一篇文章带你实现了Go-Zero模板定制化&#xff0c;本文将继续分享如何使用GO-ZERO进行业务开发。 通过编写API层&#xff0c;我们能够对外进行接口的暴露&#xff0c;因此学习规范的API层编写姿势是很重要的。 通过本文的分享&#xff0c;你将能够学习到Go-Zero的API…

数据库学习之select语句练习

目录 素材 练习 1、显示所有职工的基本信息。 结果 2、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 结果 3、求出所有职工的人数。 结果 4、列出最高工和最低工资。 结果 5、列出职工的平均工资和总工资。 结果 6、创建一个只有职…

直流无刷电机控制(一)六步换相(有感霍尔)

直流无刷电机概述 直流无刷电机的转子为永磁铁&#xff0c;定子为换相线圈&#xff0c;有别于有刷电机通过电刷或者换向器换相&#xff0c;无刷电机通过控制器电子换相。 极对数 直流无刷电机采用永磁铁作为转子&#xff0c;一对NS磁极为一极对&#xff0c;为了使电机运转更…