项目背景
和平精英项目与“火箭少女”开启了主题活动。3月18日上线“火箭少女”101与游戏特种兵人脸融合的小程序活动。人脸融合技术由腾讯云AI团队提供支持,采用优图新融合算法在GPU上实现人脸融合功能,新融合的特点就是保证与这类动漫人物或虚拟人物的融合度达到自然、贴合完成换脸的视觉感受。
项目体验
目前活动已经结束,小程序已无下架无法体验,我录制了一段项目流程视频供大家观看体验:
[##e0952ys2mjh##]
技术点解析
项目逻辑流程图
-
基础功能:页面交互、用户信息、抽奖、照片上传/自拍、照片优化、长按保存图片,分享
-
创新功能:云函数完成腾讯云AI人脸融合功能
在小程序云开发出现之前,类似的人脸融合功能需要专门的后台开发人员来协助实现,有了小程序云开发,这部分工作完全可以通过云开发来完成,新开发模式,缩短了项目人力排期成本。小程序云开发简单易用,对此感兴趣的同学可以查看官方文档的相关API即可
账号与费用:
小程序账号申请、云函数收费情况、腾讯云账号申请、人脸融合服务开通、小程序关联app (手Q/微信需双份信息)
项目收费部分包括:1、云函数调用收费 2、AI人脸融合接口收费。项目在微信/手Q都使用云函数功能,云函数调用扣费需在腾讯云账户信息关联微信/手Q扣费账号!腾讯云管理端可查看开通云函数套餐
下面内容重点介绍:
1、使用云函数完成AI人脸融合相关功能
2、一些坑
3、项目展望
AI人脸融合
AI人脸融合功能,结合实际项目情况对市面人脸融合功能实现方式筛选后,选择了腾讯云人脸融合技术支持,算法版本为:换脸版AI人脸融合接口文档信息
Q1:云函数如何实现人脸融合功能?
先看流程示意图,简单说明人脸融合功能
1、编写云函数,接收小程序传过来的event,包括用户上传图片信息(image)、用户选择的模特素材id(modelId)
2、云函数逻辑,请求facefusion服务,其中接口签名与接口必填参数信息按要求格式处理。参考腾讯云人脸融合文档
3、小程序使用wx.cloud.callFunction,参数:用户上传图片信息(image)、用户选择的模特素材id(modelId)
4、小程序处理云函数返回数据(融合成功与否状态逻辑),参数查看腾讯云人脸融合文档
(云函数Demo 啊垒提供)
Q2、提升合照融合成功率
与腾讯云AI融合算法同事确认融合接口参数,对融合成功率进行优化。优化后,项目最终融合成功率从34%提升到85%
优化点如下:
1、用户图分辨率应<1080px ----- 对用户上传/自拍图片做压缩并控制分辨率处理 --- 啊垒提供优化组件
wxml:
核心代码:
2、联合腾讯云侧同事:针对神图人脸检测支持不完整的人脸检测返回结果做优化逻辑处理,提供融合不成功调用接口供前端调用
//部分重要接口判断代码,更多详细接口信息查询腾讯云文档
//融合成功
if (R.ReviewResultSet[0].Suggestion == "PASS") {
//融合成功逻辑
}
//鉴权失败
if (R.code === "AuthFailure.SignatureFailure") {
wx.showToast({ title: '合成失败,请选择其他照片', icon: 'none', })
return;
} //未发现人脸
if(R.code === "InvalidParameterValue.NoFaceInPhoto"){
wx.showToast({ title: '未发现人脸,请重拍或重新选择人脸照片!', icon: 'none', }) return;
}
//人脸框参数有误或者人脸太小
if (R.code === "InvalidParameterValue.FaceRectParameterValueError") {
wx.showToast({ title: '人脸不全,请重拍全人脸照片!', icon: 'none', })
return;
}
//照片效果差不适合融合 建议重新上传照片
if (R.code === "FailedOperation.ParameterValueError") {
wx.showToast({ title: '照片效果差不适合融合,建议重新上传照片!', icon: 'none', })
return;
}
3、用户自拍/上传图片界面前端提示:添加最适合拍照/图片人脸融合位置提示与文字提示
<canvas class="photo-imgpic" canvas-id="photocanvas"></canvas>
Q3、节省费用
项目收费包括两个部分:1、云函数调用收费 2、AI人脸融合接口收费
1、云函数调用收费:(函数执行内存 * 运行时间) + 外网流量 (项目数据敏感 这里不做展开)
2、AI人脸融合接口收费
优化费用成本,了解收费标准之后,从技术方面优化费用主要在云函数收费。维度参考:降低云函数调用时间与减少外网流量。
回看项目人脸融合流程图功能图,优化点如下:
a、对用户上传/自拍图片进行压缩并控制分辨率处理 ---- 减少小程序传给云函数用户图片(image)体积
b、AI人脸融合模板素材优化,融合图片区域变小,融合素材减少,同时融合效率提高,返回融合数据加快 --- 项目中6个模特分别与11个小姐姐合照生成融合模板图片,总素材图为66张*2(手Q/微信)。优化后只提供6张透明小脸融合素材图,融合后图片分别与11个小姐姐组合为最终(66*2)张融合图
实际融合素材图 --- 上传腾讯云后台融合素材图
云函数调用日志对比:云函数运行时间与文件体积下降,项目大量请求云函数,将节省大量成本!
优化前:Duration:1788ms / MaxMemoryUses: 113.83MB
优化后: Duration:256ms / MaxMemoryUses: 63.61MB
一些坑
1、手Q/IOS下拍照获取图片显示翻转
解决方案一:判断当前设备为手Q/IOS,添加样式强制翻转图片180度
qml
<image class="use-img {{usetransform == 1 ? 'usetransform':''}} " src="{{tmpImgUrl}}" mode="aspectFit"></image>
qss
.usetransform{transform: rotateY(180deg);}
JS
//拍照功能代码查看小程序文档
//手q 拍照照片翻转 强制旋转180度
let SI = wx.getSystemInfoSync();
if(SI.AppPlatform === 'qq' & SI.system.indexOf('iOS') >=0 & app.globalData.tempic==1){
console.log(SI) this.setData({ usetransform:1 })
}
解决方案二:拍照图片使用Canvas绘制保存,旋转canvas,调整图片显示问题
<canvas canvas-id="userPhoto" style="height:300px;width:100%;" ></canvas>
//拍照
takePhoto() {
let __this = this;
__this.ctx.takePhoto({
quality: 'low',
success: (res) => {
console.log('takePhoto',res)
//优化图像
compressImage({
imageInfo: res,
canvasNode: wx.createCanvasContext('userPhoto'),
process(e) {
wx.showToast({
title: '照片读取中...',
icon: 'none',
})
},
success(e) {
wx.hideToast()
},
fail(e) {
wx.showToast({
title: '照片读取失败,请重试',
icon: 'none',
})
}
})
}
})
},
//compressImage部分代码
compressImage(option){
let __this = this;
const photo = typeof option.imageInfo.tempFilePaths === 'object' ? option.imageInfo.tempFilePaths[0] : option.imageInfo.tempImagePath;
option.process(option.imageInfo)
wx.getImageInfo({
src: photo,
success(infoRes) {
let SI = wx.getSystemInfoSync();
//修复qq拍照旋转照片
if(SI.AppPlatform === 'qq' & SI.system.indexOf('iOS') >=0 && option.imageInfo.errMsg === 'operateCamera:ok'){
option.canvasNode.translate(windowWidth, 0);
option.canvasNode.scale(-1, 1);
}
option.canvasNode.drawImage(photo, picPosLeft, 0, picWidth, 300);
},
fail: function (res) {
option.fail(res)
}
})
}
2、手Q base64图片页面无法显示
base64代码
//转base64代码
qq.getFileSystemManager().readFile({
filePath: res.tempImagePath,
encoding: 'base64',
success: function (res) {
app.globalData.tmpImgUrl = 'data:image/png;base64,' + res.data
__this.setData({
tmpImgUrl: app.globalData.tmpImgUrl
})
}
})
解决方法:页面显示的图片使用未处理的 res.tempImagePath地址/ Canvans获取绘制图片地址, base64处理后图片地址通过app.globalData储存供其他地方使用
3、人脸融合接口返回融合图片格式不一致
正常情况下融合返回图片应与融合素材图片文件格式保持一致。
解决方法:联系腾讯云侧同事帮忙优化返回融合图片格式,对该项目素材文件增加文件类型字段判断。
4、融合页与分享页面调试
融合页与分享页是融合小头像叠加在模板图上,因每张模板页面人物位置不一致,有大量头像图片对齐核对工作。
解决方法:避免调用过多融合接口账号无融合测试次数使用,书写规范,使用小程序模拟客户端传参功能优化页面调试,同时也方便后期修改素材快速调整页面样式。
5、关于压测
项目中使用了云函数,AI融合服务,整个链路如何做压测?
解决方法:首先,项目云函数整个链路不支持压测功能,为避免项目没有压测出现问题,项目在云函数调用前,人脸融合接口分别对qps数据进行监控测试。云函数调用前项目后台童鞋实时监控qps,给到前端请求数据接口,前端童鞋对数据判断处理。人脸融合部分,AI团队模拟功能压测。
7、联调相关
线上小程序发现没有调试信息怎么办?
解决方法:先打开体验版二维码,打开调试信息,在打开正式环境小程序调试信息就有了
----------------
项目展望