当前位置: 首页 > news >正文

《深度学习》dlib 人脸应用实例 仿射变换 换脸术

目录

一、仿射变换

1、什么是仿射变换

2、原理

3、图像的仿射变换

1)图像的几何变换主要包括

2)图像的几何变换主要分为

1、刚性变换:

2、仿射变换

3、透视变换

3)常见仿射变换

二、案例实现

1、定义关键点索引

2、定义函数用于获取脸部掩膜

3、定义函数求变换矩阵

4、定义求68关键点函数

5、定义函数修改图片颜色

6、主函数

运行结果:


一、仿射变换

1、什么是仿射变换

        仿射变换(Affine Transformation)是指在向量空间中进行一次线性变换(乘以一个矩阵)和一次平移(加上一个向量),变换到另一个向量空间的过程,即对图像进行形状、大小和方位的变换。

2、原理

        仿射变换代表的是两幅图之间的映射关系,仿射变换矩阵为2x3的矩阵,如下图中的矩阵M,其中的B起着平移的作用,而A中的对角线决定缩放,反对角线决定旋转或错切。

        原像素点坐标(x,y),则矩阵仿射变换基本算法原理

        所以仿射变换是一种二维坐标(x,y)到二维坐标(u,v)之间的线性变换,其数学表达式如下:

        这个矩阵是2×3的,但是这会改变原始图像的维度,为此,增加一个维度,构造齐次变换矩阵3×3

        这就保持了图像的‘平直性’和‘平行性’平直性:直线、圆弧不变。平行性:平行关系不变,直线相对位置不变,但是夹角可能会改变。

3、图像的仿射变换

        1)图像的几何变换主要包括

                平移、旋转、缩放、剪切、仿射、透视等。

        2)图像的几何变换主要分为

                刚性变换、仿射变换和透视变换(投影变换)

                1、刚性变换:

                        平移+旋转 相似变换:缩放+剪切

                2、仿射变换

                        从一个二维坐标系变换到另一个二维坐标系,属于线性变换。通过已知3对坐标点可以求得变换矩阵

                3、透视变换

                        从一个二维坐标系变换到一个三维坐标系,属于非线性变换。通过已知4对坐标点可以求得变换矩阵。

        3)常见仿射变换

                常见的仿射变换包括平移(Translation)、缩放(Scaling)、旋转(Rotation)、错切(Shearing)和镜像(Flipping)等

                平移:沿着x和y轴的平移使图像的位置发生改变。

                缩放:沿着x和y轴的缩放使图像的大小发生改变。

                旋转:绕图像中心点进行旋转,使图像按某个角度进行旋转。

                错切:使图像在某个方向上产生倾斜。

                镜像:沿着x或y轴进行镜像翻转,使图像左右或上下对称。

二、案例实现

1、定义关键点索引

# 定义关键点索引
JAW_POINTS = list(range(0,17))   # 脸部轮廓关键点
RIGHT_BROW_POINTS = list(range(17,22))  # 左眉毛
LEFT_BROW_POINTS = list(range(22,27))   # 右眉毛
NOSE_POINTS = list(range(27,35))   # 鼻子
RIGHT_EYE_POINTS = list(range(36,42))   # 左眼
LEFT_EYE_POINTS = list(range(42,48))  # 右眼
MOUTH_POINTS = list(range(48,61))  # 上嘴唇
FACE_POINTS = list(range(17,68))  # 除了脸颊的其余部位# 关键点集
POINTS = [LEFT_BROW_POINTS + RIGHT_EYE_POINTS +LEFT_EYE_POINTS +RIGHT_BROW_POINTS + NOSE_POINTS + MOUTH_POINTS]# 处理为元组,后续使用方便
POINTStuple = tuple(POINTS)   # 元组内存放关键点集的列表

2、定义函数用于获取脸部掩膜

