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

OpenCV之换脸技术:一场面部识别的奇妙之旅

在这个数字化与智能化并进的时代,图像处理技术日益成为连接现实与虚拟世界的桥梁。其中,换脸技术作为一项颇受欢迎且富有挑战性的应用,不仅让人惊叹于技术的魔力,更在娱乐、影视制作等领域展现了无限可能。今天,我们就来探索如何使用OpenCV这一强大的计算机视觉库,实现基础的换脸效果。

一、前言

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,它提供了丰富的图像处理和视频分析功能。通过OpenCV,我们可以轻松地进行面部检测、特征点匹配、图像变换等操作,为实现换脸技术打下坚实基础。

二、技术原理

换脸技术的核心在于将源图像中的人脸区域精确地映射到目标图像上,同时保持面部特征的自然和协调。这通常涉及以下几个关键步骤:

  1. 面部检测:利用预训练的面部检测模型(如Haar特征分类器或深度学习方法)在图像中定位人脸区域。
  2. 特征点匹配:通过面部特征点检测算法(如Dlib的68点或5点特征检测)找到源图像和目标图像中对应的关键点。
  3. 图像变换:使用仿射变换、透视变换或更复杂的非线性变换(如Delaunay三角剖分)将源人脸变形以匹配目标人脸的形状。
  4. 图像融合:将变形后的源人脸与目标图像的背景进行无缝融合,处理边缘,使其看起来自然。
三、实现步骤

下面是一个基于OpenCV的简单换脸示例代码框架,注意,这里假设你已经安装了OpenCV和Dlib库(用于特征点检测)。

import cv2  
import dlib  
import numpy as np  # 定义面部特征点的区域索引  
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)  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)  # 将单通道图像转换为三通道图像,以适应OpenCV的显示要求  im = np.array([im, im, im]).transpose((1, 2, 0))  # 对掩模进行高斯模糊处理,以减少边缘的锯齿状  im = cv2.GaussianBlur(im, ksize=(25, 25), sigmaX=0)  return im  def getM(points1, points2):  """计算从points1到points2的仿射变换矩阵"""  # 将点转换为浮点数类型  points1 = points1.astype(np.float64)  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  # 使用奇异值分解计算仿射变换矩阵  U, S, Vt = np.linalg.svd(points1.T * points2)  R = (U * Vt).T  # 返回完整的仿射变换矩阵  return np.hstack(((s2 / s1) * R, c2.T - (s2 / s1) * R * c1.T))  def getKeypoints(im):  """检测图像中的面部关键点"""  # 检测面部  rects = detector(im, 1)  # 获取面部关键点  shape = predictor(im, rects[0])  # 将关键点转换为numpy矩阵  s = np.matrix([[p.x, p.y] for p in shape.parts()])  return s  def normalColor(a, b):  """调整b图的颜色值,使其与a图相似"""  # 对a和b进行高斯模糊处理,以减少噪声  aGauss = cv2.GaussianBlur(a, ksize=(111, 111), sigmaX=0)  bGauss = cv2.GaussianBlur(b, ksize=(111, 111), sigmaX=0)  # 计算颜色调整权值  weight = aGauss / bGauss  # 处理无穷大值  where_are_inf = np.isinf(weight)  weight[where_are_inf] = 0  # 返回调整后的b图  return b * weight  # 读取换脸所需的图片  
a = cv2.imread("pyy1.jpg")  # 换脸A图片  
b = cv2.imread("hg.png")  # 换脸B图片  # 初始化面部检测器和关键点预测器  
detector = dlib.get_frontal_face_detector()  
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")  # 获取A图片和B图片的面部关键点  
aKeyPoints = getKeypoints(a)  
bKeyPoints = getKeypoints(b)  # 复制B图片,以便后续处理不破坏原图  
bOriginal = b.copy()  # 获取A图片和B图片的面部掩模  
aMask = getFaceMask(a, aKeyPoints)  
cv2.imshow("aMask", aMask)  # 显示A图片的面部掩模  
cv2.waitKey()  bMask = getFaceMask(b, bKeyPoints)  # 获取B图片的面部掩模  
cv2.imshow("bMask", bMask)  # 显示B图片的面部掩模  
cv2.waitKey()  # 计算从B图片面部到A图片面部的仿射变换矩阵  
M = getM(aKeyPoints[POINTStuple], bKeyPoints[POINTStuple])  # 使用仿射变换矩阵将B图片的面部掩模变换到A图片上  
bMaskWarp = cv2.warpAffine(bMask, M, dsize=a.shape[:2][::-1],  borderMode=cv2.BORDER_TRANSPARENT,  flags=cv2.WARP_INVERSE_MAP)  
cv2.imshow("bMaskWarp", bMaskWarp)  # 显示变换后的B图片面部掩模  
cv2.waitKey()  # 获取面部区域的最大掩模(A和B的掩模叠加)  
mask = np.max([aMask, bMaskWarp], axis=0)  
cv2.imshow("mask", mask)  # 显示最大掩模  
cv2.waitKey()  # 使用仿射变换矩阵将B图片变换到A图片上  
bWrap = cv2.warpAffine(b, M, dsize=a.shape[:2][::-1],  borderMode=cv2.BORDER_TRANSPARENT,  flags=cv2.WARP_INVERSE_MAP)  
cv2.imshow("bWrap", bWrap)  # 显示变换后的B图片  
cv2.waitKey()  # 调整B图片的颜色,使其与A图片相似  
bcolor = normalColor(a, bWrap)  
cv2.imshow("bcolor", bcolor)  # 显示调整颜色后的B图片  
cv2.waitKey()  # 换脸:在掩模区域使用B图片的颜色,其他区域使用A图片  
out = a * (1.0 - mask) + bcolor * mask  # 显示原始图片和换脸结果  
cv2.imshow("a", a)  # 显示A图片  
cv2.imshow("b", bOriginal)  # 显示原始B图片  
cv2.imshow("out", out / 255)  # 显示换脸结果(注意:这里除以255是为了将像素值归一化到0-1之间,便于显示)  
cv2.waitKey()  
cv2.destroyAllWindows()  # 关闭所有窗口

