python:faces swap

# encoding: utf-8
# 版权所有 2024 ©涂聚文有限公司
# 许可信息查看: 两个头像图片之间换脸
# 描述: https://stackoverflow.com/questions/902761/saving-a-numpy-array-as-an-image?answertab=votes
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 311
# Datetime  : 2024/6/13 10:25
# User      : geovindu
# Product   : PyCharm
# Project   : EssentialAlgorithms
# File      : imageFaceSwapFun.py
# explain   : 学习
import cv2
import numpy as np
import dlib
from PIL import Image as im
 
class FaceSwaFun(object):
    """
    换脸类
    """
    def __init__(self,SOURCEPATH,DESTPATH):
        """
        实例化
        :param SOURCEPATH: 需要用脸的图片
        :param DESTPATH: 用脸目标图片
        """
        self.SOURCE_PATH=SOURCEPATH
        self.DEST_PATH=DESTPATH
 
 
    def index_from_array(self,numpyarray):
        """
 
        :param numpyarray:
        :return:
        """
        index = None
        for n in numpyarray[0]:
            index = n
            break
        return index
 
    def getImage(self)-> tuple:
        """
 
        :return: 返回 (图片的数组,保存的文件名)
        """
        frontal_face_detector = dlib.get_frontal_face_detector()
        frontal_face_predictor = dlib.shape_predictor("dataset/shape_predictor_68_face_landmarks.dat")
 
        source_image = cv2.imread(self.SOURCE_PATH)
        source_image_grayscale = cv2.cvtColor(source_image, cv2.COLOR_BGR2GRAY)
        #
        destination_image = cv2.imread(self.DEST_PATH)
        destination_image_grayscale = cv2.cvtColor(destination_image, cv2.COLOR_BGR2GRAY)
 
        source_image_canvas = np.zeros_like(source_image_grayscale)
        height, width, no_of_channels = destination_image.shape
        destination_image_canvas = np.zeros((height, width, no_of_channels), np.uint8)
 
        source_faces = frontal_face_detector(source_image_grayscale)
 
        # Obtaining source face landmark points, convex hull, creating mask and also getting delaunay triangle face landmark indices for every face
        for source_face in source_faces:
            source_face_landmarks = frontal_face_predictor(source_image_grayscale, source_face)
            source_face_landmark_points = []
            for landmark_no in range(68):
                x_point = source_face_landmarks.part(landmark_no).x
                y_point = source_face_landmarks.part(landmark_no).y
                source_face_landmark_points.append((x_point, y_point))
 
            source_face_landmark_points_array = np.array(source_face_landmark_points, np.int32)
            source_face_convexhull = cv2.convexHull(source_face_landmark_points_array)
 
            cv2.fillConvexPoly(source_image_canvas, source_face_convexhull, 255)
            source_face_image = cv2.bitwise_and(source_image, source_image, mask=source_image_canvas)
 
            # DELAUNAY TRIANGULATION
 
            bounding_rectangle = cv2.boundingRect(source_face_convexhull)
            subdivisions = cv2.Subdiv2D(bounding_rectangle)
            subdivisions.insert(source_face_landmark_points)
            triangles_vector = subdivisions.getTriangleList()
            triangles_array = np.array(triangles_vector, dtype=np.int32)
 
            triangle_landmark_points_list = []
            source_face_image_copy = source_face_image.copy()
 
            for triangle in triangles_array:
                index_point_1 = (triangle[0], triangle[1])
                index_point_2 = (triangle[2], triangle[3])
                index_point_3 = (triangle[4], triangle[5])
 
                index_1 = np.where((source_face_landmark_points_array == index_point_1).all(axis=1))
                index_1 = self.index_from_array(index_1)
                index_2 = np.where((source_face_landmark_points_array == index_point_2).all(axis=1))
                index_2 = self.index_from_array(index_2)
                index_3 = np.where((source_face_landmark_points_array == index_point_3).all(axis=1))
                index_3 = self.index_from_array(index_3)
 
                triangle = [index_1, index_2, index_3]
                triangle_landmark_points_list.append(triangle)
 
        destination_faces = frontal_face_detector(destination_image_grayscale)
 
        # Obtaining destination face landmark points and also convex hull for every face
        for destination_face in destination_faces:
            destination_face_landmarks = frontal_face_predictor(destination_image_grayscale, destination_face)
            destination_face_landmark_points = []
            for landmark_no in range(68):
                x_point = destination_face_landmarks.part(landmark_no).x
                y_point = destination_face_landmarks.part(landmark_no).y
                destination_face_landmark_points.append((x_point, y_point))
 
            destination_face_landmark_points_array = np.array(destination_face_landmark_points, np.int32)
            destination_face_convexhull = cv2.convexHull(destination_face_landmark_points_array)
 
        # Iterating through all source delaunay triangle and superimposing source triangles in empty destination canvas after warping to same size as destination triangles' shape
        for i, triangle_index_points in enumerate(triangle_landmark_points_list):
            # Cropping source triangle's bounding rectangle
 
            source_triangle_point_1 = source_face_landmark_points[triangle_index_points[0]]
            source_triangle_point_2 = source_face_landmark_points[triangle_index_points[1]]
            source_triangle_point_3 = source_face_landmark_points[triangle_index_points[2]]
            source_triangle = np.array([source_triangle_point_1, source_triangle_point_2, source_triangle_point_3],
                                       np.int32)
 
            source_rectangle = cv2.boundingRect(source_triangle)
            (x, y, w, h) = source_rectangle
            cropped_source_rectangle = source_image[y:y + h, x:x + w]
 
            source_triangle_points = np.array([[source_triangle_point_1[0] - x, source_triangle_point_1[1] - y],
                                               [source_triangle_point_2[0] - x, source_triangle_point_2[1] - y],
                                               [source_triangle_point_3[0] - x, source_triangle_point_3[1] - y]],
                                              np.int32)
 
            # Create a mask using cropped destination triangle's bounding rectangle(for same landmark points as used for source triangle)
 
            destination_triangle_point_1 = destination_face_landmark_points[triangle_index_points[0]]
            destination_triangle_point_2 = destination_face_landmark_points[triangle_index_points[1]]
            destination_triangle_point_3 = destination_face_landmark_points[triangle_index_points[2]]
            destination_triangle = np.array(
                [destination_triangle_point_1, destination_triangle_point_2, destination_triangle_point_3], np.int32)
 
            destination_rectangle = cv2.boundingRect(destination_triangle)
            (x, y, w, h) = destination_rectangle
 
            cropped_destination_rectangle_mask = np.zeros((h, w), np.uint8)
 
            destination_triangle_points = np.array(
                [[destination_triangle_point_1[0] - x, destination_triangle_point_1[1] - y],
                 [destination_triangle_point_2[0] - x, destination_triangle_point_2[1] - y],
                 [destination_triangle_point_3[0] - x, destination_triangle_point_3[1] - y]],
                np.int32)
 
            cv2.fillConvexPoly(cropped_destination_rectangle_mask, destination_triangle_points, 255)
 
            # Warp source triangle to match shape of destination triangle and put it over destination triangle mask
 
            source_triangle_points = np.float32(source_triangle_points)
            destination_triangle_points = np.float32(destination_triangle_points)
 
            matrix = cv2.getAffineTransform(source_triangle_points, destination_triangle_points)
            warped_rectangle = cv2.warpAffine(cropped_source_rectangle, matrix, (w, h))
 
            warped_triangle = cv2.bitwise_and(warped_rectangle, warped_rectangle,
                                              mask=cropped_destination_rectangle_mask)
 
            # Reconstructing destination face in empty canvas of destination image
 
            # removing white lines in triangle using masking
            new_dest_face_canvas_area = destination_image_canvas[y:y + h, x:x + w]
            new_dest_face_canvas_area_gray = cv2.cvtColor(new_dest_face_canvas_area, cv2.COLOR_BGR2GRAY)
            _, mask_created_triangle = cv2.threshold(new_dest_face_canvas_area_gray, 1, 255, cv2.THRESH_BINARY_INV)
 
            warped_triangle = cv2.bitwise_and(warped_triangle, warped_triangle, mask=mask_created_triangle)
            new_dest_face_canvas_area = cv2.add(new_dest_face_canvas_area, warped_triangle)
            destination_image_canvas[y:y + h, x:x + w] = new_dest_face_canvas_area
 
        # Put reconstructed face on the destination image
        final_destination_canvas = np.zeros_like(destination_image_grayscale)
        final_destination_face_mask = cv2.fillConvexPoly(final_destination_canvas, destination_face_convexhull, 255)
        final_destination_canvas = cv2.bitwise_not(final_destination_face_mask)
        destination_face_masked = cv2.bitwise_and(destination_image, destination_image, mask=final_destination_canvas)
        destination_with_face = cv2.add(destination_face_masked, destination_image_canvas)
 
        # Seamless cloning to make attachment blend with surrounding pixels
 
        # we have to find center point of reconstructed convex hull to pass into seamlessClone()
        (x, y, w, h) = cv2.boundingRect(destination_face_convexhull)
        destination_face_center_point = (int((x + x + w) / 2), int((y + y + h) / 2))
        seamless_cloned_face = cv2.seamlessClone(destination_with_face, destination_image, final_destination_face_mask,
                                                 destination_face_center_point, cv2.NORMAL_CLONE)
 
        data = im.fromarray(seamless_cloned_face)
 
        # saving the final output
        # as a PNG file
        file='geovindu.png'
        data.save(file)
 
        #cv2.imshow("Destination image with source face 2", seamless_cloned_face)
        #cv2.waitKey(0)
        #cv2.destroyAllWindows()
        print(type(seamless_cloned_face))
        return (seamless_cloned_face,file)
 
        '''
        1.
        import cv2
        cv2.imwrite("geovindu.jpg", seamless_cloned_face)
        2.
        from PIL import Image
        im = Image.fromarray(seamless_cloned_face)
        im.save("geovindu.jpg")
        3.
        import scipy.misc
        scipy.misc.imsave('geovindu.jpg', seamless_cloned_face)
        4.
        import scipy.misc
        scipy.misc.toimage(seamless_cloned_face, cmin=0.0, cmax=...).save('geovindu.jpg')
        5.
        import matplotlib
        matplotlib.image.imsave('geovindu.png', seamless_cloned_face)
 
        '''

