【AI趣玩】 量身定制千人千面的二次元动漫形象

原创
01/09 21:22
阅读数 254

时间:2020年1月9日 晚上

百度AI ONE秒 生成Q版动漫形象,超萌趣二次元动漫形象

接口地址不能少:https://ai.baidu.com/tech/imageprocess/selfie_anime

注:

1.此接口暂未正式上架。需要的开发者小伙伴们。加QQ群:659268104 找群管理申请了哦。只需要反馈APPID,公司名称即可

2.木有百度账号的小伙伴。那就需要多一些步骤了。很简单,详见:https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjgn3

3.小帅为了快速展示出效果。优先选择了微信小程序进行实现哦

4.本文适合调用过百度AI接口的开发者们参考。如果为第一次使用百度AI请查看任意模块的QuickStart图文详细步骤说明了注册百度账号、创建应用等过程

首先获取AccessToken

百度AI接口的AccessToken有一个月的有效期,为了演示效果就优先获取固定写在小程序中。

大家为了后续方便。最好自动定时获取。不想借助后端语言。那就可以考虑一下微信小程序的云开发。本文就使用获取固定写在小程序相关代码中方式喽
获取AccessToken接口地址 https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu#%E8%8E%B7%E5%8F%96access-token

替换URL中的APIKEYSECRETKEY为自己应用的真实值

https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=APIKEY&client_secret=SECRETKEY

使用编程语言、浏览器、POSTMAN都可以快速获取AccessToken哦 ,将以上替换后的URL直接在浏览器地址栏输入回车即可拿到AccessToken哦 返回如下JSON字符串 我们只要access_token的值哦

{
  "refresh_token": "25.123456789730ffc9dbd89ec5a4952a56.315360000.1893997048.282335-12345678",
  "expires_in": 2592000,
  "session_key": "9mzdAqFbzEpjT/tsQOgi4BoWEgc5jOYlr5Lau0lCBk9BNX3ed/UEEWCOunVvz8+AMf8a/IvhjWUbWpcmtTRPvYRALNSCkA==",
  "access_token": "24.12345678982e904de41e99fa7c213a1f.2592000.1581229048.282335-12345678",
  "scope": "brain_selfie_anime brain_image_definition_enhance public brain_all_scope brain_colourize brain_stretch_restore brain_dehaze brain_contrast_enhance brain_image_quality_enhance brain_style_trans brain_inpainting wise_adapt lebo_resource_base lightservice_public hetu_basic lightcms_map_poi kaidian_kaidian ApsMisTest_Test权限 vis-classify_flower lpq_开放 cop_helloScope ApsMis_fangdi_permission smartapp_snsapi_base iop_autocar oauth_tp_app smartapp_smart_game_openapi oauth_sessionkey smartapp_swanid_verify smartapp_opensource_openapi smartapp_opensource_recapi fake_face_detect_开放Scope vis-ocr_虚拟人物助理 idl-video_虚拟人物助理",
  "session_secret": "efeb1f7cfd0330f04b81925097b61ec8"
}

AccessToken写在代码中

微信小程序utils文件夹中增加baiduai.js 并写入如下内容

/**
 * 调用百度AI示例代码
 */
let accessToken = '24.12345678982e904de41e99fa7c213a1f.2592000.1581229048.282335-12345678'//自己的accessToken 根据实际情况可以进行封装 自动获取token
let faceAnimeUrl = 'https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime';//人像动漫化

编写方法调用人脸动漫化接口

/**
 * 人像动漫化
 * @param imgData 图片的base64
 */
let faceAnimeRequest = (imgData,callback)=>{
  //拼接接口body参数
  let params = {
    image: imgData,
  }
  //发送接口请求
  wx.request({
    //拼接请求的接口地址 大家要注意access_token为URL参数 非body参数
    url: faceAnimeUrl + '?access_token=' + accessToken,
    data: params,
    header: {
      //这里根据接口文档要求来。如果要求为json则修改为 application/json
      'content-type': 'application/x-www-form-urlencoded'
    },
    method: 'POST',
    success: function (res) {
      callback.success(res.data)
    },
    fail: function (res) {
      if (callback.fail)
        callback.fail()
    }
  })
}

把方法暴露出去

//暴露出去的接口
module.exports = {
  faceAnimeRequest: faceAnimeRequest
}

baiduai.js 完整代码

/**
 * 调用百度AI示例代码
 */
let accessToken = ''//自己的accessToken 根据实际情况可以进行封装 自动获取token
let faceAnimeUrl = 'https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime';//人像动漫化
/**
 * 人像动漫化
 * @param imgData 图片的base64
 */
