《计算机视觉》—— 换脸

news2024/11/29 22:37:27
  • 效果如下:
    在这里插入图片描述
  • 完整代码:
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)     # 填充凸包,数字在0~1之间
    # 单通道im构成3通道im(3,行,列),改变形状(行、列、3)适应0penCV
    im = 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 Decomposition
    U, S, Vt = np.linalg.svd(points1.T * points2)
    R = (U * Vt).T      # 通过U和Vt找到R
    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])     # 获取关键点
    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] = 0
    return b * weight


a = 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()

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

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

相关文章

linux下使用VSCODE 调试python

文章目录 一、环境准备安装VS Code:安装Python: 二、环境测试创建Python文件:编写测试代码运行 Linux下使用VS Code调试Python 在Linux环境中进行Python开发时,一个高效、直观的调试工具是必不可少的。Visual Studio Code&#xf…

Web Hid Api浏览器读取IC卡号Js源码,无需插件支持

本示例使用的读卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bW5eU3X&ftt&id615391857885 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-trans…

【R语言】gadm全球行政区划数据库

我R语言不熟、也不是学GIS的。仅用于记录。 文章目录 一、gadm 数据库简介二、R 语言示例三、sf 包的函数 一、gadm 数据库简介 GADM&#xff08;全称Database of Global Administrative Areas&#xff09;是一个高精度的全球行政区划数据库&#xff0c;它包含了全球所有国家和…

数字图像处理:图像去噪

图像去噪–总变差去噪&#xff08;TV&#xff09; 引用资料&#xff1a; 1.全变分图像去噪算法&#xff08;TV&#xff09; 2.TV去噪的理解 总变差去噪 (Total Variation Denoising) 是一种经典的图像去噪方法&#xff0c;能够有效减少噪声&#xff0c;同时保留图像的边缘细节…

单例模式(自动加载)

目录 介绍 使用 在脚本中写一个函数 让一个「自定义场景」作为单例「自动加载」 介绍 单例模式是编程中的一种设计思想&#xff0c;是为了解决某些编程语言中没有全局变量概念而产生的这对于实现某种模块非常好用 比如玩家信息&#xff0c;有时候&#xff0c;游戏中的很多…

以太网交换安全:MAC地址漂移与检测(实验:二层环路+网络攻击)

一、什么是MAC地址漂移&#xff1f; MAC地址漂移是指网络中设备的MAC地址在运行过程中发生变化的现象。 MAC地址是用于唯一标识网络中的设备。 MAC地址漂移是指交换机上一个VLAN内有两个端口学习到同一个MAC地址&#xff0c;后学习到的MAC地址表项覆盖原MAC地址表项的现象。…

Jsoup在Java中:解析京东网站数据

对于电商网站如京东来说&#xff0c;其页面上的数据包含了丰富的商业洞察。对于开发者而言&#xff0c;能够从这些网站中提取有价值的信息&#xff0c;进行分析和应用&#xff0c;无疑是一项重要的技能。本文将介绍如何使用Java中的Jsoup库来解析京东网站的数据。 Jsoup简介 …

Windows】【DevOps】Windows Server 2022 采用WinSW 启动一个会创建新的控制台程序窗口的程序行为分析

WinSW使用参考 【Windows】【DevOps】Windows Server 2022 采用WinSW将一个控制台应用程序作为服务启动&#xff08;方便&#xff09;-CSDN博客 源码 调整ConsoleApp1程序源代码如下&#xff1a; using System; using System.Diagnostics; using System.IO; using System.R…

十、客户端与服务端进行通信

一、服务端 1、建立协议脚本 此处必须序列化才能转为二进制发送出去 IP为本地连接&#xff1b;端口随意&#xff1b;不要选择规定的端口 2、建立服务端连接脚本 这个的方法都是重写的dll文件中的代码 在Start代码中进行调用 二、客户端 1、与客户端连接代码 2、开始代码 三…

腰背肌筋膜炎有哪些治疗方法

腰背肌筋膜炎主要表现为腰背部的疼痛、酸胀、僵硬、活动受限等症状。在疾病初期&#xff0c;症状可能相对较轻&#xff0c;通过休息、保暖、适当的物理治疗等&#xff0c;往往可以缓解症状&#xff0c;此时病情不算严重。如果患者不重视&#xff0c;继续保持不良的生活习惯&…

Nexpose 6.6.273 发布,新增功能概览

Nexpose 6.6.273 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, released Oct 10, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/ 查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 您的本地…

微调小型Llama 3.2(十亿参数)模型取代GPT-4o

微调Llama VS GPT-4o 别忘了关注作者&#xff0c;关注后您会变得更聪明&#xff0c;不关注就只能靠颜值了 ^_^。 一位年轻的儿科医生与一位经验丰富的医师&#xff0c;谁更能有效治疗婴儿的咳嗽&#xff1f; 两者都具备治疗咳嗽的能力&#xff0c;但儿科医生由于专攻儿童医学…

数据中台业务架构图

数据中台的业务架构是企业实现数据驱动决策和业务创新的关键支撑。它主要由数据源层、数据存储与处理层、数据服务层以及数据应用层组成。 数据源层涵盖了企业内部各个业务系统的数据&#xff0c;如 ERP、CRM 等&#xff0c;以及外部数据来源&#xff0c;如社交媒体、行业数据…

2024年9月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析

一、单选题 1、下列选项中关于 turtle.color(red) 语句的作用描述正确的是&#xff1f;&#xff08; &#xff09; A. 只设置画笔的颜色为红色 B. 只设置填充的颜色为红色 C. 设置画笔和填充的颜色为红色 D. 设置画笔的颜色为红色&#xff0c;设置画布背景的颜色为红色 正…

基于langchain.js快速搭建AI-Agent

基于langchain.js快速搭建AI-Agent 什么是AIAgent? 1. 替换默认请求地址为自定义API 构建基础会话大模型 import { ChatOpenAI } from langchain/openai;const chat new ChatOpenAI({model: gpt4o,temperature: 0,apiKey: ****,configuration: {baseURL: https://www.xx.co…

[含文档+PPT+源码等]精品大数据项目-基于python实现的社交媒体用户活跃时间预测系统

大数据项目——基于Python实现的社交媒体用户活跃时间预测系统的背景可以从以下几个方面进行详细阐述&#xff1a; 一、项目背景与意义 随着互联网技术的快速发展和社交媒体的普及&#xff0c;社交媒体平台已经成为人们日常生活中不可或缺的一部分。每天都有数以亿计的用户在…

Golang笔记_day08

Go面试题&#xff08;一&#xff09; 1、空切片 和 nil 切片 区别 空切片&#xff1a; 空切片是指长度和容量都为0的切片。它不包含任何元素&#xff0c;但仍然具有切片的容量属性。在Go语言中&#xff0c;可以使用内置的make函数创建一个空切片&#xff0c;例如&#xff1a;…

[Godot4] 水底气泡的 gdshader

水底气泡的 gdshader 来自 shadertoy 的代码 在这里&#xff0c;我添加了 x 方向和 y 方向上的 uv 位移 但是还是感觉太弱智 shader_type canvas_item; // Created by greenbird10 // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0uniform float bub…

C语言笔记(指针的进阶)

目录 1.字符指针 2.指针数组 3.数组指针 3.1.创建数组指针 3.2.&数组名和数组名 1.字符指针 int main() { char ch w;char* pc &ch;const char *p "abcdef";//常量字符串 产生的值就是首元素的地址//常量字符串不能被修改 因此需要加上一个…

go 环境安装

最近搭建AIGC大模型聚合平台&#xff0c;涉及到了go语言&#xff0c;随手整理一下环境安装步骤分享给大家。 1、安装 官网下载地址&#xff1a;https://go.dev/ 1.1 Linux 安装 yum install git -y yum install golang -y yum install gcc -y # 日志工具&#xff0c;如需要…