Vue+tracking.js 实现前端人脸检测功能


Posted in Javascript onApril 16, 2020

项目中需要实现人脸登陆功能,实现思路为在前端检测人脸,把人脸照片发送到后端识别,返回用户token登陆成功

前端调用摄像头使用tracking.js检测视频流中的人脸,检测到人脸后拍照上传后端。

后端使用face_recognition人脸识别库,使用Flask提供restfulAP供前端调用

实现效果如下图:

登陆界面:

Vue+tracking.js 实现前端人脸检测功能

摄像头检测人脸界面:

Vue+tracking.js 实现前端人脸检测功能

前端代码如下:

<template>
 <div id="facelogin">
 <h1 class="title is-1">{{FaceisDetected}}</h1>
 <!-- <p>{{FaceisDetected}}</p> -->
 <div class="content-cam">
 <div class="camera-wrp sec">
 <video width="320" height="320" ref="videoDom" id="video_cam" preload autoplay loop muted></video>
 <canvas width="320" height="320" ref="canvasDOM" id="face_detect"></canvas>
 <div class="control-btn"></div>
 </div>
 <div class="images-wrp sec">
 <!-- <p class="title is-5">Image taken</p> -->
 <div
  :class="`img-item img-item-${index}`"
  v-for="(image, index) in images"
  :key="`img-wrp-${index}`"
  :style="`background-image: url('${image}')`"
 ></div>
 </div>
 </div>
 </div>
</template>

