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 相关文章推荐
Knockoutjs的环境搭建教程
Nov 26 Javascript
jquery应该如何来设置改变按钮input的onclick事件
Dec 10 Javascript
JS模拟Dialog弹出浮动框效果代码
Oct 16 Javascript
基于jQuery实现表格的查看修改删除
Aug 01 Javascript
JS当前页面登录注册框,固定DIV,底层阴影的实例代码
Sep 29 Javascript
js实现可输入可选择的select下拉框
Dec 21 Javascript
JavaScript中的子窗口与父窗口的互相调用问题
Feb 08 Javascript
jQuery 控制文本框自动缩小字体填充
Jun 16 jQuery
javascript+html5+css3自定义弹出窗口效果
Oct 26 Javascript
每天学点Vue源码之vm.$mount挂载函数
Mar 11 Javascript
Javascript执行流程细节原理解析
May 14 Javascript
微信小程序实现电子签名功能
Jul 29 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
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
PHP的魔术常量__METHOD__简介
2014/07/08 PHP
CI框架常用方法小结
2016/05/17 PHP
PHP基于堆栈实现的高级计算器功能示例
2017/09/15 PHP
jquery 插件 人性化的消息显示
2008/01/21 Javascript
动态创建的表格单元格中的事件实现代码
2008/12/30 Javascript
在线编辑器中换行与内容自动提取
2009/04/24 Javascript
JavaScript中变量提升 Hoisting
2012/07/03 Javascript
jQuery jcrop插件截图使用方法
2013/11/20 Javascript
常用的JavaScript验证正则表达式汇总
2013/11/26 Javascript
在JavaScript中重写jQuery对象的方法实例教程
2014/08/25 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
2016/08/19 Javascript
vue.js+Element实现表格里的增删改查
2017/01/18 Javascript
vue.js vue-router如何实现无效路由(404)的友好提示
2017/12/20 Javascript
vue 音乐App QQ音乐搜索列表最新接口跨域设置方法
2018/09/25 Javascript
React+Redux实现简单的待办事项列表ToDoList
2019/09/29 Javascript
vue 强制组件重新渲染(重置)的两种方案
2019/10/29 Javascript
浅析微信小程序自定义日历组件及flex布局最后一行对齐问题
2020/10/29 Javascript
[08:47]DOTA2每周TOP10 精彩击杀集锦vol.6
2014/06/25 DOTA
[46:04]Liquid vs VP Supermajor决赛 BO 第四场 6.10
2018/07/05 DOTA
详解python3实现的web端json通信协议
2016/12/29 Python
python 中的int()函数怎么用
2017/10/17 Python
Pycharm运行加载文本出现错误的解决方法
2019/06/27 Python
Python 图像对比度增强的几种方法(小结)
2019/09/25 Python
python中的subprocess.Popen()使用详解
2019/12/25 Python
python多项式拟合之np.polyfit 和 np.polyld详解
2020/02/18 Python
快速解决jupyter启动卡死的问题
2020/04/10 Python
TripAdvisor越南:全球领先的旅游网站
2017/09/21 全球购物
世界上最大的皮肤科医生拥有和经营的美容网站:LovelySkin
2021/01/03 全球购物
儿科主治医生个人求职信
2013/09/23 职场文书
2014年保卫部工作总结
2014/11/21 职场文书
开票员岗位职责
2015/02/12 职场文书
护士自荐信怎么写
2015/03/06 职场文书
python 提取html文本的方法
2021/05/20 Python
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python
浅谈Python魔法方法
2021/06/28 Java/Android