微信小程序---人脸识别登陆的实现
关键词:微信小程序 人脸识别 百度云接口
前言
这是一篇关于一个原创微信小程序开发过程的原创文章。涉及到的核心技术是微信小程序开发方法和百度云人脸识别接口。小程序的主体是一个用于个人密码存储的密码管理器,在登陆注册阶段,需要调用百度云人脸识别接口以及百度云在线人脸库的管理接口。本文主要涉及登陆注册模块的实现,而且不需要PHP后台代码,完全在线调用接口实现,希望后来的你能有所收获!(补充说明,如果要在实际中使用的话,要谨慎,后面的上传图片的步骤存在问题。暂时还未解决!)
步骤
开发过程
1.拍摄人脸图片上传至人脸库---注册
准备工作:需要在百度云注册(或者直接用百度云盘app扫码登陆),并创建人脸识别的应用。(完全免费)
具体如下:
百度云:/
注册完成后(或者直接扫码登陆),进入管理控制台->产品服务->人工智能->人脸识别->创建应用->填写必要信息->立即创建
至此,我们已经创建好了人脸识别的应用。接下来,进入应用列表,找到我们才新建的应用,查看人脸库,我们需要创建用户组(用来集中管理小程序的用户人脸照片)
新建组(id不要太复杂,后面还要用的。)
至此,我们已经完成了在云上的所有必要操作。下面,我们在小程序中,拍照上传即可。
拍照上传
需要在pages中新建一个目录,用来承载我们的登陆注册模块。就假定为 camera{camera.js camera.wxml camera.wxss camera.json}
主要文件自然是 *.wxml 和 *.js 了。
camera.wxml
1 <!-- camera.wxml相机大小需要从重新设置 --> 2 <camera 3 device-position="front" 4 flash="off" 5 binderror="error" 6 style="width: 100%; height: 400px;" 7 ></camera> 8 9 <!-- 需要使用 button 来授权登录 -->10 <button11 wx:if="{{canIUse}}"12 open-type="getUserInfo"13 bindgetuserinfo="bindGetUserInfo"14 type="primary"15 >16 授权17 </button>18 <view wx:else>请升级微信版本</view>19 20 <!-- 拍照按钮 -->21 <button type="primary" bindtap="takePhoto"> 拍照 </button>22 23 <button bindtap='btnreg'> 注册须知 </button>
我所谓的授权是,我需要获取用户微信的昵称来充当我人脸库照片的用户id,你可以不需要(设置成一样的,如果是只有一个人使用的话。)
camera.js
调用wxAPI takePhoto() 拍照并获取src -> wx.request() 访问百度云 用先前创建的应用的API Key & Screct Key 获取 access_token ->wx.request() 访问百度云 上传 所拍照片(要经过base64编码)详情可参考小程序API文档 以及 百度云API文档(接口以及于升级至v3)
1 // camera.js 2 const app = getApp() 3 Page({ 4 data: { 5canIUse: wx.canIUse('button.open-type.getUserInfo'), 6nickName : "", 7src : "",//图片的链接 8token: "", 9base64: "", 10msg:"" 11 }, 12 13 //拍照 14 takePhoto() { 15var that = this; 16//拍照 17const ctx = wx.createCameraContext() 18ctx.takePhoto({ 19 quality: 'high', 20 success: (res) => { 21 this.setData({ 22 src: res.tempImagePath//获取图片 23 }) 24 25 //图片base64编码 26 wx.getFileSystemManager().readFile({ 27 filePath: this.data.src, //选择图片返回的相对路径 28 encoding: 'base64', //编码格式 29 success: res => { //成功的回调 30 this.setData({ 31base64: res.data 32 }) 33 } 34 }) 35 }//拍照成功结束 36 37})//调用相机结束 38 39 //acess_token获取,qs:需要多次尝试 40 wx.request({ 41 url: '/oauth/2.0/token', //是真实的接口地址 42 data: { 43 grant_type: 'client_credentials', 44 client_id: '**********************',//用你创建的应用的API Key 45 client_secret: '************************'//用你创建的应用的Secret Key 46 }, 47 header: { 48 'Content-Type': 'application/json' // 默认值 49 }, 50 success(res) { 51 that.setData({ 52 token: res.data.access_token//获取到token 53 }) 54 } 55 }) 56 57 //上传人脸进行注册-----test 58 wx.request({ 59 url: '/rest/2.0/face/v3/faceset/user/add?access_token=' + this.data.token, 60 method: 'POST', 61 data: { 62 image: this.data.base64, 63 image_type: 'BASE64', 64 group_id: '********',//自己建的用户组id 65 user_id: this.data.nickName//这里获取用户昵称 66 }, 67 header: { 68 'Content-Type': 'application/json' // 默认值 69 }, 70 success(res) { 71 that.setData({ 72 msg: res.data.error_msg 73 }) 74 console.log(that.data.msg) 75 //做成功判断 76 if (that.data.msg == 'SUCCESS') {//微信js字符串请使用单引号 77 wx.showToast({ 78title: '注册成功', 79icon: 'success', 80duration: 2000 81 }) 82 wx.switchTab({ 83url: '../UI/ui', 84 }) 85 86 } 87 88 } 89 }), 90 91 //失败尝试 92 wx.showToast({ 93 title: '请重试', 94 icon: 'loading', 95 duration: 500 96 }) 97 }, 98 error(e) { 99console.log(e.detail)100 },101 102 //获取用户信息103 bindGetUserInfo: function(e){104this.setData({105 nickName: e.detail.userInfo.nickName106})107wx.showToast({108 title: '授权成功',109 icon: 'success',110 duration: 1000111})112 },113 114 //先授权登陆,再拍照注册115 btnreg:function(){116wx.showModal({117 title: '注册须知',118 content: '先授权登陆,再拍照注册哦!网络可能故障,如果不成功,请再试一下!',119})120 }121 122 })
这里要多试几次,我以为可能由于网络的问题,会调用失败, 但其实是wx.request()是并发的,所以获取access_token和上传请求会冲突(可能没有获取到access_token就上传,会发生错误)。
注意:还问题还未解决,如果你有好的想法或者解决办法,请务必留言或评论。
目前我的改动是:
在Page的data中声明一个flag,初始值置为false;在获取access_token的request返回succes中将flag 置为true;然后,在下面那个上传图片的request函数体外包一层if(false == true),这样就会解决你当前遇到的问题。即:只有在上一个request执行成功才去进行下一个request。但是,会导致新的问题,Cannot read property 'user_list' of null;at api request success callback function这个似乎是后台返回数据的问题,还未解决,但是网上有人遇到相似的问题,可以参考解决。
另外,要开启微信小程序 IDE 的 不校验合法域名的选项(设置->项目设置 -> 勾选 不校验......)
至此,注册 就完成了(即获取用户昵称、拍照、上传人脸库注册。)
2.拍照上传在线人脸识别---登陆
找到指定用户组中与上传照片最相似的人脸并返回,比对结果。
我们仍然需要再建立一个页面来承载我们的登陆相关操作。就假定为 camera2{camera2.js camera2.wxml camera2.wxss camera2.json}
camera2.wxml
1 <!-- camera.wxml --> 2 <camera 3 device-position="front" 4 flash="off" 5 binderror="error" 6 style="width: 100%; height: 300px;" 7 ></camera> 8 <button type="primary" bindtap="takePhoto">拍照</button> 9 <view>预览</view>10 <image mode="widthFix" src="{{src}}"></image>
camera2.js 与注册大同小异,区别是图片上传的接口不同(这次是 /rest/2.0/face/v3/search 人脸搜素),获取access_token、拍照、照片base64编码都相同。
1 // camera.js 2 Page({ 3 data: { 4base64: "", 5token: "", 6msg: null 7 }, 8 //拍照并编码 9 takePhoto() {10//拍照11const ctx = wx.createCameraContext()12ctx.takePhoto({13 quality: 'high',14 success: (res) => {15 this.setData({16 src: res.tempImagePath17 })18 }19})20 21var that = this;22//图片base64编码23wx.getFileSystemManager().readFile({24 filePath: this.data.src, //选择图片返回的相对路径25 encoding: 'base64', //编码格式26 success: res => { //成功的回调27 that.setData({28 base64: res.data29 })30 }31})32 33//acess_token获取34wx.request({35 url: '/oauth/2.0/token', //真实的接口地址36 data: {37 grant_type: 'client_credentials',38 client_id: '**************************',39 client_secret: '*******************************'//用自己的40 },41 header: {42 'Content-Type': 'application/json' // 默认值43 },44 success(res) {45 that.setData({46 token: res.data.access_token//获取到token47 })48 }49})50 51//上传人脸进行 比对52wx.request({53 url: '/rest/2.0/face/v3/search?access_token=' + that.data.token,54 method: 'POST',55 data: {56 image: this.data.base64,57 image_type: 'BASE64',58 group_id_list: '********'//自己建的用户组id59 },60 header: {61 'Content-Type': 'application/json' // 默认值62 },63 success(res) {64 that.setData({65 msg: res.data.result.user_list[0].score66 })67 if(that.data.msg > 80){68 wx.showToast({69 title: '验证通过',70 icon: 'success',71 duration: 100072 })73 //验证通过,跳转至UI页面74 wx.switchTab({75 url: '../UI/ui',76 })77 }78 }79});80 81wx.showToast({82 title: '请重试',83 icon: 'loading',84 duration: 50085})86 },87 error(e) {88console.log(e.detail)89 }90 })
至此,我们的登陆也搞定了。
注意:上述的 登陆注册 是一个某个小程序的一个模块。关系如下
所以,需要在index页面中设置按钮,来跳转到注册以及登陆页面,然后注册登陆成功后,再跳转至其他功能页面。
后记
这次小程序实战,对我自己也是一个不小的挑战,对比各个云接口、看接口文档、查资料,耗费了大概十来天。但是,我相信大有裨益。另外,对我参考的博客和回答的诸位表示感谢。我们一起前进!
参考资料
【1】微信小程序开发文档
【2】百度云接口文档.v3版