OpenCv--换脸

引言

在当今数字化时代,图像处理技术的发展日新月异。换脸技术作为其中一项极具趣味性和挑战性的应用,吸引了众多开发者和爱好者的目光。OpenCV 作为一款强大的开源计算机视觉库,为我们实现换脸提供了丰富的工具和方法。本文将深入探讨如何使用 OpenCV 进行换脸操作,从原理到实践,一步步带领大家揭开换脸技术的神秘面纱。

一、换脸技术原理

OpenCV换脸的基本原理是通过​​人脸检测​​定位源人脸和目标人脸的位置,利用​​关键点检测​​(如Dlib的68点模型)标记五官轮廓,然后通过​​仿射变换​​将源人脸对齐到目标人脸的几何结构上,最后将换脸区域与目标图像进行颜色和边缘的无缝混合。整个过程结合了几何变形、颜色校正和智能融合技术,实现逼真的换脸效果。换脸技术的核心在于找到两张人脸之间的对应关系,并将一张脸的特征映射到另一张脸上。

二、关键点检测

人脸关键点检测是计算机视觉中的一项重要技术,用于​​精确定位人脸的五官轮廓和关键特征点​​(如眼睛、眉毛、鼻子、嘴巴、下巴等)。它在人脸识别、表情分析、换脸(Face Swap)、AR滤镜等应用中发挥核心作用。

本文我们通过​Dlib库来实现对人脸的68点检测

import dlib
#构建人脸检测器
detector = dlib.get_frontal_face_detector()
#读取人脸关键点定位模型
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
#检测人脸
face = detector(img,0)
#返回68个关键点
landmarks = predictor(img, face)

三、仿射变换

图像的几何变换主要包括:平移,旋转,剪切,仿射,透视等

仿射变换​​ 是一种在几何中广泛使用的线性变换方法,它能够保持图像的 ​​平行性​​ 和 ​​直线性​​,但可能改变距离和角度。在计算机视觉和图像处理中,仿射变换常用于 ​​图像校正、旋转、缩放、平移、倾斜(剪切)​​ 等操作。

仿射变换简单的来说就是通过3对坐标点从一个二维坐标系变换到另一个二维坐标系

# 计算 3 组对应点(源点 → 目标点)
mat_src = np.float32([[0, 0], [0, h-1], [w-1, 0]])     
mat_dst = np.float32([[0, 0], [100, h-100], [w-100, 100]])  # 计算仿射变换矩阵​
M = cv2.getAffineTransform(mat_src, mat_dst)       
# 仿射变换​
dst = cv2.warpAffine(img, M, (w, h))   

​四、换脸

下面我们通过代码来实现对以下两张图片的换脸处理

首先导入相应的库

import cv2
import dlib
import numpy as np

创建一个列表,保存脸部不同位置68个关键点模型

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,36))
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_BROW_POINTS+LEFT_EYE_POINTS+RIGHT_EYE_POINTS+NOSE_POINTS+MOUTH_POINTS]POINTStuple=tuple(POINTS)

掩膜函数,生成人脸区域的掩膜

def getFaceMask(im, keyPoints):#根据关键点获取脸部掩膜im = np.zeros(im.shape[:2], dtype=np.float64)for p in POINTS:points = cv2.convexHull(keyPoints[p])   #获取凸包cv2.fillConvexPoly(im, points, color=1)  #填充凸包,数字在0~1之间 0.# 单通道im构成3通道im(3,行,列),改变形状(行、列、3)适应OpenCVim = np.array([im, im, im]).transpose((1, 2, 0))im = cv2.GaussianBlur(im,(25,25), 0)#这个参数比较重要,需要调整return im

使用dlib检测人脸并提取68个关键点。 

def getKeyPoints(im):#获取关键点rects = detector(im, 1) #获取人脸方框位置shape = predictor(im, rects[0])  # 获取关键点s= np.matrix([[p.x, p.y] for p in shape.parts()])return s

求出b脸仿射变换到a脸的变换矩阵M

def getM(points1, points2):points1 = points1.astype(np.float64) #int8转换为浮点数类型points2 = points2.astype(np.float64) #转换为浮点数类型c1 = np.mean(points1, 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)R = (U * Vt).T# 通过U和Vt找到Rreturn np.hstack(((s2/s1)*R, c2.T-(s2/s1)*R*c1.T))

通过高斯模糊,将图像 b 的颜色风格匹配到图像 a

def normalColor(a,b):ksize=(111,111)aGauss=cv2.GaussianBlur(a,ksize,0)bGauss=cv2.GaussianBlur(b,ksize,0)weight=aGauss/bGausswhere_are_inf=np.isinf(weight)weight[where_are_inf]=0return b*weight

主程序

a=cv2.imread('hl2.jpg')
b=cv2.imread('hl1.jpg')#构造脸部位置检测器
detector=dlib.get_frontal_face_detector()
#读取人脸关键点定位模型
predictor=dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')#获取关键点
aKeyPoints=getKeyPoints(a)
bKeyPoints=getKeyPoints(b)#获取人脸掩膜
aMask=getFaceMask(a,aKeyPoints)
cv2.imshow('aMask',aMask)
cv2.waitKey(0)bMask=getFaceMask(b,bKeyPoints)
cv2.imshow('bMask',bMask)
cv2.waitKey(0)#求出b脸仿射变换到a脸的变换矩阵M
M=getM(aKeyPoints[POINTStuple],bKeyPoints[POINTStuple])#将b的脸部(bmask)根据M仿射变换到a上
dsize=a.shape[:2][::-1]
#仿射变换
bMaskWarp=cv2.warpAffine(bMask,M,dsize,borderMode=cv2.BORDER_TRANSPARENT,flags=cv2.WARP_INVERSE_MAP)
cv2.imshow('bMaskWarp',bMaskWarp)
cv2.waitKey(0)#获取脸部掩膜最大值(两个脸掩膜叠加)
mask=np.max([aMask,bMaskWarp],axis=0)
cv2.imshow('mask',mask)
cv2.waitKey(0)#使用仿射矩阵M,将b映射到a
bWarp=cv2.warpAffine(b,M,dsize,borderMode=cv2.BORDER_TRANSPARENT,flags=cv2.WARP_INVERSE_MAP)
cv2.imshow('bWrap',bWarp)
cv2.waitKey(0)

得到换脸结果

#求b图片的仿射到图片a的颜色值,b的颜色值改为a的颜色
bcolor = normalColor(a, bWrap)
cv2.imshow("bcolor",bcolor)
cv2.waitKey()#图片混合
out = a * (1.0 - mask) + bcolor * mask
# 输出换脸结果
cv2.imshow("a",a)
cv2.imshow("b",bOriginal)
cv2.imshow("out",out/255)
cv2.waitKey()
cv2.destroyAllWindows()

最终得到结果如图所示

五、总结

通过以上步骤,我们利用 OpenCV 成功实现了换脸操作。从人脸检测、特征点提取到人脸对齐和图像融合,每一步都蕴含着计算机视觉技术的精妙之处。然而,目前的换脸技术仍存在一些局限性,如在复杂光照条件下、人脸姿态变化较大时可能效果不佳,以及换脸后的图像可能存在边缘不自然等问题。未来,随着深度学习等技术的不断发展,换脸技术有望在准确性和自然度上取得更大的突破,应用领域也将更加广泛,如影视制作、虚拟现实、娱乐等。

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

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

相关文章

安卓基础(SQLite)

基础 import sqlite3# 连接到数据库 conn sqlite3.connect(mydatabase.db) cursor conn.cursor()# 执行查询 cursor.execute("SELECT * FROM users") rows cursor.fetchall()for row in rows:print(row)# 关闭连接 conn.close() 创建一个继承自 SQLiteOpenHelpe…

QuickAPI 核心能力解析:构建数据服务化的三位一体生态

在企业数据资产化运营的进程中,如何打破数据开发与共享的效率瓶颈,实现从 “数据可用” 到 “数据好用” 的跨越?麦聪软件的 QuickAPI 给出了系统性答案。作为 SQL2API 理念的标杆产品,QuickAPI 通过SQL 编辑器、数据 API、数据市…

《计算机视觉度量:从特征描述到深度学习》—生成式人工智能在工业检测的应用

2022 年 11 月 30 日一个很重要的标志事件就是chatgpt的出现,打开了生成式人工智能的开端。这也许会是一个历史性的时刻,今天是2025年4月,过去两年多,那个时刻目前回想还是对本人造成了冲击,一个完全有自主分析能力的生…

【软件测试】自动化测试框架Pytest + Selenium的使用

Pytest Selenium 是一种常见的自动化测试框架组合,用于编写和执行 Web 应用程序的自动化测试。Pytest 是一个强大的 Python 测试框架,而 Selenium 是一个用于浏览器自动化的工具,二者结合使用可以高效地进行 Web 应用的功能测试、UI 测试等。…

煤矿湿喷砂浆搅拌机组创新设计与关键技术研究

引言&#xff1a;湿喷工艺在煤矿支护中的革命性意义 在深部煤矿巷道支护领域&#xff0c;湿喷混凝土技术以其回弹率低&#xff08;<15%&#xff09;、粉尘浓度小&#xff08;<10mg/m&#xff09;的显著优势&#xff0c;逐步取代传统干喷工艺。作为湿喷工艺的核心设备&am…

如何处理ONLYOFFICE文档服务器与Java Web应用间的安全认证和授权

如何处理ONLYOFFICE文档服务器与Java Web应用间的安全认证和授权&#xff1f; 处理 ONLYOFFICE 文档服务器与 Java Web 应用之间的安全认证和授权&#xff0c;通常涉及以下几个关键步骤和技术&#xff1a; 1. JWT (JSON Web Token) 认证 启用 JWT&#xff1a; ONLYOFFICE 文档…

无参数RCE

无参数RCE&#xff08;Remote Code Execution&#xff0c;远程代码执行&#xff09; 是一种通过利用目标系统中的漏洞&#xff0c;在不直接传递用户可控参数的情况下&#xff0c;实现远程执行任意代码的攻击技术。与传统的RCE攻击不同&#xff0c;无参数RCE不依赖外部输入参数…

OL9设置oracle23ai数据库开机自启动

1、设置oracle用户的环境变量信息 [oracleOracleLinuxR9U5 ~]$vim ~/.bash_profile # Set Oracle environment variables for Oracle 23c AI export ORACLE_HOME/opt/oracle/product/23ai/dbhomeFree export ORACLE_SIDFREE export PATH$ORACLE_HOME/bin:$PATH export LD_LIB…

AI agents系列之智能体框架介绍

1. 引言 智能体AI Agents框架通过赋予自主系统动态感知、推理和行动的能力&#xff0c;彻底改变了AI领域。本节将探讨智能体框架的核心概念&#xff0c;并重点介绍为什么开源解决方案对现代AI开发的创新和可扩展性至关重要。 1.1 什么是智能体框架&#xff1f; 智能体框架代…

【数据资产入表】数据确权

&#xfeff;#数据要素[话题]#&#xfeff; &#xfeff;#数据资源盘点[话题]#&#xfeff; &#xfeff;#数据资产盘点[话题]#&#xfeff; &#xfeff;#数据资产[话题]#&#xfeff; &#xfeff;#数据资产入表[话题]#&#xfeff; &#xfeff;#数据盘点[话题]#&…

关于vxe-select得filter-method 自定义方法得使用,忽略大小写匹配

vxe-select使用模糊匹配时&#xff0c;filter-method自定义匹配方法&#xff0c;模糊忽略大小写进行匹配数据 <vxe-select v-model"marketingId":options"marketingOptions"transfer clearable placeholder"市场"filterable :filter-method&…

AIDL 中如何传递 Parcelable 对象

目录 1. 直接在 AIDL 中定义 Parcelable 对象2. 自定义 Parcelable 对象的传递3. 以 Rect 类为例的 Parcelable 实现4. 注意安全性5. 小结1. 直接在 AIDL 中定义 Parcelable 对象 背景说明 从 Android 10(API 级别 29)开始,AIDL 允许直接在 .aidl 文件中定义 Parcelable 对…

【LangChain核心组件】Retrieval(检索)模块

在AI技术日新月异的今天&#xff0c;大型语言模型&#xff08;LLM&#xff09;的局限性也逐渐显现——它们无法有效处理特定领域知识和用户私有数据。这正是检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;技术崛起的根本原因。作为当前最…

Java使用WebSocket视频拆帧进度处理与拆帧图片推送,结合Apipost进行调试

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>Configuration public class WebSocketConfig {/*** 启动 WebSocket 服务器*/Beanpublic ServerEndpointE…

XSS攻击(反射型、存储型、dom型、PDF、SWF、SVG)

一、XSS攻击是什么 XSS是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中 Web 里面的脚本代码会被执行&#xff0c;从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的。 二、XSS分类 反射型XSS 常见情况是…

vue + element-plus自定义表单验证(修改密码业务)

写一个vue组件Password.vue 没有表单验证只有3个表单项 <template><div><el-form><el-form-item label"旧密码"><el-input></el-input></el-form-item><el-form-item label"新密码"><el-input>&l…

Linux下使用MTK的SP_Flash_tool刷机工具

MTK的SP_Flash_tool刷机工具安装流程如下&#xff1a; 1、解压SP_Flash_Tool_Linux_v5.1336.00.100_Customer.zip unzip SP_Flash_Tool_exe_Linux_64Bit_v5.1520.00.100.zip 2、首先安装 libusb-dev 这个包&#xff1a; sudo apt-get install libusb-dev 3、安装成功之后…

基于 PyGetWindow 获取窗口信息和控制窗口

PyGetWindow 是基于Python的一款简单、跨平台的模块&#xff0c;用来获取窗口信息和控制窗口。可以实现的功能有&#xff1a; 获取当前系统中所有打开窗口的列表。 根据窗口标题、窗口句柄等属性获取特定的窗口对象。 激活、最小化、最大化和关闭窗口。 获取和设置窗口的位置、…

STM32硬件IIC+DMA驱动OLED显示——释放CPU资源,提升实时性

目录 前言 一、软件IIC与硬件IIC 1、软件IIC 2、硬件IIC 二、STM32CubeMX配置KEIL配置 三、OLED驱动示例 1、0.96寸OLED 2、OLED驱动程序 3、运用示例 4、效果展示 总结 前言 0.96寸OLED屏是一个很常见的显示模块&#xff0c;其驱动方式在用采IIC通讯时&#xff0c;常用软件IIC…

【ozone工具使用指南】基于keil使用ozone创建一个调试工程

前言&#xff1a;一般调试嵌入式工程代码最常见的方式是基于keil上面DEBUG&#xff0c;使用这种最古老的方式虽然也很方便&#xff0c;但是一些功能并没有办法体现&#xff0c;比如变量的变化曲线或者波形并无法直观的显示出来&#xff0c;ozone这个工具就结合了上面提到的比ke…