調用:

# 调用
    du= BLL.imageFaceSwapFun.FaceSwaFun("media/images/modi.jpg","media/images/viplav.jpeg")
    #du.SOURCE_PATH="media/images/modi.jpg"
    # du.DEST_PATH="media/images/viplav.jpeg"
    geovindu=du.getImage()
    print(geovindu)
    cv2.imwrite("geovindu20.png", geovindu[0])

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

低成本,高性能:10 万美元实现Llama2-7B级性能

高性能的语言模型如Llama2-7B已经成为推动自然语言处理技术进步的重要力量。然而,这些模型往往需要昂贵的计算资源和庞大的研发投入,使得许多研究团队和小型企业望而却步。现在,JetMoE架构以其创新的设计和优化策略,不仅成功地在只…

PC微信逆向) 定位微信浏览器打开链接的call

首发地址: https://mp.weixin.qq.com/s/Nik8fBF3hxH5FPMGNx3JFw 前言 最近想写一个免费的微信公众号自动采集的工具,我看公众号文章下载需求还挺多的。搜了下github,免费的工具思路大多都是使用浏览器打开公众号主页获取到需要的请求参数,例…

云化XR什么意思,Cloud XR是否有前景?

云化XR(CloudXR)什么意思? 云化XR(CloudXR)是一种基于云计算技术的扩展现实(XR)应用方式,将XR体验从本地设备转移到云端进行处理和交付。它通过将计算和渲染任务放置在云端服务器上…