export default {
name: 'facelogin',
data() {
return {
count: 0,
isdetected: '请您保持脸部在画面中央',
videoEl: {},
canvasEL: {},
images: [],
trackCcv: false,
trackTracking: false,
autoCaptureTrackTraking: false,
userMediaConstraints: {
audio: false,
video: {
// ideal(应用最理想的)
width: {
min: 320,
ideal: 1280,
max: 1920
},
height: {
min: 240,
ideal: 720,
max: 1080
},
// frameRate受限带宽传输时,低帧率可能更适宜
frameRate: {
min: 15,
ideal: 30,
max: 60
},
// 摄像头翻转
facingMode: 'user'
}
}
}
},
computed: {
FaceisDetected() {
return this.isdetected
}
},
created() {
this.changeView()
},

 mounted() {
 // The getUserMedia interface is used for handling camera input.
 // Some browsers need a prefix so here we're covering all the options
 navigator.getMedia =
 navigator.getUserMedia ||
 navigator.webkitGetUserMedia ||
 navigator.mozGetUserMedia ||
 navigator.msGetUserMedia
 this.init()
 },
 methods: {
 async init() {
 this.videoEl = this.$refs.videoDom
 this.canvasEL = this.$refs.canvasDOM
 await navigator.mediaDevices
 .getUserMedia(this.userMediaConstraints)
 .then(this.getMediaStreamSuccess)
 .catch(this.getMediaStreamError)
 await this.onPlay()
 },
 async onPlay() {
 debugHelper.log('onPlay')


 this.onTrackTracking()
 },
 changeView() {
 this.setTitle('刷脸登陆')
 this.setBackDisabled(false)
 this.setBackIcon('arrow_back')
 msgbus.vm.setBottomNavVisible(false)
 msgbus.vm.setBottomBtnVisible(false)
 msgbus.vm.setMsgInputVisible({ value: false })
 },


 onTrackTracking() {
 const context = this
 const video = this.videoEl
 const canvas = this.canvasEL
 const canvasContext = canvas.getContext('2d')
 let tracker = new tracking.ObjectTracker('face')


 video.pause()
 video.src = ''
 tracker.setInitialScale(4)
 tracker.setStepSize(2)
 tracker.setEdgesDensity(0.1)
 tracking.track('#video_cam', tracker, { camera: true })
 tracker.on('track', function(event) {
 const { autoCaptureTrackTraking } = context
 canvasContext.clearRect(0, 0, canvas.width, canvas.height)
 event.data.forEach(function({ x, y, width, height }) {
  canvasContext.strokeStyle = '#a64ceb'
  canvasContext.strokeRect(x, y, width, height)
  canvasContext.font = '11px Helvetica'
  canvasContext.fillStyle = '#fff'
 })


 if (!isEmpty(event.data) && context.count <= 10) {
  if (context.count < 0) context.count = 0
  context.count += 1
  //debugHelper.log(context.count)
  if (context.count > 10) {
  context.isdetected = '已检测到人脸,正在登录'
  //context.$router.push({ name: 'pwdlogin' })
  }
 } else {
  context.count -= 1
  if (context.count < 0) context.isdetected = '请您保持脸部在画面中央'
  //this.isdetected = '已检测到人脸,正在登录'
 }
 
 })
 },
 onDownloadFile(item) {
 const link = document.createElement('a')
 link.href = item
 link.download = `cahyo-${new Date().toISOString()}.png`
 link.click()


 link.remove()
 },
 onTakeCam() {
 const canvas = document.createElement('canvas')
 const video = this.$el.querySelector('#video_cam')
 const canvasContext = canvas.getContext('2d')


 if (video.videoWidth && video.videoHeight) {
 const isBiggerW = video.videoWidth > video.videoHeight
 const fixVidSize = isBiggerW ? video.videoHeight : video.videoWidth
 let offsetLeft = 0
 let offsetTop = 0


 if (isBiggerW) offsetLeft = (video.videoWidth - fixVidSize) / 2
 else offsetTop = (video.videoHeight - fixVidSize) / 2


 // make canvas size 300px
 canvas.width = canvas.height = 300
 const { width, height } = canvas


 canvasContext.drawImage(
  video,
  offsetLeft,
  offsetTop,
  fixVidSize,
  fixVidSize,
  0,
  0,
  width,
  height
 )
 const image = canvas.toDataURL('image/png')
 this.images.push(image)
 }
 },
 onDetectFace(param, index) {
 const imgItem = document.querySelector(`.img-item-${index}`)
 const image = new Image()
 image.src = param


 const tracker = new tracking.ObjectTracker('face')
 tracker.setStepSize(1.7)
 tracking.track(image, tracker)


 tracker.on('track', function(event) {
 event.data.forEach(function(rect) {
  window.plot(rect.x, rect.y, rect.width, rect.height)
 })
 })


 window.plot = function(x, y, w, h) {
 const rect = document.createElement('div')
 document.querySelector(`.img-item-${index}`).appendChild(rect)
 rect.classList.add('rect')
 rect.style.width = w + 'px'
 rect.style.height = h + 'px'
 rect.style.left = x + 'px'
 rect.style.top = y + 'px'
 rect.style.border = '2px solid yellow'
 rect.style.position = 'absolute'
 }
 },
 getMediaStreamSuccess(stream) {
 window.stream = stream // make stream available to browser console
 this.videoEl.srcObject = stream
 debugHelper.log('getMediaStreamSuccess1')
 //this.$store.commit('setVideoCanvasObject', this.videoEl)
 debugHelper.log('getMediaStreamSuccess2')
 },
 // 视频媒体流失败
 getMediaStreamError(error) {
 alert('视频媒体流获取错误' + error)
 },
 // 结束媒体流
 stopMediaStreamTrack() {
 clearInterval(this.timeInterval)
 if (typeof window.stream === 'object') {
 this.videoEl.srcObject = null
 //this.$store.commit('setVideoCanvasObject', '')
 window.stream.getTracks().forEach(track => track.stop())
 }
 },

总结

到此这篇关于Vue+tracking.js 实现前端人脸检测功能的文章就介绍到这了,更多相关vue tracking.js 人脸检测内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery 获取对象 根据属性、内容匹配, 还有表单元素匹配
May 31 Javascript
漂亮的jquery提示效果(仿腾讯弹出层)
Feb 05 Javascript
jquery中交替点击事件的实现代码
Feb 14 Javascript
js面向对象编程之如何实现方法重载
Jul 02 Javascript
Javascript实现商品秒杀倒计时(时间与服务器时间同步)
Sep 16 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
Oct 16 Javascript
浅谈jquery.form.js的ajaxSubmit和ajaxForm的使用
Sep 09 Javascript
BootStrap Validator使用注意事项(必看篇)
Sep 28 Javascript
React-Native 组件之 Modal的使用详解
Aug 08 Javascript
jQuery实现手势解锁密码特效
Aug 14 jQuery
VUE页面中加载外部HTML的示例代码
Sep 20 Javascript
Vue中插入HTML代码的方法
Sep 21 Javascript
tracking.js实现前端人脸识别功能
Apr 16 #Javascript
electron 如何将任意资源打包的方法步骤
Apr 16 #Javascript
vue中keep-alive内置组件缓存的实例代码
Apr 16 #Javascript
详解Nuxt内导航栏的两种实现方式
Apr 16 #Javascript
javascript设计模式 ? 职责链模式原理与用法实例分析
Apr 16 #Javascript
vue下canvas裁剪图片实例讲解
Apr 16 #Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
Apr 16 #Javascript
You might like
DOTA2 探索永无止境 玩家自创强悍插眼攻略
2020/04/20 DOTA
在php中取得image按钮传递的name值
2006/10/09 PHP
Smarty foreach控制循环次数的实现详解
2013/07/03 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
使用swoole扩展php websocket示例
2014/02/13 PHP
php实现按照权重随机排序数据的方法
2015/01/09 PHP
php检查日期函数checkdate用法实例
2015/03/19 PHP
在html页面中包含共享页面的方法
2008/10/24 Javascript
用JS判别浏览器种类以及IE版本的几种方法小结
2011/08/02 Javascript
javascript获取当前鼠标坐标的方法
2015/01/10 Javascript
Angularjs+bootstrap+table多选(全选)支持单击行选中实现编辑、删除功能
2017/03/27 Javascript
angularjs路由传值$routeParams详解
2020/09/05 Javascript
vue登录路由验证的实现
2017/12/13 Javascript
vue .sync修饰符的使用详解
2018/06/15 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
JS实现可针对算术表达式求值的计算器功能示例
2018/09/04 Javascript
基于JS实现前端压缩上传图片的实例代码
2019/05/14 Javascript
微信小程序云函数添加数据到数据库的方法
2020/03/04 Javascript
vue键盘事件点击事件加native操作
2020/07/27 Javascript
python zip文件 压缩
2008/12/24 Python
python3图片转换二进制存入mysql
2013/12/06 Python
python发送邮件接收邮件示例分享
2014/01/21 Python
Python实现对比不同字体中的同一字符的显示效果
2015/04/23 Python
放弃 Python 转向 Go语言有人给出了 9 大理由
2017/10/20 Python
Python+tkinter使用40行代码实现计算器功能
2018/01/30 Python
python使用TensorFlow进行图像处理的方法
2018/02/28 Python
python实现list由于numpy array的转换
2018/04/04 Python
python将字符串转换成json的方法小结
2019/07/09 Python
python PyQt5/Pyside2 按钮右击菜单实例代码
2019/08/17 Python
波兰数码相机及配件网上商店: Cyfrowe.pl
2017/06/19 全球购物
介绍一下Python下range()函数的用法
2013/11/07 面试题
毕业生幼师求职自荐信
2013/10/01 职场文书
最新计算机专业自荐信
2013/10/16 职场文书
入党转预备思想汇报
2014/01/07 职场文书
给老师的检讨书
2014/02/11 职场文书
艺术设计专业求职自荐信
2014/05/19 职场文书