let faceAnimeRequest = (imgData,callback)=>{
  //拼接接口body参数
  let params = {
    image: imgData,
  }
  //发送接口请求
  wx.request({
    //拼接请求的接口地址 大家要注意access_token为URL参数 非body参数
    url: faceAnimeUrl + '?access_token=' + accessToken,
    data: params,
    header: {
      //这里根据接口文档要求来。如果要求为json则修改为 application/json
      'content-type': 'application/x-www-form-urlencoded'
    },
    method: 'POST',
    success: function (res) {
      callback.success(res.data)
    },
    fail: function (res) {
      if (callback.fail)
        callback.fail()
    }
  })
}
//暴露出去的接口
module.exports = {
  faceAnimeRequest: faceAnimeRequest
}

编写页面增加一个用户交互的页面

要求是图片的base64.对于用户来说不可能让用户去提交图片的base64数据。那就需要咱们写一个上传图片的流程来替代要用户提交图片base64数据的方式

在index.wxml页面中写如下内容

<view class="page-body">
  <view class="page-body-wrapper">
    <image src="{{ img }}" bindtap='preview' style="width:100%;height:800rpx;" id="imageDom" mode='aspectFit' />
  </view>
  <button bindtap="uploads" class="up">拍照/选取图片识别</button>
  <view class="footer">效果仅供娱乐。测试期间非面部图片也会返回效果</view>
</view>

没有任何样式,那就在index.wxss页面中写如下样式代码内容

.up {
  color: rgb(255, 255, 255);
  font-size: 20px;
  font-family: 微软雅黑;
  width: 200px;
  height: 50px;
  vertical-align: middle;
  text-align: center;
  line-height: 45px;
  border-radius: 25px;
  background-color: rgb(26, 160, 225);
}
.page-body-wrapper image{
    background: #ececec;
}
image {
    width: 100%;
    height: 100%;
    max-height: 1
}
.msg {
    margin: 10px 0;
    text-align: center;
}
.table {
  margin-top: 10rpx;
  border: 0px solid darkgray;
  width: 100%;
}
.tr {
  display: flex;
  width: 100%;
  justify-content: center;
  height: 80rpx;
  
}
.td {
  font-family: 微软雅黑;
    font-size: 28rpx;
    width:100%;
    display: flex;
    justify-content: center;
    text-align: center;
    align-items: center;
}
.bg-g{
  background: white;
}
.baikeform{
  font-size: 20rpx;
  color: #c0c0c0;
  border-top: 1rpx solid #eeeeee;
  margin:30rpx 40rpx 0rpx 40rpx;
  padding: 20rpx;
}
.th {
  font-size: 28rpx;
  width: 48%;
  justify-content: center;
  background: #3366FF;
  color: #fff;
  display: flex;
  height: 80rpx;
  align-items: center;
}
.preview-tips {
  margin: 50rpx 0  30rpx;  
}

.video {
  margin: 20rpx auto;
  width: 100%;
  height: 300px;
}
switch{
    zoom: 0.8;
}
page {
  background-color: #F8F8F8;
  height: 100%;
  font-size: 32rpx;
  line-height: 1.6;
}
.weui-cell_ft{
  font-size: 32rpx;
}

.page-body-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.btn-area {
  margin-top: 40rpx;
  box-sizing: border-box;
  width: 100%;
  padding: 0 30rpx;
}
.footer{
  font-size: 30rpx;
  text-align: center; 
  color: #7367F0;
}

会显示如下的效果图

编写交互函数让页面功能动起来

需要index.js 引入baiduai.js文件、data中增加img变量,对按钮增加事件、对用户选择的图片进行大小判断

小帅这里就一气呵成写完了哈。

var app = getApp();
//引入baiduai.js
var api = require('../../utils/baiduai.js');
Page({
  data: {
    motto: '动漫化身',
    img: ''
  },
  onShareAppMessage: function () {
    return {
      title: '动漫化身',
      path: '/pages/index/index',
      imageUrl: '../../images/sharefaceanime.jpg',
      success: function (res) {
        if (res.errMsg == 'shareAppMessage:ok') {
          wx.showToast({
            title: '分享成功',
            icon: 'success',
            duration: 500
          });
        }
      },
      fail: function (res) {
        if (res.errMsg == 'shareAppMessage:fail cancel') {
          wx.showToast({
            title: '分享取消',
            icon: 'loading',
            duration: 500
          })
        }
      }
    }
  },
  //选择图片绑定事件
  uploads: function () {
    var that = this
    var takephonewidth
    var takephoneheight
    wx.chooseImage({
      count: 1, // 默认9
      sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        wx.getImageInfo({
          src: res.tempFilePaths[0],
          success(res) {
            takephonewidth = res.width,
            takephoneheight = res.height
          }
        })
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        if (res.tempFiles[0].size > (4096 * 1024)) {
          wx.showToast({
            title: '图片文件过大哦',
            icon: 'none',
            mask: true,
            duration: 1500
          })
        } else {
          wx.showLoading({
            title: "分析中...",
            mask: true
          }),
            that.setData({
              img: res.tempFilePaths[0]
            })
        }
        //根据上传的图片读取图片的base64
        var fs = wx.getFileSystemManager();
        fs.readFile({
          filePath: res.tempFilePaths[0].toString(),
          encoding: 'base64',
          success(res) {
            //获取到图片的base64 进行请求人脸动漫化接口
            api.faceAnimeRequest(res.data, {
              success(res) {
                wx.hideLoading();
                that.setData({
                  img: 'data:image/png;base64,' + res.image
                })
              }
            })
          }
        })
      },
    })
  },
  /**
 * 点击查看图片,可以进行保存
 */
  preview(e) {
    var that = this;
    wx.previewImage({
      urls: [that.data.img],
      current: that.data.img
    })
  }
});

看一个效果喽

Java语言API调用

前面获取的AccessToken需要用到哦

FileUtil 、 Base64Util、 HttpUtil 是百度官方提供的。小帅整理的下载地址在这里 http://aixiaoshuai.mydoc.io/?t=234826

import com.alibaba.fastjson.JSONObject;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Base64;

/**
 * @Description 人脸动漫化示例代码
 * @author 小帅丶
 * @className FaceAnimeAPISample
 * @Date 2020/1/10
 **/
public class FaceAnimeAPISample {
    /** 编码格式 */
    private static String ENCODING_UTF_8 = "UTF-8";
    public static void main(String[] args) throws Exception{
        /** 接口所需的accessToken */
        String accessToken = "";
        /** 接口地址 */
        String api_url = "https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime";
        /** 图片地址 */
        String imgaePath = "F:\\testimg\\demo-card-2.jpg";
        /** 图片转byte */
        byte[] imageByte = FileUtil.readFileByBytes(imgaePath);
        /** 图片byte转base64 */
        String imgBase64 = Base64Util.encode(imageByte);
        /** 组装接口所需的参数 */
        String param = "image="+ URLEncoder.encode(imgBase64, ENCODING_UTF_8);
        /** 请求接口返回的内容 */
        String result = HttpUtil.post(api_url, accessToken, param);
        /**看过接口文档就清楚返回的为图片的base64。并不是图片地址或其他。需要我们额外处理一下。
         * 小帅这边就使用fastjson把接口内容转换成Object 读取image的值(即图片的base64) 进行转存成图片文件
         */
        JSONObject object = JSONObject.parseObject(result);
        //获取图片的base64 并保存成图片文件
        GenerateImage(object.getString("image"),"F:\\testimg\\demo-card-2110.jpg");
    }
    /**
     * base64字符串转化成图片
     * @param imgStr 接口返回的图片base64数据
     * @param imgFilePath 即将要保存的图片的本地路径包含文件名称和格式 例如:F:/generateimage.jpg
     * @return
     */
    public static boolean GenerateImage(String imgStr, String imgFilePath) { // 对字节数组字符串进行Base64解码并生成图片
        if (imgStr == null) // 图像数据为空
            return false;
        Base64.Decoder decoder = Base64.getDecoder();
        try {
            // Base64解码
            byte[] b = decoder.decode(imgStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);// 新生成的图片
            out.write(b);
            out.flush();
            out.close();
            System.out.println("保存成功" + imgFilePath);
            return true;
        } catch (Exception e) {
            System.out.println("出错了" + e.getMessage());
            return false;
        }
    }
}

Python语言API调用

前面获取的AccessToken需要用到哦

import urllib3,base64
import json
from urllib.parse import urlencode
# 前面获取到的AccessToken
access_token=''
http=urllib3.PoolManager()
url='https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime?access_token='+access_token
f = open('F:/testimg/demo-card-2.jpg','rb')
# 参数image:图像base64编码
img = base64.b64encode(f.read())
params={'image':img}
# 对base64数据进行urlencode处理
params=urlencode(params)
request=http.request('POST',
                     url,
                     body=params,
                     headers={'Content-Type':'application/x-www-form-urlencoded'})
# 对返回的byte字节进行处理。Python3输出位串,而不是可读的字符串,需要进行转换
result = str(request.data,'utf-8')
# 使用json库 字符串转字典
resultObject = json.loads(result)
# 保存为图片文件
imgByte = base64.b64decode(resultObject['image'])
newFile = open('F:/testimg/demo-card-2110py.jpg','wb')
newFile.write(imgByte)
newFile.close()

体验二维码(微信扫一扫)

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部