Linux基础IO【II】真的很详细

目录 一.文件描述符 1.重新理解文件 1.推论 2.证明 2.理解文件描述符 1.文件描述符的分配规则 3.如何理解文件操作的本质? 4.输入重定向和输出重定向 1.原理 2.代码实现重定向 3.dup函数 ​编辑 4.命令行中实现重定向 二.关于缓冲区 1.现象 …

Modbus转Profinet网关的IP地址怎么设置

在工业自动化领域,Modbus和Profinet是两种常用的通信协议,而网关可以实现不同协议之间的转换,使得不同设备能够互相通信。本文将详细介绍如何设置Modbus转Profinet网关(XD-MDPN100)的IP地址,让您轻松实现设…

vue相关的2个综合案例,网页打字练习

for循环的应用 /* 1. 用for循环控制台打印0到100 */ for (var i 0; i < 100; i) {console.log(i) } /* 2. 用for循环控制台打印100到0 */ for (var i 100; i > 0; i--) {console.log(i) }网页打字练习案例练习 <template><div class"main"><…

洛谷P1305 新二叉树(树的基本遍历)

题目描述 输入一串二叉树&#xff0c;输出其前序遍历。 输入格式 第一行为二叉树的节点数 &#x1d45b;。(1≤&#x1d45b;≤26) 后面 &#x1d45b; 行&#xff0c;每一个字母为节点&#xff0c;后两个字母分别为其左右儿子。特别地&#xff0c;数据保证第一行读入的节点…

IPTCP知识

1. IP&#xff1a; IP地址是一个32位的二进制数&#xff0c;通常被分割为4个“8位二进制数”IP地址分类&#xff1a;A类地址、B类地址、C类地址、D类地址、E类地址 A类地址分配给规模特别大的网络使用&#xff0c;B类地址分配给一般的中型网络&#xff0c;C类地址分配给小型网…

STM32无法烧写程序的故障排除

