YOLO813

python利用API批量生成动漫头像

    本篇博客介绍了如何通过百度提供的应用程序接口生成动漫头像,先说测试结果,总体效果还是不错的,首先最好是女士的照片,自拍大头照最好,因为脸部的二次元效果是最好的,其它地方只是趋于动漫的效果,另外不建议男士使用这个程序,因为真的是:太丑了(实测)!!!

 

    这个图片转动漫的效果实现主要是依靠百度的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()