微信小程序---人脸识别登陆的实现
关键词:微信小程序 人脸识别 百度云接口
前言
这是一篇关于一个原创微信小程序开发过程的原创文章。涉及到的核心技术是微信小程序开发方法和百度云人脸识别接口。小程序的主体是一个用于个人密码存储的密码管理器,在登陆注册阶段,需要调用百度云人脸识别接口以及百度云在线人脸库的管理接口。本文主要涉及登陆注册模块的实现,而且不需要PHP后台代码,完全在线调用接口实现,希望后来的你能有所收获!【自己玩玩可以,如果要实际生产使用,慎重!!!】
注:之前存在的1.移动端无法使用(请打开手机调试功能,具体操作在文末);2.注册和登录需要多次尝试才能成功;3.小问题报错 问题,均已解决,目前可以正常使用。(这里要感谢@lllsp童鞋发现问题,并提出解决方法)
步骤
步骤 | 涉及接口(百度云) |
拍摄或者相册选择 并 上传比对样本照片到 人脸库 | 人脸库管理接口(main:人脸注册) |
拍摄照片并上传,云服务器在线比对 人脸库照片与上传图片的相似度 | 人脸识别接口 |
获取返回结果(相似度) | 人脸识别接口 |
开发过程
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=" 100%; height: 400px;" 7 ></camera> 8 9 <!-- 需要使用 button 来授权登录 --> 10 <button 11 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文档(接口已经于18年升级至v3)
1 // camera.js 2 const app = getApp() 3 Page({ 4 data: { 5 canIUse: wx.canIUse('button.open-type.getUserInfo'), 6 nickName: "", 7 src: "", //图片的链接 8 token: "", 9 base64: "", 10 msg: "" 11 }, 12 //拍照后调用的函数,用于获取token和上传图片进行注册 13 myrquest: function () { 14 var that = this; 16 wx.request({ 17 url: 'https://aip.baidubce.com/oauth/2.0/token', 18 data: { 19 grant_type: 'client_credentials', 20 client_id: '***************',//自己的API key 21 client_secret: '******************' //自己的密码 22 }, 23 header: { 24 'Content-Type': 'application/json' // 默认值 25 }, 26 success(res) { 27 that.setData({ 28 token: res.data.access_token //获取到token 29 }) 31 //上传人脸进行注册 32 wx.request({ 33 url: 'https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=' + that.data.token, 34 method: 'POST', 35 data: { 36 image: that.data.base64, 37 image_type: 'BASE64', 38 group_id: '**********', //自己的组id 39 user_id: that.data.nickName //这里获取 40 }, 41 header: { 42 'Content-Type': 'application/json' // 默认值 43 }, 44 success(res) { 46 var errorcode = res.data.error_code 47 //做成功判断 48 if (errorcode == 0) { 49 wx.showToast({ 50 title: '注册成功', 51 icon: 'success', 52 duration: 500 53 }) 54 //注册成功,跳转到主界面 55 wx.switchTab({ 56 url: '../UI/ui' 57 }) 58 } 59 } 60 }) 61 } 62 }) 63 }, 64 65 //拍照 66 takePhoto() { 67 var that = this; 68 //拍照 69 const ctx = wx.createCameraContext() 70 ctx.takePhoto({ 71 quality: 'medium',//使用small可以加快速度 72 success: (res) => { 73 that.setData({ 74 src: res.tempImagePath //获取图片 75 }) 76 77 //图片base64编码 78 wx.getFileSystemManager().readFile({ 79 filePath: that.data.src, //选择图片返回的相对路径 80 encoding: 'base64', //编码格式 81 success: res => { //成功的回调 82 that.setData({ 83 base64: res.data 84 }) 85 that.myrquest();//拍照之后,调用上传函数,获取token上传人脸 86 } 87 }) 88 } //拍照成功结束 89 90 }) //调用相机结束 91 92 //失败尝试 93 wx.showToast({ 94 title: '注册中...', 95 icon: 'loading', 96 duration: 1000 97 }) 98 }, 99 error(e) { 100 console.log(e.detail) 101 }, 102 103 //获取用户信息 104 bindGetUserInfo: function (e) { 105 this.setData({ 106 nickName: e.detail.userInfo.nickName 107 }) 108 wx.showToast({ 109 title: '授权成功', 110 icon: 'success', 111 duration: 500 112 }) 113 }, 114 115 //先授权登陆,再拍照注册 116 btnreg: function () { 117 wx.showModal({ 118 title: '注册须知', 119 content: '先授权登陆,再拍照注册哦!网络可能故障,如果不成功,请再试一下!' 120 }) 121 } 122 123 })
这里之前要多试几次,我之前以为可能由于网络的问题,会调用失败, 但其实是wx.request()是并发的,所以获取access_token和上传请求会冲突(可能没有获取到access_token就上传,会发生错误)。
解决办法是:将获取token和上传图片封装成一个函数,且将上传图片的request放在获取token的成功回调中,这样可避免出现access token is invalid or no longer valid. 错误。
(正确的代码就是上方给出的代码,不需要自己改)
另外,要开启微信小程序 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=" 100%; height: 300px;" 7 ></camera> 8 <button type="primary" bindtap="takePhoto">拍照</button> 9 <view>预览</view> 10 <image mode="widthFix" src="{{src}}"></image>
camera2.js 与注册大同小异,区别是图片上传的接口不同(这次是 https://aip.baidubce.com/rest/2.0/face/v3/search 人脸搜素),获取access_token、拍照、照片base64编码都相同。
1 // camera.js 2 Page({ 3 data: { 4 base64: "", 5 token: "", 6 msg: null, 7 src: '' 8 }, 9 10 //上传人脸进行验证(用于拍照后调用) 11 myRequest: function () { 12 var that = this; 13 //acess_token获取 14 wx.request({ 15 url: 'https://aip.baidubce.com/oauth/2.0/token', // 仅为示例,并非真实的接口地址 16 data: { 17 grant_type: 'client_credentials', 18 client_id: '*********', //自己的API key 19 client_secret: '*****************' //自己的Secrec Key 20 }, 21 header: { 22 'Content-Type': 'application/json' // 默认值 23 }, 24 success(res) { 25 that.setData({ 26 token: res.data.access_token //获取到token 27 //上传人脸进行 比对 28 }) 29 wx.request({ 30 url: 'https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=' + that.data.token, 31 method: 'POST', 32 data: { 33 image: that.data.base64, //change:使用that 34 image_type: 'BASE64', 35 group_id_list: '**********' //自己的用户组id 36 }, 37 header: { 38 'Content-Type': 'application/json' // 默认值 39 }, 40 success(res) { 41 var errorcode = res.data.error_code 42 if (errorcode == 0) //访问成功 43 { 44 var ulist = res.data.result 45 //打印返回msg看看 46 if (ulist.user_list != null) { 47 // console.log('ulist存在'); 48 var result = ulist.user_list[0].score 49 if (result > 80) { 50 wx.showToast({ 51 title: '验证通过', 52 icon: 'success', 53 duration: 500 54 }) 55 //验证通过,跳转到主界面 56 wx.switchTab({ 57 url: '../UI/ui'//自己的 58 }) 59 } else { 60 console.log('不匹配') 61 } 62 } 63 } else { 64 console.log('访问失败') 65 } 66 } 67 }); 68 } 69 }) 70 }, 71 72 //拍照并编码 73 takePhoto() { 74 var that = this; 75 //拍照 76 const ctx = wx.createCameraContext() 77 ctx.takePhoto({ 78 quality: 'medium',//使用small可加快速度 79 success: (res) => { 80 that.setData({ 81 src: res.tempImagePath 82 }) 83 //图片base64编码 84 wx.getFileSystemManager().readFile({ 85 filePath: that.data.src, //选择图片返回的相对路径 86 encoding: 'base64', //编码格式 87 success: res => { //成功的回调 88 that.setData({ 89 base64: res.data 90 }) 91 that.myRequest();//调用函数进行token获取和图片上传验证 92 } 93 }) 94 } 95 }) 96 //失败重试提醒 97 wx.showToast({ 98 title: '验证中...', 99 icon: 'loading', 100 duration: 1000 101 }) 102 }, 103 error(e) { 104 console.log(e.detail) 105 } 106 })
至此,我们的登陆也搞定了。
注意:上述的 登陆注册 是一个小程序的一个模块。关系如下
所以,需要在index页面中设置按钮,来跳转到注册以及登陆页面,然后注册登陆成功后,再跳转至其他功能页面。
后记
这次小程序实战,对我自己也是一个不小的挑战,对比各个云接口、看接口文档、查资料,耗费了大概十来天。但我相信大有裨益。另外,对我参考的博客和回答的诸位表示感谢。我们一起前进!
参考资料
【1】微信小程序开发文档
【2】百度云接口文档.v3版
打开小程序调试功能: