前提提要
在上篇文章中,我们已经设计好了这次要开发的融合小程序的系统架构,给大家复习下:
下面让我们跟着这个思路,搭建属于自己的融合小程序~
小程序前端开发
由于本文主要介绍小程序端调用人脸融合云接口,所以前端这里简单设计,整个前端页面分为三个区域:
模版区
展示模版图列表,标柱各模版图人脸,每次融合只能选择一张融合图,每次选择只能选中一张人脸
输入区
展示用户上传的输入图列表,标柱各输入图人脸,每次选择只能选中一张人脸
融合结果区
展示融合结果图
使用说明
- 上传输入图,展示输入人脸->选择模版人脸->选择输入人脸,组合成MergeInfos元素->点击融合->获取融合结果并展示
- 可以上传多张输入图
- 可以重复【选择模版人脸->选择输入人脸】操作,最多三组,实现多脸融合
调用人脸接口
main云函数
main云函数实际是一个统一请求云sdk的接口,里面封装好大部分请求云API的操作:
- 公共参数处理:组装好包括service、version、action,以及用于身份校验的sercetId、secretKey等参数
- 处理图片数据:由于小程序从本地相册或相机获取的图片数据,云服务无法直接处理,因此小程序需要将这些图片先上传,再请求云函数 在这个demo采取的方式是先将图片上传的云开发的数据库,获取到fileId,在云函数请求云API之前,通过云开发提供的cloud.getTempFileURL方法,获取云文件真实的链接。
async function getFileUrl(url) {
// 如果是 cloud:// 则,换取云文件真实链接
if (/^cloud:///.test(url)) {
const { fileList } = await cloud.getTempFileURL({
fileList: [url],
});
if (!fileList || !fileList[0]) throw new Error('无法获取文件');
const file = fileList[0];
return file.tempFileURL;
} else {
return url;
}
};
- 封装请求云API的统一接口:
// 腾讯云sdk
const tencentcloud = require('tencentcloud-sdk-nodejs');
const { Credential } = tencentcloud.common;
const { ClientProfile } = tencentcloud.common;
const { HttpProfile } = tencentcloud.common;
// 请求腾讯云API接口
function requestAPI({
endpoint, // 请求域名 (可选)
service, // 服务前缀
action, // 接口名称
version, // 版本号
region, // 地域 (可选)
secretId, // 密钥ID
secretKey, // 密钥Key
sessionToken, // 密钥Token (可选)
data, // 请求数据
}) {
const { Client } = tencentcloud[service][version];
const { Models } = tencentcloud[service][version];
const cred = new Credential(secretId, secretKey, sessionToken);
const httpProfile = new HttpProfile();
httpProfile.endpoint = endpoint || `${service}.tencentcloudapi.com`;
const clientProfile = new ClientProfile();
clientProfile.httpProfile = httpProfile;
const client = new Client(cred, region || 'ap-shanghai', clientProfile);
const req = new Models[`${action}Request`]();
const reqParams = JSON.stringify({ ...data });
req.from_json_string(reqParams);
return new Promise((resolve, reject) => {
client[action](req, (errMsg, response) => {
if (errMsg) {
reject(errMsg);
return;
}
resolve(JSON.parse(response.to_json_string() || {}));
});
});
}
main云函数实现如下:
代码语言:txt复制// 云函数入口文件
const cloud = require('wx-server-sdk')
const { handleImage, requestAPI } = require('./utils');
const actionConfig = {
DetectFace: {
service: 'iai',
action: 'DetectFace',
version: 'v20180301',
secretId: '你的secretId',
secretKey: '你的secretKey'
},
FuseFace: {
service: 'facefusion',
action: 'FuseFace',
version: 'v20181201',
secretId: '你的secretId',
secretKey: '你的secretKey'
}
};
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext();
// 整理默认参数,action指定请求那个云API接口
let config = actionConfig[event.action];
if (!config) {
return {
Response: {
Error: {
Code: -1,
Message: 'Action错误'
}
}
};
}
// 整理本次请求入参,处理入参的图片数据,这里不展开逻辑
config.data = handleImage(event.data || {})
let requestRes;
try {
// 发起请求
requestRes = {
Response: await requestAPI(config),
};
} catch (err) {
console.error(err);
requestRes = {
Response: {
Error: {
Code: err.code || -1,
Message: err.message || '未知错误',
},
}
};
}
return requestRes;
}
小程序调用云函数
参考官网文档,实现小程序调用云函数即可:
- 人脸检测:获取本地图片后执行人脸检测,获取人脸框信息:
const self = this;
// 选择本地图片
chooseImage(async function(res) {
// 上传图片
const fileId = await uploadImage(res);
wx.showLoading({
title: '加载中',
mask: true
});
// 指定请求人脸检测,填好请求入参
wx.cloud.callFunction({
name: 'main',
data: {
action: 'DetectFace',
data: {
MaxFaceNum: 3,
MinFaceSize: 30,
Url: fileId,
NeedFaceAttributes: 0,
NeedQualityDetection: 0
}
},
success(result) {
wx.hideLoading();
// TODO:success event
},
fail(error) {
wx.hideLoading();
console.log(error);
}
});
}, function(err) {
console.log(err);
})
- 人脸融合:
let { mergeInfos, activeModelId, projectId } = this.data;
wx.showLoading({
title: '融合中',
mask: true
});
const self = this;
// 发起融合
wx.cloud.callFunction({
name: 'main',
data: {
action: 'FuseFace',
data: {
RspImgType: 'url',
ProjectId: projectId,
ModelId: activeModelId,
MergeInfos: mergeInfos
}
},
success(result) {
wx.hideLoading();
// TODO:success event
},
fail(err) {
console.log(err);
wx.hideLoading();
}
});
有个坑
由于小程序使用的云SDK版本问题,当我们编写完main的云函数,上传并部署时,若选择【云端安装依赖】,那么此时云端安装的云SDK并不包含FuseFace这个服务!! 因此这里推荐大家本地安装好依赖(拉取最新版本latest)后,一并上传部署。
代码语言:txt复制"dependencies": {
"wx-server-sdk": "latest",
"tencentcloud-sdk-nodejs": "latest"
}
至此,整个人脸融合小程序就开发完毕了,有兴趣的同学可以体验一下:
感谢阅读两篇文章的小伙伴,对使用人脸融合服务有问题的同学可以评论区留言,下来一起讨论下。