网站首页 > 技术文章 正文
最近刷脸支付很火,老板们当然要追赶时代潮流,于是就有了刷脸支付这个项目。前端实现关键的技术是摄像头录像,拍照和人脸比对,本文来探讨一下如何在html5环境中如何实现刷脸支付以及开发过程中遇到的问题。
1.摄像头
1.1 input获取摄像头
html5中获取手机上的图片,有两种方式,使用input,如下可以打开摄像头拍照:
<input type="file" capture="camera" accept="image/*"/>
另外如果想打开相册,可以这样:
<input type="file" accept="img/*">
但是这两种方式都会有兼容性问题,用过的同学可能都知道。
1.2 getUserMedia获取摄像头
getUserMedia是html5一个新的api,官方一点的定义是:
MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
简单一点说就是可以获取到用户摄像头。
同上面input一样,这种方式也有兼容性问题,不过可以使用其他方式解决,这里可以参考MediaDevices.getUserMedia(),文档中有介绍"在旧的浏览器中使用新的API"。我这里在网上也找了一些参考,总结出一个相对全面的getUserMedia版本,代码如下:
// 访问用户媒体设备
getUserMedia(constrains, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新标准API
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit内核浏览器
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.mozGetUserMedia) {
//Firefox浏览器
navagator.mozGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia(constrains).then(success).catch(error);
} else {
this.scanTip = "你的浏览器不支持访问用户媒体设备"
}
}
1.3 播放视屏
获取设备方法有两个回调函数,一个是成功,一个是失败。成功了就开始播放视频,播放视屏其实就是给video设置一个url,并调用play方法,这里设置url要考虑不同浏览器兼容性,代码如下:
success(stream) {
this.streamIns = stream
// 设置播放地址,webkit内核浏览器
this.URL = window.URL || window.webkitURL
if ("srcObject" in this.$refs.refVideo) {
this.$refs.refVideo.srcObject = stream
} else {
this.$refs.refVideo.src = this.URL.createObjectURL(stream)
}
this.$refs.refVideo.onloadedmetadata = e => {
// 播放视频
this.$refs.refVideo.play()
this.initTracker()
}
},
error(e) {
this.scanTip = "访问用户媒体失败" + e.name + "," + e.message
}
注意:
- 播放视屏方法最好写在onloadmetadata回调函数中,否则可能会报错。
- 播放视频的时候出于安全性考虑,必须在本地环境中测试,也就是http://localhost/xxxx中测试,或者带有https://xxxxx环境中测试,不然的话或有跨域问题。
- 下面用到的initTracker()方法也好放在这个onloadedmetadata回调函数里,不然也会报错。
2. 捕捉人脸
2.1 使用tracking.js捕捉人脸
视屏在video中播放成功之后就开始识别人脸了,这里使用到一个第三方的功能tracking.js,是国外的大神写的JavaScript图像识别插件。关键代码如下:
// 人脸捕捉
initTracker() {
this.context = this.$refs.refCanvas.getContext("2d") // 画布
this.tracker = new tracking.ObjectTracker(['face']) // tracker实例
this.tracker.setStepSize(1.7) // 设置步长
this.tracker.on('track', this.handleTracked) // 绑定监听方法
try {
tracking.track('#video', this.tracker) // 开始追踪
} catch (e) {
this.scanTip = "访问用户媒体失败,请重试"
}
}
捕获到人脸之后,可以在页面上用一个小方框标注出来,这样有点交互效果。
// 追踪事件
handleTracked(e) {
if (e.data.length === 0) {
this.scanTip = '未检测到人脸'
} else {
if (!this.tipFlag) {
this.scanTip = '检测成功,正在拍照,请保持不动2秒'
}
// 1秒后拍照,仅拍一次
if (!this.flag) {
this.scanTip = '拍照中...'
this.flag = true
this.removePhotoID = setTimeout(() => {
this.tackPhoto()
this.tipFlag = true
}, 2000)
}
e.data.forEach(this.plot)
}
}
在页面中画一些方框,标识出人脸:
<div class="rect" v-for="item in profile"
:style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}"></div>
// 绘制跟踪框
plot({x, y, width: w, height: h}) {
// 创建框对象
this.profile.push({ width: w, height: h, left: x, top: y })
}
2.2 拍照
拍照,就是使用video作为图片源,在canvas中保存一张图片下来,注意这里使用toDataURL方法的时候可以设置第二个参数quality,从0到1,0表示图片比较粗糙,但是文件比较小,1表示品质最好。
// 拍照
tackPhoto() {
this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
// 保存为base64格式
this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
// this.compare(imgUrl)
this.close()
},
// Base64转文件
getBlobBydataURI(dataURI, type) {
var binary = window.atob(dataURI.split(',')[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: type
});
},
// 保存为png,base64格式图片
saveAsPNG(c) {
return c.toDataURL('image/png', 0.3)
}
拍照完成之后就可以把文件发送给后端,让后端进行对比验证,这里后端使用的是阿里云的接口。
3. 最后效果
3.1 参考代码demo
最后,demo我已经放在github上了,感兴趣可以打开看一下。
效果如下:
3.2 在项目中落地
最后放在项目中,无非就是最后一个步骤,去调用接口比对,根据比对结果成功是成功还是失败,决定是人脸支付还是继续使用原来的密码支付,效果如下:
ps:这里人脸比对失败了,是因为我带着口罩,就不呲牙露脸了。
作者:Tyler Ning 出处:http://www.cnblogs.com/tylerdonet/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过以下邮箱地址344805262@qq.com 联系我,非常感谢。
- 上一篇: Java教程从入门到精通,零基础学习多久才能找到工作?
- 下一篇: js的15种循环遍历,你掌握了几种
猜你喜欢
- 2024-12-13 一文让你彻底搞懂 vuex,满满的干货
- 2024-12-13 vue前端通过Base64编码解码
- 2024-12-13 「前端进阶」高性能渲染十万条数据(虚拟列表)
- 2024-12-13 Web前端新人笔记之了解Jquery
- 2024-12-13 typeScript 学习笔记(二)——数据类型大全
- 2024-12-13 对于async和await的使用方式、作用效果不理解 ?没关系,看这篇
- 2024-12-13 一文解读前端实现电子签名
- 2024-12-13 WebSocket实现后台向前端推送信息
- 2024-12-13 前端面试被问到项目中的难点有哪些?
- 2024-12-13 js的15种循环遍历,你掌握了几种
你 发表评论:
欢迎- 06-24发现一款开源宝藏级工作流低代码快速开发平台
- 06-24程序员危险了,这是一个 无代码平台+AI+code做项目的案例
- 06-24一款全新的工作流,低代码快速开发平台
- 06-24如何用好AI,改造自己的设计工作流?
- 06-24濮阳网站开发(濮阳网站建设)
- 06-24AI 如何重塑前端开发,我们该如何适应
- 06-24应届生靠这个Java简历模板拿下了5个offer
- 06-24服务端性能测试实战3-性能测试脚本开发
- 571℃几个Oracle空值处理函数 oracle处理null值的函数
- 568℃Oracle分析函数之Lag和Lead()使用
- 553℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 549℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 548℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 539℃【数据统计分析】详解Oracle分组函数之CUBE
- 528℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 522℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)