和平精英项目与“火箭少女”开启了主题活动。3月18日上线“火箭少女”101与游戏特种兵人脸融合的小程序活动。人脸融合技术由腾讯云AI团队提供支持,采用优图新融合算法在GPU上实现人脸融合功能,新融合的特点就是保证与这类动漫人物或虚拟人物的融合度达到自然、贴合完成换脸的视觉感受。
在这个活动中,我们使用小程序来承载整体的活动,并借助云开发快速且高效的实现了「与火箭少女合影」的效果。目前活动已经结束,小程序已无下架无法体验,我们录制了一段项目流程视频供大家观看体验:
如何又好又快的实现合影功能
小程序具体的合影功能使用了腾讯云 AI 的人脸融合功能,通过人脸融合,实现了合影的功能。
整体的架构比较简单,小程序侧调用云函数进行处理,云函数侧直接调用 AI 的人脸融合接口,前端直接完成相关功能的接入。
相关代码逻辑可以参考如下的代码
小程序端代码
// 在小程序侧主要是读取图片,并借助云函数的参数对数据进行上传。
Page({
callFaceFusion: function (photo) {
wx.cloud.callFunction({
name: 'FaceFusion',
data: {
//合成的原始图片
image: photo,
//素材ID
modelId: __this.data.modelNowId
},
complete: res => {
this.setData({
faceFusionRes: res.result.Image,
photoStatus: 'step3',
canvasTop: '-600px'
})
}
})
}
})
云函数代码
const { SecretId, SecretKey } = require('./tencentcloud_secret.json')
const cloud = require('wx-server-sdk')
const tencentcloud = require('tencentcloud-sdk-nodejs')
cloud.init()
//tencentCloud API
const FacefusionClient = tencentcloud.facefusion.v20181201.Client;
const models = tencentcloud.facefusion.v20181201.Models;
const Credential = tencentcloud.common.Credential;
const ClientProfile = tencentcloud.common.ClientProfile;
const HttpProfile = tencentcloud.common.HttpProfile;
let cred = new Credential(SecretId, SecretKey);
let httpProfile = new HttpProfile();
httpProfile.endpoint = "facefusion.tencentcloudapi.com";
let clientProfile = new ClientProfile();
clientProfile.httpProfile = httpProfile;
let client = new FacefusionClient(cred, "ap-guangzhou", clientProfile);
let req = new models.FaceFusionRequest();
/**
* formatting arraybuffer to base64
*
* @param {Array} array Uint8Array格式化后的普通数组
*/
function arrayBufferToBase64(array) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let bytes = new Uint8Array(array);
let len = bytes.length;
let base64 = "";
for (let i = 0; i < len; i += 3) {
base64 += chars[bytes[i] >> 2];
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64 += chars[bytes[i + 2] & 63];
}
if ((len % 3) === 2) {
base64 = base64.substring(0, base64.length - 1) + "=";
} else if (len % 3 === 1) {
base64 = base64.substring(0, base64.length - 2) + "==";
}
return base64;
}
// 云函数入口函数
exports.main = async (event, context) => {
// 图片转 Base 64
let imageBase64 = arrayBufferToBase64(event.image);
// 构建参数
let params = '{"ProjectId":"123456","ModelId":"' + event.modelId + '","Image":"' + imageBase64 + '","RspImgType":"url ","PornDetect":1,"CelebrityIdentify":1}'
req.from_json_string(params);
return new Promise((resolve, reject) => {
// 调用 API
client.FaceFusion(req, function (errMsg, response) {
if (errMsg) {
console.log(errMsg);
resolve(errMsg)
}
resolve(response)
});
})
}
合影功能优化
在具体的实现方面,为了获得更好的效果,我们在实现方面做了一些优化,具体包括:
对用户上传图片进行压缩处理,减少图片大小,提升处理速度
在研究了云开发的计费模式后发现,云函数的主要计费在于运行时间和函数外网流量,因此,我们通过研究,决定对用户上传的图片进行压缩。通过压缩用户上传的图片,来控制函数的处理时间和相应的外网流入时间。
通过加入 Canvas 转存的功能,我们实现了对于图片的压缩功能。
在实际的生产环境中,图片经过压缩后,体积会从缩小为原来的 1%,大大的提升了处理的速度和效率。
对于人脸融合素材进行缩小处理,仅做局部融合
除了对于图片进行压缩处理以外,我们还调整了人脸融合的素材,通过将需要融合的部分缩小,需要融合的区域和相应的素材都变小后。AI人脸融合的速度和性能都得到了大幅度的提升。
在实际的生产环境中,云函数运行时间与文件体积下降,项目大量请求云函数,节省了大量成本!生产环境中成本下降近 10 倍,可以说是效果非常好了。
一些独特的设计
在这个小程序中,我们并没有使用云开发的云存储进行图片的转存,和一般意义上的 Best Practice 不太一样。这里的主要考量有二:
没有业务存储图片的需求:这个活动小程序所需要的AI融合图片和一般意义上的需求不太一样。融合后的AI图片存储在AI融合服务服务器。
AI 融合接口会直接返回的图片:我们调用 AI 融合接口返回的是图片,而不是云存储的地址,因此,我们在整个流程中直接传递图片可以有效减少环节,缩短整个流程的时间。
如果你的项目也有类似的特点,可以考虑参考我们的方案来进行实现。
项目总结
本次和平精英「与明星特种兵女团合影」小程序,联动AI人脸融合技术在标杆游戏中落地。该项目多团队合作,多团队技术支持,云函数相关数据,AI人脸融合数据,为后续跨团队合作项目积累了宝贵的技术与经验,也期待与项目有更多技术落地!