python:faces swap

news2025/1/13 18:20:38

# 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])

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

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

相关文章

(几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。

(几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。计 算六边形面积的公式是: 这里的s就是边长。下面是一个运行示例 package myjava; import java.math.*; import java.util.Scanner; public class cy {public static void main(S…

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

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

STM32理论 —— μCOS-Ⅲ(2/2):时间管理、消息队列、信号量、任务内嵌信号量/队列、事件标志、软件定时器

文章目录 9. 时间管理9.1 OSTimeDly()9.2 OSTimeDlyHMSM()9.3 OSTimeDlyResume()9.4 延时函数实验 10. 消息队列10.1 创建消息队列函数OSQCreate()10.2 发送消息到消息队列函数(写入队列)OSQPost()10.3 获取消息队列中的消息函数(读出队列)OSQPend()10.4 消息队列操作实验 11. …

【因果推断python】32_合成控制2

目录 合成控制作为线性回归的一种实现​编辑 合成控制作为线性回归的一种实现 为了估计综合控制的治疗效果,我们将尝试构建一个类似于干预期之前的治疗单元的“假单元”。然后,我们将看到这个“假单位”在干预后的表现。合成控制和它所模仿的单位之间的…

Apollo配置中心最佳实践

携程配置中心地址:GitCode - 全球开发者的开源社区,开源代码托管平台 1.1 Apollo配置中心介绍 Apollo(阿波罗)是开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端…

又一个对标Sora的AI视频工具,Dream Machine,开始免费试用

新的AI视频工具又又来了-Dream Machine,开始免费试用。 地址:https://lumalabs.ai/dream-machine 该工具需要科学上网 先看一下官网的宣传视频 luma AI 发布 Dream Machine 我生成了几个视频,效果还可以 生成视频很简单 只需要输入描述就可…

高等数学笔记(一):映射与函数

一、映射 1.1 映射的概念 存在一个法则 f ,使得对 X 中每个元素 x ,在 Y 中有唯一确定的元素 y 与之对应(X、Y 非空集) 称 f 为从 X 到 Y 的映射,如图所示 其中 y 称为元素 x(在映射 f 下)的…

高交会专题展—2024BTE第8届国际生物技术大会暨展览会

第二十六届中国国际高新技术成果交易会 THE 26th CHINA HI-TECH FAIR BTE第8届国际生物技术大会暨展览会 The 8th International Bio-technology Conference & Expo 2024年11月14-16日 深圳国际会展中心 展位预定:137交易会1016交易会3299 龚经理 组织机构…

企业商家如何精明选择软件开发公司

在当今信息化社会,企业的运营和发展已经离不开软件系统的支持。而选择一个合适的软件开发公司,则成为了企业商家在信息化道路上的一大挑战。那么,究竟如何挑选出既符合业务需求,又能保障项目成功的软件开发公司呢? 明…

【第5章】Vue之API风格

文章目录 前言一、选项式 API(Options API)1. 代码2. 效果 二、组合式 API(Composition API)1. 代码2. 效果 三、两者之间的区别总结 前言 Vue.js 提供了两种主要的 API 风格来组织组件的代码:选项式 API(…

SAP MMRV/MMPV 物料账期月结月底月初开关

公告:周一至周五每日一更,周六日存稿,请您点“关注”和“在看”,后续推送的时候不至于看不到每日更新内容,感谢。 这是一条刮刮乐,按住全部选中:点关注的人最帅最美,欢迎&#xff1…

码农学点儿经济学-博傻理论

博傻理论 一位石油大佬去天堂开会,他兴冲冲地跑进会议室,却发现座无虚席,早已经没了他的座位。于是他灵机一动,大喊一声:大家注意啦!听说,有人在地狱发现了石油!此言一出&#xff0c…

(财务应用程序:计算利息)

(财务应用程序:计算利息)如果知道收支余额和年利率的百分比,就可以使用下面的 公式计算: 编写程序,读取收支余额和年百分利率,显示下月利息。下面是一个运行示例: package myjava; import java.math.*; import java.util.Scanner;…

10.4 Go 并发模式

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

使用Arthas查看方法的参数信息情况

使用Arthas查看方法的参数信息情况 前言 最近在排查一个bug,需要看看一个接口方法的传参,但是方法里并没有打印传参,而且还是生产环境,更新包也麻烦,所以,准备安装一下Arthas,通过Arthas可以做…

iText7——画发票PDF(完整)

显示描述&#xff1a; 1、每页显示必须带有发票头、“销售方和购买方信息” 2、明细填充为&#xff1a;当n≤8 行时&#xff0c;发票总高度140mm&#xff0c;每条发票明细行款高度4.375mm&#xff1b; 当8<n≤12行时&#xff0c;发票高度增加17.5mm&#xff0c;不换页&#…

Flink任务如何跑起来之 2.算子 StreamOperator

Flink任务如何跑起来之 2.算子 StreamOperator 前文介绍了Transformation创建过程&#xff0c;大多数情况下通过UDF完成DataStream转换中&#xff0c;生成的Transformation实例中&#xff0c;核心逻辑是封装了SimpleOperatorFactory实例。 UDF场景下&#xff0c;DataStream到…

python怎么显示行号

我们如果想让Python IDLE显示行号&#xff0c;我们可以通过扩展IDLE功能来做到。 1.我们需要下载一个LineNumber.py扩展。 2.我们打开Python安装目录&#xff0c;找到安装目录下的Lib\idlelib目录&#xff0c;复制LineNumber到这个目录。 3.然后启动扩展。 4.配置扩展的方式…

CCF 矩阵重塑

第一题&#xff1a;矩阵重塑&#xff08;一&#xff09; 本题有两种思路 第一种 &#xff08;不确定是否正确 但是100分&#xff09; #include<iostream> using namespace std; int main(){int n,m,p,q,i,j;cin>>n>>m>>p>>q;int a[n][m];for(i…