用Python实现AI换脸

AI换脸要求把两张人脸的面部内容进行交替,并且能够尽量地进行拟合。

我们首先在互联网上下载两张图片:(妹子证件照不好找,用下面两位哥的图片凑合一下)

换脸技术在现在看来已经不是那么热门了,已经有很多应用软件都实现了换脸技术。

但是我不建议使用它们的软件,它们前期开发的这些软件,目的就是收集你的人脸信息,帮助训练他们的数据模型。

所谓的搞人工智能相关的人才,一类是专门做学术研究的,研究这些算法的;还有一类是专门应用这些算法的。而大家所了解的一些换脸这些应用,它是免费开放给你用的。但你要知道,它也是有研发成本的,不是无缘无故就免费给你用的。它需要去收集大量的用户人脸数据,方便训练他自己的模型。如果你去了解一些谷歌开源的一些人工智能框架,或者其他公司给你开源的人工智能框架,你会发现框架的东西,包括有一些算法,其实已经有人提出来了,也有些人的是能够理解掌握的。但关键的是支撑这些算法的数据,它没有给你开放。

我们今天实现的内容是:实现两张图片中人脸面部信息的交换。

需要用到的工具

import json
import base64
import requests

其中json和base64是python自带的,requests是第三方的包。

换脸的思路很简单,我们甚至可以使用截图工具,把一张脸截取替换另一张脸上。但是,使用python操作图像并不是那么简单,我们要考虑的东西有很多。

首先,需要识别图像当中脸部的轮廓。

人类可以很轻松的识别什么是脸,什么是肩膀,什么是背景,而计算机并不知道。

它需要有一系列的算法,以及建立所谓的模型来识别人脸。

利用这些算法可以智能的实现人脸面部信息的识别。当然也可以去GitHub上找一些现成的,别人训练好的模型。

如果要自己训练,就需要通过爬虫在互联网上下载大量的人脸图片数据,通过这些数据来训练模型,使其达到人工智能的要求。

这对于我这样一个新手小白来说是短期内无法完成的,我们没有人工智能的理论基础和实践经验,更没有海量的数据。算法我们尚且可以学习,原理不难,但操作起来难以理解。但大量的数据我们却没有。谷歌公司的强大之处很大程度就在于它真正掌握了那些我们想都不敢想的海量数据。

为了实现功能,我们需要站在巨人的肩膀上,调用已有的工具,即已经训练好的模型。(使用轮子)

实现步骤:

找到人脸数据,不光光是脸部的轮廓,还有脸部的大小,眼睛鼻子的大小。

拟合,拼接人脸

# 找到人脸数据
def find_face():
pass
# 拟合,拼接人脸
def merge_face():
pass

找到人脸

注册旷视:https://console.faceplusplus.com.cn/login

它可以提供人脸识别,人体识别,证件识别,图像识别等api,前提是需要注册。

API接口:

https://api-cn.faceplusplus.com/facepp/v3/detect

这个接口的作用就是帮助我们找到人脸相关的数据,你只需要把图像传给它,就就可以通过调用后台服务器的运算,对图像进行处理,并把处理后的结果返回。

注册完成以后,点击创建我的应用,即可生成试用版的 api_key 和 api_secret

因为要携带数据,所以使用post请求,携带的数据不仅包含api_key 和 api_secret,同时也包含img_url和return_landmark。

img_url表示图片的路径,return_landmark则表示返回的人脸区域坐标。

除了携带参数的请求,也可以携带一个文件去请求,就好比上传一个文件。

files = {'image_file':open(imgpath)}

拼接人脸

拼接人脸的第一个,先获取两张图片的脸部轮廓数据。

然后进行换脸,需要用到用到一个接口:

https://api-cn.faceplusplus.com/imagepp/v1/mergeface

我们说调用别人的接口,就必须别人的规范,传递的参数类型,参数值都要符合人家的要求。

参数包含:

api_key

api_secret

template_base64:base64编码后的模板图片

template_rectangle:字符串格式的脸部数据

merge_base64:编码后的待合并图片

merge_rectangle:字符串格式的脸部数据

merge_rate:相似度

这里总结两种json格式转化为字典格式的方法:

1、

req_dict = json.loads(req_con)

2、

req_dict = json.JSONDecoder().decode(req_con)

文件读取:

f1 = open(img_url1,'rb')
f1_64 = base64.b64encode(f1.read()) #编码
f1.close()

文件写入:

file = open(img_url3,'wb')
file.write(imgdata)
file.close()

在相似度设置为100的情况下,合并后的图片效果对比:

改变两张图片的位置,效果:

相似度设置为30,也就是相当于没有100%换脸,只是换了30%,效果就不粘贴了。

