本篇博客介绍了如何通过百度提供的应用程序接口生成动漫头像,先说测试结果,总体效果还是不错的,首先最好是女士的照片,自拍大头照最好,因为脸部的二次元效果是最好的,其它地方只是趋于动漫的效果,另外不建议男士使用这个程序,因为真的是:太丑了(实测)!!!
这个图片转动漫的效果实现主要是依靠百度的API(Application Programming Interface)进行实现的,代码并不复杂,首先登录百度智能云(百度账号即可),我们可以看到右侧的人工智能下面的分类:图像特效
进入之后,我们可以选择创建应用,填写应用名称和下方的应用描述提交即可。
创建成功之后,我们选择管理应用,可以看到里面有我们接下来需要用到的API Key和Secret Key,我们将其复制下来备用。
在开始写代码之前,我们可以看一下百度对这个API调用的文档说明,主要是两篇文章,链接我放在下方的“参阅”中,从文档中我们可以了解到,我们首先需要获取到一个Access Token,因为百度API开放平台规定了调用API时必须在URL中带上access_token参数,所以我在代码中写了一个getAccessToken方法,运行该方法之后会返回(return)一个我们想要的access_token,由于我们使用了requests库,所以需要提前使用pip下载requests库:
"""
face anime test;
convert all pictures(now include png, jpg) in the folder to anime pictures;
anime pic will exist in the "anime" folder;
"""
import requests #该库需使用pip下载
import base64 #用于将图片转为base64位编码
import os
import random
def getAccessToken():
host = "https://aip.baidubce.com/oauth/2.0/token?"
params = {
"grant_type": "client_credentials", # 固定
"client_id": "API Key", # your API Key
"client_secret": "Secret Key", # your Secret Key
}
response = requests.post(host, params)
if response:
return response.json()['access_token']
在获取到这个参数之后,我们再向指定的url提交图片(需转变成base64位编码),即可获取到百度返回的动漫图片base64,我们再将其转存为图片即可,我们还可以根据mask_id类别来控制生成的口罩形状。
request_url = "https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime"
# 二进制方式打开图片文件
f = open('test.jpg', 'rb')
img = base64.b64encode(f.read())
params = {"image":img}
access_token = response.json()['access_token'] # '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
print (response.json())
f = open("result.jpg", 'wb')
anime = response.json()['image']
anime = base64.b64decode(anime)
f.write(anime)
f.close()
大致的人脸动漫程序逻辑便是如此,当然我将程序完善了一下,目前程序具有的功能:
- 可以选择是否为图片生成戴口罩的动漫图片,如果选择戴口罩,将会为头像随机戴上8种口罩之一。
"""
if you don't wanna a mask, you can change this number to anything
"""
need_mask = 1
- 自动搜寻与该程序同文件夹下的所有png及jpg格式的图片,当然,你还可以添加你想要的图片格式。
def listMyImg():
my_Img_List = []
img_type = ["png", "jpg"] # picture format you want
for i in range(len(os.listdir())):
if os.listdir()[i].split(".")[-1] in img_type:
my_Img_List.append(os.listdir()[i])
return my_Img_List
- 程序将会在当前文件夹下生成一个"anime"文件夹(如果不存在该文件夹的话),用于存放生成的动漫图片,所有生成的动漫图片都将保持原名,并在其前面加入了前缀名"anime_"以区别原始图片。
注意事项:
在运行代码之前,请先确保自己的电脑安装了python3版本!并检查缩进格式是否正确,python要求代码的缩进均为制表符或者均为空格(4个),如果缩进格式不对,控制台将会报“IndentationError”错误。
当然,百度API开放文档中不仅仅介绍了python实现的方法,还介绍了PHP, JAVA等语言的实现,有兴趣可以了解下。每个百度云账户有500次的免费使用额度,对于个人学习、研究来说是足够了。
参考
人像动漫化文档:
https://cloud.baidu.com/doc/IMAGEPROCESS/s/Mk4i6olx5#%E8%BF%94%E5%9B%9E%E8%AF%B4%E6%98%8E
鉴权认证机制文档:
https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu
完整源代码如下:
# -*- coding: utf-8 -*-
"""
face anime test;
convert all pictures(now include png, jpg) in the folder to anime pictures;
anime pic will exist in the "anime" folder;
"""
import requests
import base64 #用于将图片转为base64位编码
import os
import random
"""
if you don't wanna a mask, you can change this number to anything
"""
need_mask = 1
# pic output folder
output_folder = "anime"
def getAccessToken():
host = 'https://aip.baidubce.com/oauth/2.0/token?'
params = {
"grant_type": "client_credentials", # 固定
"client_id": "API Key", # API Key
"client_secret": "Secret Key", # Secret Key
}
response = requests.post(host, params)
if response:
return response.json()['access_token']
else:
print("check your params!\n")
def listMyImg():
my_Img_List = []
img_type = ["png", "jpg"] # picture format you want
for i in range(len(os.listdir())):
if os.listdir()[i].split(".")[-1] in img_type:
my_Img_List.append(os.listdir()[i])
print(f"my_Img_List: {my_Img_List}")
return my_Img_List
def imgToAnime():
request_url = "https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime"
img_List = listMyImg()
for i in range(len(img_List)):
f = open(img_List[i], 'rb')
img = base64.b64encode(f.read())
if needMask():
mType = "anime_mask"
mask_id = random.randint(1,8)
params = {
"image":img,
"type":mType,
"mask_id": mask_id
}
else:
params = {"image":img}
access_token = getAccessToken() # '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
if not os.path.exists(output_folder):
os.makedirs(output_folder)
f = open(output_folder + "/anime_"+ img_List[i], 'wb')
anime = response.json()['image']
anime = base64.b64decode(anime)
f.write(anime)
f.close()
else:
print("maybe something wrong in your access_token!")
def needMask():
if need_mask == 1:
return True
else:
return False
if __name__ == "__main__":
imgToAnime()