《计算机视觉》—— 换脸
- 效果如下:

- 完整代码:
import cv2
import dlib
import numpy as npJAW_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) # 填充凸包,数字在0~1之间# 单通道im构成3通道im(3,行,列),改变形状(行、列、3)适应0penCVim = np.array([im, im, im]).transpose((1, 2, 0))im = cv2.GaussianBlur(im, (25, 25), 0) # 需要根据具体调整return im""" 求出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))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图相同 """
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[where_are_inf] = 0return b * weighta = cv2.imread("dlrb_3.jpg") # 换脸A图片
b = cv2.imread("zly.jpg") # 换脸B图片detector = dlib.get_frontal_face_detector() # 构造脸部位置检测器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 获取人脸关键点定位模型aKeyPoints = getKeyPoints(a) # 获取A图片的68关键点
bKeyPoints = getKeyPoints(b) # 获取B图片的68关键点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])"""将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)
cv2.imshow("bMaskWarp", bMaskWarp)
cv2.waitKey()"""获取脸部最大值(两个脸模板香加)"""
mask = np.max([aMask, bMaskWarp], axis=0)
cv2.imshow("mask", mask)
cv2.waitKey()""" 使用仿射矩阵M,将b映射到a """
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()""" ===========step8:换脸(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()
相关文章:
《计算机视觉》—— 换脸
效果如下: 完整代码: import cv2 import dlib import numpy as npJAW_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…...
【JavaEE初阶】深入透析文件-IO关于文件内容的操作(四种文件流)
前言 🌟🌟本期讲解关于CAS的补充和JUC中有用的类,这里涉及到高频面试题哦~~~ 🌈上期博客在这里:【JavaEE初阶】文件-IO之实现文件系统的操作如何进行实现-CSDN博客 🌈感兴趣的小伙伴看一看小编主页&…...
复习:react 中的 refs,怎么使用,有哪些使用场景
在 React 中,refs(引用)是一个重要的特性,它允许开发者直接访问 DOM 元素或者 React 组件的实例。以下是对 React 中 refs 的使用及其使用场景的详细解释: 一、refs 的使用方法 字符串引用 在早期的 React 版本中,可以通过字符串来设置 ref。然而,这种方法已经被废弃,…...
Python OpenCV精讲系列 - 目标检测与识别深入理解(二十)
💖💖⚡️⚡️专栏:Python OpenCV精讲⚡️⚡️💖💖 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计,从基础概念入手,逐步深入到图像处理、特征检测、物体识…...
golang中的上下文
背景 在Go语言中,使用context包来管理跨API和进程间的请求生命周期是常见的做法。特别是在涉及到并发编程时,如启动协程(goroutine)来处理异步任务,正确地传递和监听context变得尤为重要。比如,在gin框架中…...
Navigation2 算法流程
转自 https://zhuanlan.zhihu.com/p/405670882 此文仅作学习笔记 启动流程 在仿真环境中启动导航包的示例程序,执行nav2_bringup/bringup/launch/tb3_simulation_launch.py文件。ROS2的launch文件支持采用python语言来编写以支持更加复杂的功能,本文件…...
OpenAI swarm+ Ollama快速构建本地多智能体服务 - 1. 服务构建教程
OpenAI开源了多智能体编排的工程swarm,今天介绍一下swarm与OLLAMA如何结合使用的教程,在本地构建自己的多智能体服务,并给大家实践演示几个案例。 安装步骤 安装ollama,在官网下载对应操作系统的版本即可,下载后用ol…...
HTB:Wifinetic[WriteUP]
目录 连接至HTB并启动靶机 1.What is the name of the OpenWRT backup file accessible over FTP? 使用nmap对靶机21、22端口进行脚本、服务信息扫描 2.Whats the WiFi password for SSID OpenWRT? 3.Which user reused the WiFi password on thier local account? 4.…...
专业学习|马尔可夫链(概念、变体以及例题)
一、马尔可夫链的概念及组成 (一)学习资料分享 来源:024-一张图,但讲懂马尔可夫决策过程_哔哩哔哩_bilibili 马尔可夫链提供了一种建模随机过程的方法,具有广泛的应用。在实际问题中,通过转移概率矩阵及初…...
RK3576 安卓SDK编译环境搭建
编译 Android14 对机器的配置要求较高: 建议预留500G存储 多分配CPU和内存 建议使用 Ubuntu 20.04 操作系统或更高版本 sudo apt-get updatesudo apt-get install make gcc sudo apt-get install g++ patchelf gawk texinfo chrpath diffstat binfmt-support sudo apt-get …...
Renesas R7FA8D1BH (Cortex®-M85) 上光电编码器测速功能
目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 硬件架构 2.1 硬件框架结构 2.2 测速功能原理介绍 2.2.1 理论描述 2.2.2 实现原理 2.2.3 系统硬件结构 3 软件实现 3.1 FSP配置项目 3.2 代码实现 3.2.1 初始化函数 3.2.2 功能函数 3.…...
软件测试学习笔记丨Linux三剑客-sed
本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/32521 一、简介 sed(Stream editor)是一个功能强大的文本流编辑器,主要用于对文本进行处理和转换。它适用于自动化处理大量的文本数据,能够支持…...
Vue脚手架学习 vue脚手架配置代理、插槽、Vuex使用、路由、ElementUi插件库的使用
目录 1.vue脚手架配置代理 1.1 方法一 1.2 方法二 2.插槽 2.1 默认插槽 2.2 具名插槽 2.3 作用域插槽 3.Vuex 3.1 概念 3.2 何时使用? 3.3 搭建vuex环境 3.4 基本使用 3.5 getters的使用 3.6 四个map方法的使用 3.6.1 mapState方法 3.6.2 mapGetter…...
使用yml文件安装环境时,如何添加conda和pip的镜像源
博客参考 添加conda镜像源 name: NAME channels:- conda-forge- pytorch- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2- defaults depende…...
c语言经典100例
1.字符串转为数字 #include <stdio.h>int strToInt(char *s) {int num0;int sign1;int step1;if (*s -){sign -1;s;}while (*s > 0&&*s < 9){num num*10(*s-0);step 10;s;}return num*sign; }int main() {char a[10] "-1234";char *s a ;pr…...
百易云资产管理运营系统 ufile.api.php SQL注入漏洞复现
0x01 产品描述: 百易云资产管理运营系统,是专门针对企业不动产资产管理和运营需求而设计的一套综合解决方案。该系统能够覆盖资产的全生命周期管理,包括资产的登记、盘点、评估、处置等多个环节,同时提供强大的运营分析功能&#…...
【分布式微服务云原生】《Redis RedLock 算法全解析:应对时钟漂移与网络分区挑战》
《Redis RedLock 算法全解析:应对时钟漂移与网络分区挑战》 摘要: 本文深入探讨 Redis 的 RedLock 算法,详细阐述其步骤及工作原理,同时重点分析该算法如何处理时钟漂移和网络分区这两个常见的分布式系统问题。读者将通过本文深入…...
OceanBase 的写盘与传统数据库有什么不同?
背景 在数据库开发过程中,“写盘”是一项核心操作,即将内存中暂存的数据安全地转储到磁盘上。在诸如MySQL这样的传统数据库管理系统中,写盘主要有以下几步:首先将数据写入缓存池;其次,为了确保数据的完整性…...
用Java爬虫API,轻松获取taobao商品SKU信息
在电子商务的世界里,SKU(Stock Keeping Unit,库存单位)是商品管理的基础。对于商家来说,SKU的详细信息对于库存管理、价格策略制定、市场分析等都有着重要作用。taobao作为中国最大的电子商务平台之一,提供…...
OpenHarmony 入门——ArkUI 自定义组件内同步的装饰器@State小结(二)
文章大纲 引言一、组件内状态装饰器State1、初始化2、使用规则3、变量的传递/访问规则说明4、支持的观察变化的场景5、State 变量的值初始化和更新机制6、State支持联合类型实例 引言 前一篇文章OpenHarmony 入门——ArkUI 自定义组件之间的状态装饰器小结(一&…...
你的 Android App 可能白白损失了 35% 的性能——R8 全模式配置详解
字节跳动的工程师优化启动速度时,可能花了数周分析 trace、改代码;Monzo 的团队却只改了一行配置,性能指标全线提升了 35%。这不是段子,是 Google 官方 blog 2026 年 3 月底发出来的案例。 问题来了:你的项目ÿ…...
SEO_如何通过内容优化有效提升SEO效果?(403 )
如何通过内容优化有效提升SEO效果? 在当今竞争激烈的网络环境中,如何通过内容优化有效提升SEO效果,成为了每一个网站运营者的关键问题。搜索引擎优化(SEO)是一门艺术,需要我们在内容策略和技术手段上不断探…...
Jetson硬件SSD启动盘配置与CUDA环境搭建全攻略
1. 为什么需要SSD启动盘? Jetson系列开发板(如Nano、Xavier NX等)自带的eMMC存储容量通常只有16GB或32GB,安装完JetPack基础系统后,剩余空间往往不足10GB。对于需要运行深度学习模型、处理大量数据的开发者来说&#x…...
实战演练:基于快马平台与zeroclaw理念构建高性能个人博客系统
最近在尝试用zeroclaw理念重构个人博客系统,发现这种极简高效的设计思路确实能大幅提升开发效率和运行性能。今天就来分享下基于InsCode(快马)平台实现的完整实战过程。 项目架构设计 zeroclaw的核心是"零冗余",所以在设计阶段就做了严格的功能…...
如何利用秒排 seo 快速提升关键词排名
如何利用秒排 seo 快速提升关键词排名 在互联网时代,搜索引擎优化(SEO)已经成为提升网站流量和品牌知名度的关键手段。其中,“秒排 SEO”这一概念在近几年越来越受到关注。究竟什么是“秒排 SEO”,如何利用它来快速提…...
Pixel Language Portal详细步骤:从GitHub源码构建到自定义16-bit图标替换
Pixel Language Portal详细步骤:从GitHub源码构建到自定义16-bit图标替换 1. 项目介绍与准备工作 Pixel Language Portal(像素语言跨维传送门)是一款基于Tencent Hunyuan-MT-7B翻译引擎构建的创新型翻译工具。它将传统翻译功能与16-bit像素…...
【数字信号检测】基于迫零算法大规模MIMO低复杂度信号检测附Matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。👇 关注我领取海量matlab电子书和数学建模资料🍊个人信条:格物致知,完整Matl…...
零基础玩转DeepSeek-R1推理模型:Ollama一键部署Llama-8B教程
零基础玩转DeepSeek-R1推理模型:Ollama一键部署Llama-8B教程 1. 引言:为什么选择DeepSeek-R1-Distill-Llama-8B 你是否想体验强大的文本生成能力,却被复杂的模型部署流程劝退?DeepSeek-R1-Distill-Llama-8B是一个经过优化的8B参…...
前端 SSE(Server-Sent Events)实现详解:从原理到前端 AI 对话应用
为什么前端越来越需要“流式能力”?在传统 Web 应用中,前端与后端的通信方式大多是 “请求—响应” 模式: 前端发起请求,后端计算完成后一次性返回结果。但随着应用形态的演进,这种模式越来越显得“笨重”:…...
OpenClaw语音控制之GoogleAPI 集成实战教程
11.1 Google Cloud 账号设置 在使用 Google Cloud 的任何服务之前,首先需要拥有一个 Google Cloud 账号。本节将详细介绍账号注册、项目创建和支付方式绑定的完整流程。 步骤 1:访问 Google Cloud 控制台 打开浏览器,访问 Google Cloud 控制台地址:https://console.clou…...