如果你在使用STM32微控制器时遇到无法烧写程序的问题&#xff0c;可以按以下步骤进行故障排除&#xff1a; 1. 确认硬件连接 检查电源&#xff1a;确保STM32板子正确供电。调试器连接&#xff1a;确认ST-LINK调试器或其他编程工具与STM32开发板的连接无误&#xff0c;尤其是S…

如何基于 Python 快速搭建 QQ 开放平台 QQ 群官方机器人详细教程(更新中)

注册 QQ 开放平台账号 账号注册 QQ 机器人&#xff1a;一个机器人可以被添加到 群聊/频道 内对话&#xff0c;QQ 用户也可以直接跟机器人 单独对话。 开发者账号主体要求 单聊对话&#xff1a;【定向邀请】 群聊场景&#xff1a;仅支持企业主体【个人主体暂不支持】 频道场…

基于uni-app与图鸟UI打造的各领域移动端模板大赏

随着移动互联网的迅猛发展&#xff0c;各类移动端应用层出不穷&#xff0c;为了帮助企业快速搭建高效、美观的移动平台&#xff0c;我们基于强大的uni-app与图鸟UI&#xff0c;精心打造了不下于40套覆盖多个领域的移动端模板。今天&#xff0c;就让我们一起领略这些模板的风采吧…

淘宝镜像地址失效

1. 使用nvm安装node时候报错 报错内容 Get "https://npm.taobao.org/mirrors/node/latest/SHASUMS256.txt": tls: failed to verify certificate: x509: certificate has expired or is not yet valid:报错原因 淘宝镜像地址的证书过期了 解决 找到nvm安装的根目…

Java-集合类-Arrays.asList()使用需要注意的大坑

Arrays.asList使用需要注意的大坑 大坑1.不可修改列表大小&&原始数组与列表共享数据2.对于基本类型数组的使用限制 两个错误案例wrong1wrong2 ​ Arrays.asList() 是 Java 中一个常用的方法&#xff0c;它 用于将数组转换为列表&#xff08;List&#xff09;。这个方…

Bybatis动态SQL的绑定和公共sql语句片段

Mybatis除了大部分动态标签&#xff0c;最后还有三个标签&#xff0c;分别是bind&#xff0c;sql和include&#xff1a; ①bind&#xff1a;这个标签作用就是将OGNL标签里的值&#xff0c;进行二次加工&#xff0c;在绑定到另一个变量里&#xff0c;供其他标签使用 调用getUse…

Java—集合简述

集合类继承结构图 Collection|---------------------| | | Set List Queue| | | SortedSet ArrayList Deque| LinkedList | NavigableSet Vector ArrayDeque| Stack | TreeSet …

数据结构笔记-2、线性表

2.1、线性表的定义和基本操作 如有侵权请联系删除。 2.1.1、线性表的定义&#xff1a; ​ 线性表是具有相同数据类型的 n (n>0) 个数据元素的有限序列&#xff0c;其中 n 为表长&#xff0c;当 n 0 时线性表是一个空表。若用 L 命名线性表&#xff0c;则其一般表示为&am…

【软件工程导论】——期末复习(冲刺篇)

&#x1f4d6; 前言&#xff1a;快考试了&#xff0c;做篇期末总结&#xff0c;都是重点与必考点。 题型&#xff1a;材料分析题、简答题、看图分析题 课本&#xff1a; 目录 &#x1f552; 1. 软件生存周期与软件过程&#x1f558; 1.1 软件生存周期&#x1f558; 1.2 传统…

Java老人护理上门服务类型系统小程序APP源码

&#x1f338; 老人上门护理服务系统&#xff1a;温暖与专业并存 &#x1f338; 一、&#x1f3e0; 走进老人上门护理服务系统 随着社会的快速发展&#xff0c;我们越来越关注老年人的生活质量。老人上门护理服务系统应运而生&#xff0c;它结合了现代科技与人性化服务&#…

webpack代码分割

webpack代码分割方式 entry配置&#xff1a;通过多个 entry 文件来实现动态加载(按需加载)&#xff1a;通过主动使用import来动态加载抽取公共代码&#xff1a;使用splitChunks配置来抽取公共代码 基础概念 概念含义Entry入口&#xff0c;Webpack 执行构建的第一步将从 Entr…

Adobe Illustrator (AI)小技巧总结

AI2024(64bit) Adobe Illustrator 软件安装包下载地址&#xff1a; 百度网盘下载https://pan.baidu.com/s/1C10-2JVN1rxFF5VFRuV2Yw?pwdSIMS 1.效果-扭曲与变换-变换&#xff0c;两个图形组合&#xff08;CtrlG&#xff09;中心点在中间 例&#xff1a;角度7.5副本24半圆48格…