代码效果:

结语

通过上述步骤,我们利用OpenCV和Dlib实现了一个基础的换脸效果。虽然这只是冰山一角,但它为我们打开了一个充满无限想象的空间。随着技术的不断进步,未来的换脸技术将更加智能化、高效化,为我们的生活带来更多乐趣和可能。如果你对图像处理感兴趣,不妨亲自动手尝试一下,探索更多未知的领域吧!

相关文章:

OpenCV之换脸技术:一场面部识别的奇妙之旅

在这个数字化与智能化并进的时代,图像处理技术日益成为连接现实与虚拟世界的桥梁。其中,换脸技术作为一项颇受欢迎且富有挑战性的应用,不仅让人惊叹于技术的魔力,更在娱乐、影视制作等领域展现了无限可能。今天,我们就…...

Linux学习笔记9 文件系统的基础

一、查看文件组织结构 Linux中一切都是文件。 Linux和Win的文件系统不是一个结构,Linux存在的根目录是所有目录的起点。 所有的存储空间和设备共享一个根目录,不同的磁盘块和分区挂载在其下,成为某个子目录的子目录,甚至设备也挂…...

Android OpenGL粒子特效

在本篇,我们将开启一个新的项目,探索粒子的世界。粒子是一种基本的图形元素,它们通常被表示为一组点。通过巧妙地组合一些基础的物理效果,我们能够创造出许多令人惊叹的视觉效果。想象一下,我们可以模拟一个水滴从喷泉…...

5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战

在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战 无论是在单机单卡(一台机器上只有一块GPU)还是单机多卡(一台机器上有多块GPU)的硬件配置上启动ChatGLM3-6B模型,其前置环境配置和项目文件是相同的。如果大家对配置过程还…...

dpkg:错误:另外一个进程已经为dpkg前端锁加锁

一、 问题描述 在新装ubuntu系统时,我们常常会遇见dpkg的错误,dpkg:错误:另外一个进程已经为dpkg前端锁加锁,如下图。 二、问题解决 方法一 先执行sudo rm /var/lib/dpkg/lock-frontend然后再继续安装软件包,如果出现问题dpkg:…...

基于SSM服装定制系统的设计

管理员账户功能包括:系统首页,个人中心,用户管理,服装类型管理,服装信息管理,服装定制管理,留言反馈,系统管理 前台账号功能包括:系统首页,个人中心&#xf…...

RK3588开发笔记-usb3.0 xhci-hcd控制器挂死问题解决