def getFaceMask(im,keyPoints):   # 传入图像和关键点矩阵,根据关键点获取脸部掩膜im = np.zeros(im.shape[:2],dtype=np.float64)   # 生成一个和图像大小一致的0矩阵,类型为浮点型for p in POINTS:   # 遍历每一个关键点的索引号points = cv2.convexHull(keyPoints[p])   # 调用凸包函数,获取凸包,即最小凸多边形,返回凸包边界信息cv2.fillConvexPoly(im,points,color=1)   # 在掩膜im上填充凸包points,color=1表示填充蓝色# 单通道im构成3通道im(3,行,列),改变形状(行、列、3)适应0penCVim = np.array([im,im,im]).transpose((1,2,0))  # 将掩膜升高一个维度然后转换第一个维度和第三个维度的位置,表示为宽、高、3通道im = cv2.GaussianBlur(im,ksize=(25,25),sigmaX=0)   # 使用高斯模糊对im掩膜进行处理,高斯核大小为25*25,0表示指定高斯核在x方向的标准差,设置为0表示自动计算一个合适的值return im   # 返回处理完的掩膜图像

3、定义函数求变换矩阵

def getM(points1, points2):points1 = points1.astype(np.float64)   # int8转换为浮点数类型points2 = points2.astype(np.float64)   # 转换为浮点数类型c1 = np.mean(points1,axis=0)   # 计算均值,axis=0表示计算行方向或垂直方向c2 = np.mean(points2,axis=0)   # 用于归一化:(数值-均值)/标准差,均值不同,主要是脸五官位置大小不同points1 -= c1   # 减去均值points2 -= c2   # 减去均值s1 = np.std(points1)  # 方差计算标准差s2 = np.std(points2)points1 /= s1   # 除标准差,计算出归一化的结果points2 /= s2   # 除标准差,计算出归一化的结果# 奇异值分解,Singular Value DecompositionU, S, Vt = np.linalg.svd(points1.T * points2)  # points1.T * points2计算协方差矩阵,使用np.linalg.svd对协方差矩阵进行奇异值分解,返回三个矩阵R = (U * Vt).T  # 通过U和Vt计算旋转矩阵R,U * Vt将points1对其到points2,T为转置return np.hstack(((s2 / s1) * R,c2.T-(s2 / s1) * R * c1.T))  # 返回a仿射到b的变换矩阵# 计算一个刚体变换矩阵,该矩阵可以将一个点集(points1)经过旋转和平移后对齐到另一个点集(points2),同时考虑了可能的尺度差异。

4、定义求68关键点函数

def getKeyPoints(im):  # 接收到一张图片,获取图片中人脸的关键点rects = detector(im,1)   # 调用人脸检测器,获取人脸方框位置,返回数组类型,其中存放方框左上角坐标和右下角坐标shape = predictor(im,rects[0])  # 调用预训练模型,获取人脸的68个关键点s = np.matrix([[p.x,p.y] for p in shape.parts()])  # shape.parts()获取关键点的迭代器,遍历出来每一个关键点,将遍历出来的关键点存入列表,然后使用np.matrix创建一个二维矩阵return s   # 返回68个关键点的坐标矩阵

5、定义函数修改图片颜色

def normalColor(a, b):ksize = (111,111)  # 非常大的核,用于进行高斯模糊的核,去噪等运算时为11就比较大了aGauss = cv2.GaussianBlur(a,ksize,0)  # 对a进行高斯滤波bGauss = cv2.GaussianBlur(b,ksize,0)  # 对b进行高斯滤波weight = aGauss/bGauss    # 计算目标图像调整颜色的权重值,存在0除警告,可忽略。where_are_inf = np.isinf(weight)   # 检查weight中是否有无穷大的值weight[where_are_inf] = 0   # 如果有将其更改为0return b * weight   # 将权重应用于图像b,以调整其颜色

6、主函数

