当前位置: 首页 > 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制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

XCTF-web-easyupload

试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性&#xf…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...

【iOS】 Block再学习

iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...