全部代码

import json
import base64
import requests
# 算法
# 构建模型
# 训练模型 ---> 需要数据集
# 找到人脸数据
def find_face(imgpath):
http_url = 'https://api-cn.faceplusplus.com/facepp/v3/detect'
#参数
data = {
'api_key': '你自己的api_key',
'api_secret': '你自己的api_secret',
'img_url':imgpath,
'return_landmark':1
}
#文件
files = {'image_file':open(imgpath,'rb')}#rb表示二进制的读取
# 携带数据的请求我们通常使用post请求
resp = requests.post(http_url,data=data,files=files)
#req_con是个json格式的数据
req_con = resp.text
#类型转换
this_dict = json.loads(req_con)
faces = this_dict['faces']
list0 = faces[0]
#得到人脸框的数据
rectangle = list0['face_rectangle']
print(rectangle)
return rectangle
# 拟合,拼接人脸
def merge_face(img_url1,img_url2,img_url3,number):
"""
:param img_url1: 第一张图像
:param img_url2: 第二张图像
:param img_url3: 合并后的效果图
:param number:相似度
:return:
"""
#分别获取第一张图片和第二张图片的人脸数据
ff1 = find_face(img_url1)
ff2 = find_face(img_url2)
#因为参数需要是字符串类型,而ff1和ff2都是字典,我们需要格式转换
rectangle1 = str( str(ff1['top'])+","+str(ff1['left'])+","+str(ff1['width'])+","+str(ff1['height']) )
rectangle2 = str( str(ff2['top'])+","+str(ff2['left'])+","+str(ff2['width'])+","+str(ff2['height']) )
print(rectangle1)
print(rectangle2)
f1 = open(img_url1,'rb')
f1_64 = base64.b64encode(f1.read()) #编码
f1.close()
f2 = open(img_url2, 'rb')
f2_64 = base64.b64encode(f2.read()) # 编码
f2.close()
#合并,我们需要使用另一个接口
url_add = 'https://api-cn.faceplusplus.com/imagepp/v1/mergeface'
data = {
'api_key': '你自己的api_key',
'api_secret': '你自己的api_secret',
'template_base64':f1_64,'template_rectangle':rectangle1,
'merge_base64':f2_64,'merge_rectangle':rectangle2,
'merge_rate':number
}
resp = requests.post(url_add,data=data)
req_con = resp.text
# req_dict = json.loads(req_con)
# 把json转化为字典,作用和上面那个一样,殊途同归
req_dict = json.JSONDecoder().decode(req_con)
result = req_dict['result']
imgdata = base64.b64decode(result)
file = open(img_url3,'wb')#用wb写入这张图像
file.write(imgdata)
file.close()
if __name__=="__main__":
img1 = r"E:\test\1.jpg"
img2 = r"E:\test\2.jpg"
img3 = r"E:\test\result.jpg"
merge_face(img1,img2,img3,30)

免责声明:
本案例使用到的图片来源于互联网,仅供个人学习使用,侵删。

相关文章

Python自动生成手绘、证件照、九宫格...太炫酷了

Python像是叮当猫的口袋,几乎什么都能做,适合外行小白们去摸索学习,能极大的增加对编程的兴趣。有些工具用python来实现不一定是技术上的最优选择,但可能是最简洁、最面向大众的。介绍几个不错的处理...

教你使用python编程绘制函数图像

函数公式很抽象,图像更直观,但聪明的我们总不会手画图像吧?来学习一下用Python怎么画函数图像吧。首先打开Visual Studio Code(后面简称VSCode),点击New File(中文版是...

新手必看!如何用Python绘制复杂函数图像

在数据可视化的奇妙世界里,Python 就像是一把万能钥匙,能够帮我们打开一扇扇通往复杂函数图像绘制的大门。今天,就跟着我一起来探索如何用 Python 绘制那些令人惊叹的复杂函数图像吧!对于数学爱好...

怎么做到的?用python制作九宫格图片,太棒了

1. ? 应用场景 ?当初的想法是:想把一张图切割成九等份,发布到微信朋友圈,切割出来的图片,上传到朋友圈,发现微信不按照我排列的序号来排版。这样的结果是很耗时间的。让我深思,能不能有一种,直接拼接成...

python调用 stable diffusion批量生成图片代码解析

文中大多数内容来源github,版权属于原作者,1. 基础环境在windows上做示例,本地要安装了pythonpython的pip模块 安装 webuiapi编辑器 pyCharm 2024.2(c...

python图像处理入门-提取轮廓

提取图像中物体的轮廓,通常用在图像识别中,比如图像像素级分割,应用面比较广。import cv2 import numpy as np from skimage.measure import fi...