a = cv2.imread("pyy1.png")   # 待换脸的A图片
b = cv2.imread("zly1.png")detector = dlib.get_frontal_face_detector()   # 构造脸部位置检测器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")   # 读取人脸68关键点检测器的预处理模型aKeyPoints = getKeyPoints(a)  # 将图片传入函数,获取A图片的68个关键点坐标矩阵
bKeyPoints = getKeyPoints(b)bOriginal = b.copy()   # 不对原来的图片b进行破坏和修改aMask = getFaceMask(a,aKeyPoints)   # 获取图片A的人脸掩膜
cv2.imshow("aMask",aMask)   # 展示掩膜
cv2.waitKey()bMask = getFaceMask(b,bKeyPoints)  # 获取图片B的人脸掩膜
cv2.imshow("bMask", bMask)
cv2.waitKey()"""求出b脸仿射变换到a脸的变换矩阵M"""
M = getM(aKeyPoints[POINTStuple],bKeyPoints[POINTStuple])   # 传入a脸关键点坐标和b脸关键点坐标,获取a仿射到b的变换矩阵"""将b的脸部(bmask)根据M仿射变换到a上"""
dsize = a.shape[:2][::-1]   # 获取原图高宽,然后倒序
# 目标输出与图像a大小一致
# 需要注意,shape是(行、列),warpAffine参数dsize是(列、行)
# 使用a.shape[:2][::-1],获取a的(列、行)# 函数warpAffine(src,M,dsize,dst=None, flags=None, borderMode=None, borderValue=None)
# src:输入图像
# M:运算矩阵,2行3列的,
# dsize:运算后矩阵的大小,也就是输出图片的尺寸
# dst:输出图像
# flags:插值方法的组合,与resize函数中的插值一样,可以查看cv2.resize
# borderMode:边界模式,BORDER_TRANSPARENT表示边界透明
# borderValue:在恒定边框的情况下使用的borderValue值;默认情况下,它是0
bMaskWarp = cv2.warpAffine(bMask,M,dsize,borderMode=cv2.BORDER_TRANSPARENT,flags=cv2.WARP_INVERSE_MAP)
# 返回变换后的掩膜图像,包含了根据变换矩阵M和指定大小dsize对bMask进行仿射变换的结果。cv2.imshow("bMaskWarp",bMaskWarp)
cv2.waitKey()"""获取脸部最大值(两个脸模板叠加)"""
mask = np.max([aMask,bMaskWarp],axis=0)  # a将掩膜图像与b变换后的掩膜图像数值转变为数组类型,然后沿行方向求最大值
cv2.imshow("mask",mask)
cv2.waitKey()"""使用仿射矩阵M,将b映射到a"""
# 计算b图片经过变换矩阵进行仿射变换处理后的图像
bWrap = cv2.warpAffine(b,M, dsize,borderMode=cv2.BORDER_TRANSPARENT,flags=cv2.WARP_INVERSE_MAP)
cv2.imshow("bWrap",bWrap)
cv2.waitKey()# 求b图片仿射到图片a的颜色值,b的颜色值改为a的颜色
bcolor = normalColor(a,bWrap)
cv2.imshow("bcolor",bcolor)
cv2.waitKey()# 换脸(mask区域用bcolor,非mask区城用a)
out = a*(1.0-mask) + bcolor * mask# 输出原始人脸、换脸结果
cv2.imshow("a",a)
cv2.imshow("b" ,bOriginal)
cv2.imshow("out", out/255)
cv2.waitKey()
cv2.destroyAllWindows()
        运行结果:

相关文章:

《深度学习》dlib 人脸应用实例 仿射变换 换脸术

目录 一、仿射变换 1、什么是仿射变换 2、原理 3、图像的仿射变换 1)图像的几何变换主要包括 2)图像的几何变换主要分为 1、刚性变换: 2、仿射变换 3、透视变换 3)常见仿射变换 二、案例实现 1、定义关键点索引 2、定…...

springboot044美容院管理系统(论文+源码)_kaic

本科毕业设计论文 题目:美容院管理系统设计与实现 系 别: XX系(全称) 专 业: 软件工程 班 级: 软件工程15201 学生姓名: 学生学号: 指导教师: 导师…...

大数据新视界 --大数据大厂之数据脱敏技术在大数据中的应用与挑战

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

Erric Gamma 关于resuable code的采访

采访地址 The risk of speculating Bill Venners: The GoF book says, “The key to maximizing reuse lies in anticipating new requirements and changes to existing requirements, and in designing your systems so they can evolve accordingly. To design a system s…...

【Ubuntu18.04命令行code打不开】可能的解决方法