目录 前言 一、问题现象 二、问题分析 三、问题排查 总结 前言 在使用 RK3588 芯片进行开发的过程中,我遇到了 USB 3.0 xHCI-HCD 控制器外接5G通讯模块偶尔挂死的问题。这个问题导致 USB 设备失去响应,且不能恢复,需要重启整个系统才能恢复使用,针对该问题进行大量测试以…...

深入解析TCP/IP协议:网络通信的基石

1. 引言 TCP/IP 协议是现代计算机网络的核心,它为互联网上的设备提供了通信的基础。在网络通信中,TCP/IP 协议栈是无处不在的,无论是个人设备的浏览器请求,还是大型分布式系统的内部通信,都依赖于它的稳定、高效与可靠…...

基于微信小程序的汽车预约维修系统(lw+演示+源码+运行)

基于微信小程序的汽车预约维修系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的汽车预约维修系统的开发全过程。通过分析基于微信小程序的汽车预约维修系统管理的不足,创建了…...

wifi、热点密码破解 - python

乐子脚本,有点小慢,试过多线程,系统 wifi 连接太慢了,需要时间确认,多线程的话系统根本反应不过来。 也就可以试试破解别人的热点,一般都是 123456 这样的傻鸟口令 # coding:utf-8 import pywifi from pyw…...

bean的实例化2024年10月17日

跟不上为基础 1.你的java学习路线 2. 3.课程 注解的装配 contoller调用service用的是注解装配...

告别ELK,APO提供基于ClickHouse开箱即用的高效日志方案——APO 0.6.0发布

ELK一直是日志领域的主流产品,但是ElasticSearch的成本很高,查询效果随着数据量的增加越来越慢。业界已经有很多公司,比如滴滴、B站、Uber、Cloudflare都已经使用ClickHose作为ElasticSearch的替代品,都取得了不错的效果&#xff…...

Excel使用技巧:定位Ctrl+G +公式+原位填充 Ctrl+Enter快速填充数据(处理合并单元格)

Excel的正确用法: Excel是个数据库,不要随意合并单元格。 数据输入的时候一定要按照行列输入,中间不要留空,不然就没有关联。 定位CtrlG 公式原位填充 CtrlEnter快速填充数据 如果把合并的单元格 取消合并,只有第一…...

JAVA学习-练习试用Java实现“成绩归类”

问题: 编写程序,输入一批学生的成绩,遇0或负数则输入结束,要求统计并输出优秀(大于85)、通过(60~84)和不及格(小于60)的学生人数。 示例 &#x…...

【Hive】7-拉链表的设计与实现

拉链表的设计与实现 数据同步问题 背景 例如:MySQL中有一张用户表: tb_user,每个用户注册完成以后,就会在用户表中新增该用户的信息,记录该用户的id、手机号码、用户名、性别、地址等信息。 每天都会有用户注册,产生…...

Maxwell 底层原理 详解

Maxwell 是一个 MySQL 数据库的增量数据捕获(CDC, Change Data Capture)工具,它通过读取 MySQL 的 binlog(Binary Log)来捕获数据变化,并将这些变化实时地发送到如 Kafka、Kinesis、RabbitMQ 或其他输出端。…...

使用短效IP池的优势是什么?

短效IP池作为代理IP服务中一种独特的资源管理方式,其应用已经在数据采集、市场分析和网络安全等多个领域中展示出强大的功能。尽管“短效”听起来似乎意味着某种限制,然而在某些特定的应用场景下,短效IP池却提供了无可比拟的优势。本文将详细…...

zynq烧写程序到flash后不运行

🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&am…...

JMeter如何设置HTTP代理服务器?

1、 2、添加线程组 3、设置HTTP代理服务器,目标控制器选择“测试计划>线程组” 过滤掉不需要的信息 4、设置电脑手动代理 5、点击启动,在浏览器操作就可以了...

React面试题笔记(一)

一、react基础面试题 1.react中keys的作用是什么? key是是用于追踪哪些列表被修改,被添加或者被移除的辅助标识。 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

ios苹果系统,js 滑动屏幕、锚定无效

现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...

英国云服务器上安装宝塔面板(BT Panel)

在英国云服务器上安装宝塔面板(BT Panel) 是完全可行的,尤其适合需要远程管理Linux服务器、快速部署网站、数据库、FTP、SSL证书等服务的用户。宝塔面板以其可视化操作界面和强大的功能广受国内用户欢迎,虽然官方主要面向中国大陆…...

SpringCloud优势

目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...