从零开始制作H5人脸融合小游戏
去年的建军节,一个展示军装照的H5人脸融合游戏火遍朋友圈,带来很好的传播效果。最近欧冠决赛要来了,公司决定做一个寻找和你最像的欧冠球星的H5游戏,那么该怎么做呢?认真分析了一下,这个游戏其实用到的技术还是挺多的,是一个比较综合的项目。主要用到技术如下:
> 人脸识别
> Python web和Java web
> 域名解析和nginx
> 微信JS
> H5页面
- 人脸识别
人脸识别的API各大平台都有提供,百度,阿里,优图(腾讯),Face++. 各家的API大体相似,主要区别只是取的点的个数和返回结果的数据结构,都可用。BAT的都有免费可用(如果对QPS没有过高要求的话),Face++ 需要收费1元/次(墙裂怀疑失了智)。综合比较之后选择使用优图。
http://open.youtu.qq.com/#/develop/api-face-analysis-detect
SDK下载
http://open.youtu.qq.com/#/develop/tool-sdk
后端采用python,所以下载python版本的SDK。
从优图获取的人脸识别之后的信息全部是面部点的信息,需要进行处理,具体的处理方法全部在
https://github.com/tonyiweb/face_merge_master (star,fork来一套?)
人脸融合大师,可以满足你10分钟做出人脸融合功能的理想工具,你值得拥有。
- Python web和Java web
基于性能和表现的考虑,做了一个分离。图片识别和融合的功能全部放在一个Python web项目中,作为一个api,然后在Java web项目中调用这个API,将返回的结果或者错误信息返回到H5页面。
- Python web
python是一个能快速开发的语言,有很多易用的web框架可以使用,这里就选择Tornado这个框架。
服务器上通过nohup python -u run.py& 就可以启动一个端口号为9010(代码中可以指定,一般在7000以后)的服务。 nohup可以保证服务长期后台运行,并且可以通过tail -f nohup.out来查看日志。服务可以通过ps -ef|grep python查询服务的pid,再通过kill -9 pid来停止。
- Java web
采用SpringBoot搭建的微服务,没有任何界面。接受H5页面传过来的图片,取调用人脸融合的API,根据结果返回调用结果或者错误信息。
- 域名解析和nginx
域名解析的过程其实就是一个通过名字(相对好记一些)找IP地址(相对难以记忆)的过程,而IP地址又对应一台服务器,也就是通过名字定位服务器。在控制台的域名解析中新加一条记录,指向代码部署的服务器。
因为一台服务器上其实是部署多个服务,也会被多个域名所指向,所以其实还需要一个东西来指引服务所要对应的域名,这个东西就是nginx。 一个服务一般是要对应一个端口的,nginx可以监听一个端口,然后将这个端口的服务定向到某个域名。
注意:1,https服务需要安全证书,可以在阿里云的安全中的CA证书服务中购买(有免费的Symantic的证书)
2,一般默认的是http的,如果没有必要可以不用带安全证书的https服务
3,通过whereis nginx命令查找nginx的位置,通过vhost统一管理nginx配置文件
4,配置完nginx之后,需要重启nginx服务,命令: ./nginx -s reload 如果没有错误,就说明已经重启了。
- 微信JS
因为网页是放在微信环境下传播的,需要使用到微信的一些基础功能,如拍照,所以使用微信的JS SDK.
参考文档:https://www.w3cschool.cn/weixinkaifawendang/h8ap1qe5.html
## 1,配置微信。需要在后台根据jsapi_ticket等信息生成签名
(1)前台
```
//这里的url为当前页面的路径,为了使得分享之后的链接也是可用
var url = window.location.href;
$.get(baseUrl+"/common/get_wx_config",{url:url},
function(data){
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名,
jsApiList: ['checkJsApi','chooseImage','uploadImage','onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareQZone'] // 必填,需要使用的JS接口列表
});
setShareInfo('','');
})
```
(2)后台,微信签名过程
## 2,拍照或者从相册中选择照片
```
var serverId='0';
function getPic(){
wx.checkJsApi({
jsApiList: ['chooseImage'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
if(res.checkResult.chooseImage){
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
$("#selfImg").attr("src",localIds);
wx.uploadImage({
localId: localIds[0], // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
serverId = res.serverId; // 返回图片的服务器端ID
$("#nextBtn").css("display","block");
}
});
}
});
}else{
showAlert("微信版本过低,无法使用相机和相册功能","fail");
}
}
});
}
```
## 3,上传图片并获得人脸融合结果
(1)前台
```
if(serverId!='0'){
if(gender==1){
showAlert("正在玩命给小主儿寻找最像你的球星...","loading");
}else{
showAlert("正在玩命给小主儿寻找最像你的球星太太...","loading");
}
//在服务器端下载图片,并作人脸融合,返回融合后的结果给img的src
$.get(baseUrl+"/common/download_image",{serverId:serverId,gender:gender},
function(data){
if(data.status=='success'){
hideAlert();
$("#loadingPage").css("display","none");
$("#firstPage").css("display","none");
$("#secondPage").css("display","none");
$("#thirdPage").css("display","block");
var imageData = JSON.parse(data.data);
$("#resultName").html(imageData.modelShortName);
if(gender==1){
$("#discriptionText").html(imageData.description+',要被你迷倒啦(^_-');
setShareInfo(imageData.imageUrl[2],'和我最像的欧冠球星是'+imageData.modelShortName+','+imageData.description)
}else{
$("#discriptionText").html(imageData.modelName+','+imageData.description+',要被你迷倒啦(^_-');
setShareInfo(imageData.imageUrl[2],'和我最像的欧冠女神是'+imageData.modelShortName+','+imageData.description)
}
$('#firstResultImg').animateCss('fadeIn', function() {
$("#firstResultImg").attr("src",imageData.imageUrl[0]);
$("#firstResultImg").addClass('animated flash');
$("#secondResultImg").animateCss('fadeIn',function(){
$("#secondResultImg").attr("src",imageData.imageUrl[1]);
$("#secondResultImg").addClass('animated flash');
$("#thirdResultImg").animateCss('fadeIn',function(){
$("#thirdResultImg").attr("src",imageData.imageUrl[2]);
$("#thirdResultImg").addClass('animated flash');
$("#fourthResultImg").animateCss('fadeIn',function(){
$("#fourthResultImg").attr("src",imageData.imageUrl[3]);
$("#fourthResultImg").addClass('animated flash');
$("#resultName").addClass('animated bounceIn');
});
});
});
});
}else{
if(gender==1){
showAlert("好遗憾,没有找到和你相像的球星呢...换张照片,再玩一次吧","fail");
}else{
showAlert("好遗憾,没有找到和你相像的球星太太呢...换张照片,再玩一次吧","fail");
}
}
})
}else{
showAlert("好遗憾,你还没有上传任何照片哦...","fail");
}
```
(2)后台,上传照片并进行人脸融合
>注意:需要在真机上才可以调用相机和相册
>注意:要使用的域名必须在公众号设置——>功能设置中添加
- H5页面
页面的大半是要依赖UI设计师,下面放些设计图,实现过程就省略掉(假装不重要~.~)...
后面是制作完成后得到页面(请在微信中打开): https://worldcup.superwr.top/index.html
另外还有世界杯的改进版(加入了生成海报图片和负载均衡):https://worldcup.pro365.cn/index.html
>注意:H5页面的难点其实是在于兼容,这里通过计算设备宽度,得到相对尺寸rem,然后给元素设置以rem为单位的位置尺寸等信息,做到全部兼容ios移动设备和大部分Android设备
>注意:页面中使用到了Animate.css这个CSS动画框架,链接:http://blog.superwr.top/2018/%E5%8A%A8%E7%94%BB%E6%8F%92%E4%BB%B6animate-css%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/
个人博客地址:http://blog.superwr.top(不喜勿喷,个人比较懒,喷了也会被忽略。。。)
~。~最后还是想吐槽一句,为什么不能用markdown呢
从零开始制作H5人脸融合小游戏的更多相关文章
- 小游戏——js+h5[canvas]+cs3制作【五子棋】小游戏
五子棋小游戏学习—— 有一个问题是,棋盘线的颜色,在canvas中,明明设置了灰色,但在我的预览中还是黑色的,很重的颜色. 以下是复刻的源码: <!DOCTYPE html> <ht ...
- 我用数据结构花了一夜给女朋友写了个h5走迷宫小游戏
目录 起因 分析 画线(棋盘) 画迷宫 方块移动 结语 @(文章目录) 先看效果图(在线电脑尝试地址http://biggsai.com/maze.html): 起因 又到深夜了,我按照以往在公众号写 ...
- 微信小程序-从零开始制作一个跑步微信小程序
来源:伯乐在线 - 王小树 链接:http://ios.jobbole.com/90603/ 点击 → 申请加入伯乐在线专栏作者 一.准备工作 1.注册一个小程序账号,得用一个没注册过公众号的邮箱注册 ...
- C++ 制作一个“测运”小游戏-rand()函数的应用
游戏说明: 游戏名:Lucky Guy 玩法说明:有2种模式可以选择,一种是一直选择数字,直到抽到炸弹为止.另一种是在0~9个数字中进行选择,有5个炸弹,最高分为5,抽到炸弹即游戏结束.游戏结束后,可 ...
- 从零开始开发一款H5小游戏(二) 创造游戏世界,启动发条
本系列文章对应游戏代码已开源 Sinuous game 上一节介绍了canvas的基础用法,了解了游戏开发所要用到的API.这篇文章开始,我将介绍怎么运用这些API来完成各种各样的游戏效果.这个过程更 ...
- 从零开始开发一款H5小游戏(三) 攻守阵营,赋予粒子新的生命
本系列文章对应游戏代码已开源 Sinuous game. 每个游戏都会包含场景和角色.要实现一个游戏角色,就要清楚角色在场景中的位置,以及它的运动规律,并能通过数学表达式表现出来. 场景坐标 canv ...
- 我用Axure制作了一款火影小游戏 | PM老猫
Axure不仅仅是一个原型工具,除了原型之外还可以用来制作一些静态网页,这点对于不懂代码或前端的同学来说挺实用.之前整理了一版<Axure函数自查表>,因为感觉内容太多又对前端样式及脚本感 ...
- Unity小游戏制作 - 暗影随行
用Unity制作小游戏 - 暗影惊吓 最近玩了一个小游戏,叫做暗影惊吓,虽然是一个十分简单的小游戏,但是感觉还是十分有趣的.这里就用Unity来实现一个类似的游戏. 项目源码:DarkFollow 主 ...
- 制作动画或小游戏——CreateJS事件(二)
在Canvas中如果要添加事件,就需要计算坐标来模拟各种事件,而EaselJS中已经封装好了多个事件,只需调用即可. 一.事件 1)点击 事件是绑定在Shape类中的,click事件与DOM中的意思是 ...
随机推荐
- 关于.NET C#调用Sqlite的总结二
关于.NET C#调用Sqlite的总结一 在上一篇中我一直疑惑为什么我在使用多层架构进行开发时总是会报些莫名的错误,难道要使用Sqlite就不能分层吗?只能将UI.业务逻辑.数据访问统统都要写在一层 ...
- C++三种野指针及应对/内存泄露
C++三种野指针及应对/内存泄露 野指针,也就是指向不可用内存区域的指针.如果对野指针进行操作,将会使程序发生不可预知的错误,甚至可能直接引起崩溃. 野指针不是NULL指针,是指 ...
- Word页面去除下划线(Office 2017)实现
后面就不用说了吧设置边框无
- 【QTP专题】04_对象及操作方法
本节介绍知识点包括 1.QTP自动化的原理 2.两类对象:TO(测试对象).RO(运行对象) 3.操作方法:SetTOProperty,GetROProperty,GetTOProperty 1.QT ...
- HAOI2010 最长公共子序列
题目链接:戳我 30分暴力....暴力提取子序列即可qwqwq #include<iostream> #include<cstdio> #include<algorith ...
- OI图论 简单学习笔记
网络流另开了一个专题,所以在这里就不详细叙述了. 图 一般表示为\(G=(V,E)\),V表示点集,E表示边集 定义图G为简单图,当且仅当图G没有重边和自环. 对于图G=(V,E)和图G2=(V2,E ...
- CharSequence与String的区别
CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列. 原文: http://blog.csdn.net/joy_zha ...
- 2.ECMAScript 5.0
JS的引入方式 内接式 <script type="text/javascript"> </script> 外接式 <!--相当于引入了某个模块--& ...
- “全栈2019”Java第四十二章:静态代码块与初始化顺序
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- xshell连接centos虚拟机的几点注意
我家用电脑使用联通的宽带,使用virtualbox装了centos6,连接方式使用NAT网络,还有一个是网络地址转换(NAT),不清楚区别是什么,使用xshell连接 当使用cd /etc/sysco ...