目录 问题:命令行code打不开文件尝试① kimi是这么说的② sudo apt-get install apparmor apparmor_utils③ 在混沌的操作完以上一通后,sudo apt-get install snapd 我试了将近一个小时 : ( so depressed 我只是想用vscode打开个文件夹,我甚至…...

大数据毕业设计基于springboot+Hadoop实现的豆瓣电子图书推荐系统

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图 前言 文章底部名片,获取项目的完整演示视频,免费解答技术疑问 项目介绍 随着开数字化阅读的普及,豆瓣电子图书推荐系统应运而生,旨在为用户提供个性化的阅…...

【进阶OpenCV】 (15)-- 人脸识别 -- EigenFaces算法

文章目录 EigenFaces算法一、算法原理二、算法流程三、算法特点四、代码步骤1. 图像预处理2. 创建Eigenfaces人脸识别器3. 训练模型4. 预测图像 总结 EigenFaces算法 EigenFaces算法是一种基于主成分分析(PCA)的人脸识别方法,其核心思想是通…...

无人机封闭空间建图检测系统技术详解

无人机封闭空间建图检测系统技术是一种集成了多种传感器、智能算法与控制系统的高级技术,旨在实现无人机在复杂封闭环境下的自主导航、精确建图与高效检测。以下是对该技术的详细解析: 一、技术概述 无人机封闭空间建图检测系统通过集成激光雷达(LiDAR…...

webpack自定义插件 ChangeScriptSrcPlugin

插件文件 class ChangeScriptSrcPlugin {apply(compiler) {const pluginName "ChangeScriptSrcPlugin";compiler.hooks.compilation.tap(pluginName, (compilation, callback) > {compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(pluginName,(html…...

win11 笔记本指纹驱动正常就是使用不了

去微信官网下载最新的win11重装系统后,发现笔记本上的指纹登录失效了,网上搜索各种试过不行,新版本与旧的win11有微出入,那些方法都不行。系统版本如下: 操作前确保: 1. win11能升级,默认有试用…...

表的约束

约束就是设定条条框框,保证被约束目标符合约束条件。表的约束就是对表内列数据的约束,保证列数据的正确性。 default 设置列数据的默认值。当用户添加记录的时候没有初始化该列的数据,就是使用默认值初始化。 如果创建表的时候没有设置默认…...

jmeter是怎么用的,怎么设计接口测试用例的

如何使用: Apache JMeter 是一款广泛使用的开源性能测试工具,用于对各种服务(如 Web 应用、数据库、FTP、WEB 服务等)进行负载测试和性能测试。以下是如何使用 JMeter 的基本步骤。 1. 安装 JMeter 下载 JMeter:访问…...

数据挖掘示例

案例背景,有公司进行橡胶玩具的生产,一共生产两种产品,分别为橡皮鱼和橡皮鸭。 已知条件为: 1、公司的橡胶原材料能够生产500只橡皮鸭或者400条橡皮鱼。 2、生产效率为公司产量不会高于400只橡皮鸭和300条橡皮鱼。 3、每只橡皮…...

【PHP】在ThinkPHP6中Swoole与FPM的简单性能测试对比

一、前言 本文主要测试在ThinkPHP 6框架中,使用Swoole扩展库与使用PHP-FPM两者的HTTP并发性能差距,测试方法较简单,仅供参考。 二、测试环境 系统:Ubuntu 22.04 PHP版本:7.4.33 Swoole版本:4.8.13 ThinkPHP版本:6.1.5 ThinkPHP-Swoole扩展库版本:3.1.4 测试工具:A…...

论文写作学习--POLYGCL

POLYGCL: GRAPH CONTRASTIVE LEARNING VIA LEARNABLE SPECTRAL POLYNOMIAL filters 今天由于开了一天的积极分子会议以及要写汇报,因此,只来得及学一会。 摘要 第一步,设定背景 Recently, Graph Contrastive Learning (GCL) has achieved …...

【高等数学】无穷级数

0. 了解 无穷级数是指将无穷多个数按照一定的规律相加起来的表达式。 打个比方,就像你有一个无穷长的梯子,每一级梯子代表一个数。把这些数一个一个加起来,就形成了无穷级数。 比如常见的等比级数,这里是首项,是公比。如果,这个等比级数是收敛的,也就是它的和是一个有限…...

计算机网络——无连接传输UDP

UDP用于流媒体应用和事务性应用(一次往返搞定的应用)...

DS几大常见排序讲解和实现(下)(15)

文章目录 前言一、快排的思想二、Hoare版基本思路代码实现 三、挖坑法基本思路代码实现 四、双指针法基本思想代码实现 五、三数取中六、小区间优化七、三路划分八、自省排序总结 前言 其实下篇就单独讲个快速排序   你可能会想这是什么神通,竟然能单独开一篇来讲…...

电脑视频剪辑大比拼,谁更胜一筹?

随着短视频的火爆,越来越多的人开始尝试自己动手制作视频,无论是记录生活点滴还是创作个性短片,一款好用的视频剪辑软件是必不可少的。今天,我们就从短视频运营的角度,来聊聊几款热门的电脑视频剪辑软件,看…...

计算机毕业设计 基于Web的景区管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...

计算生物学与生物信息学漫谈-2-测序深度/读长质量和Fasta处理

上一篇文章中我们介绍了测序技术的由来与发展,那么在介绍第三代测序的时候,我们提到了关于测序深度和读长的问题,那么本篇文章就详解介绍一下。 计算生物学与生物信息学漫谈-1-测序一路走来-CSDN博客 目录 1.测序深度SEQUENCING DEPTH &…...

基于SSM+微信小程序的电子点餐管理系统(点餐1)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的电子点餐管理系统实现了管理员及用户。管理员实现了首页、个人中心、餐品分类管理、特色餐品管理、订单信息管理、用户管理、特价餐品管理、活动订单管理、系统管理。…...

IO进程---day5

1、使用有名管道实现两个进程之间的相互通信 //管道文件 #include<myhead.h> int main(int argc, const char *argv[]) {//创建有名管道文件1if(mkfifo("./pipe1",0664)-1){perror("创建管道文件失败");return 0;}if(mkfifo("./pipe2",066…...

ROS理论与实践学习笔记——5 ROS机器人系统仿真之URDF(Unified Robot Description Format)语法详解

URDF 文件是一个标准的 XML 文件格式&#xff0c;用于在 ROS 中描述机器人模型的结构。URDF 通过预定义的一系列标签&#xff0c;简洁地表达机器人的组成和运动关系。虽然机器人模型可能非常复杂&#xff0c;但在 URDF 中可以主要简化为两个核心部分&#xff1a; 连杆&#xff…...

常见SQL注入攻击示例与原理及其防御措施

SQL 注入&#xff08;SQL Injection&#xff09;是一种代码注入技术&#xff0c;用于攻击数据驱动的应用程序&#xff0c;主要通过在输入字段或 URL 查询参数中插入恶意 SQL 语句来实现。攻击者利用应用程序对用户输入数据的未充分验证或过滤&#xff0c;将恶意 SQL 语句注入到…...

Node.js 中的 WebSocket 底层实现

WebSockets 是一种网络通信协议&#xff0c;可实现双向客户端-服务器通信。 WebSockets 通常用于需要即时更新的应用程序&#xff0c;使用 HTTP 之上的持久双工通道来支持实时交互&#xff0c;而无需持续进行连接协商。服务器推送是 WebSockets 的众多常见用例之一。 本文首先…...

MySQl数据库的基本操作

1.1创建数据库 使用CREATE DATABASE语句可以轻松创建MySQL数据库&#xff0c;语法如下&#xff1a; CREATE DATABASE 数据库名; 例&#xff1a;创建fruitsales数据库 CREATE DATABASE fruitsales;1.2 查看数据库 使用SHOW语句查看当前服务器下所有已经存在的数据库 SHOW DAT…...

Egg.js 项目的合理 ESLint 配置文件模板

Egg.js 项目的合理 ESLint 配置文件模板 安装依赖 npm install eslint babel/eslint-parser eslint-plugin-import eslint-plugin-promise eslint-plugin-node --save-dev extends: 扩展了 eslint-config-egg 以及其他一些常用的插件配置。 parser: 使用 babel/eslint-parse…...

算法专题七: 分治归并

目录 1. 排序数组2. 交易逆序对的总数3. 计算右侧小于当前元素的个数4. 翻转对 1. 排序数组 算法思路: 本道题使用归并的思路进行排序, 先讲数组分为左右两个区间, 然后合并两个有序数组. class Solution {vector<int> tmp; public:vector<int> sortArray(vector&…...

一个基于vue功能强大的表格组件--vxe-table的二次封装

基础使用 一个基于 vue 的 PC 端表格组件&#xff0c;支持增删改查、虚拟滚动、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、虚拟列表、模态窗口、自定义模板、渲染器、贼灵活的配置项、扩展接口等… <vxe-grid v-bind"gridOptions1"…...