Vue+tracking.js 實(shí)現(xiàn)前端人臉檢測功能
項(xiàng)目中需要實(shí)現(xiàn)人臉登陸功能,實(shí)現(xiàn)思路為在前端檢測人臉,把人臉照片發(fā)送到后端識別,返回用戶token登陸成功
前端調(diào)用攝像頭使用tracking.js檢測視頻流中的人臉,檢測到人臉后拍照上傳后端。
后端使用face_recognition人臉識別庫,使用Flask提供restfulAP供前端調(diào)用
實(shí)現(xiàn)效果如下圖:
登陸界面:

攝像頭檢測人臉界面:

前端代碼如下:
<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(應(yīng)用最理想的)
width: {
min: 320,
ideal: 1280,
max: 1920
},
height: {
min: 240,
ideal: 720,
max: 1080
},
// frameRate受限帶寬傳輸時,低幀率可能更適宜
frameRate: {
min: 15,
ideal: 30,
max: 60
},
// 攝像頭翻轉(zhuǎn)
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)
},
// 結(jié)束媒體流
stopMediaStreamTrack() {
clearInterval(this.timeInterval)
if (typeof window.stream === 'object') {
this.videoEl.srcObject = null
//this.$store.commit('setVideoCanvasObject', '')
window.stream.getTracks().forEach(track => track.stop())
}
},
總結(jié)
到此這篇關(guān)于Vue+tracking.js 實(shí)現(xiàn)前端人臉檢測功能的文章就介紹到這了,更多相關(guān)vue tracking.js 人臉檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue render渲染時間戳轉(zhuǎn)時間,時間轉(zhuǎn)時間戳及渲染進(jìn)度條效果
這篇文章主要介紹了Vue render渲染時間戳轉(zhuǎn)時間,時間轉(zhuǎn)時間戳及渲染進(jìn)度條效果,通過實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2018-07-07
使用vue-router與v-if實(shí)現(xiàn)tab切換遇到的問題及解決方法
這篇文章主要介紹了vue-router與v-if實(shí)現(xiàn)tab切換的思考,需要的朋友可以參考下2018-09-09
Vue如何獲取new Date().getTime()時間戳
在Web開發(fā)中,前端使用Vue.js獲取的是毫秒級時間戳,而PHP后端則是秒級時間戳,處理此類問題時,需要將PHP的時間戳乘以1000轉(zhuǎn)換為毫秒級,以保證數(shù)據(jù)的一致性和正確的邏輯判斷2024-10-10
vue登錄以及權(quán)限驗(yàn)證相關(guān)的實(shí)現(xiàn)
這篇文章主要介紹了vue登錄以及權(quán)限驗(yàn)證相關(guān)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
vue子組件實(shí)時獲取父組件的數(shù)據(jù)實(shí)現(xiàn)
本文主要介紹了vue子組件實(shí)時獲取父組件的數(shù)據(jù)實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12
Element InfiniteScroll無限滾動的具體使用方法
這篇文章主要介紹了Element InfiniteScroll無限滾動的具體使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
vue3中使用highlight.js實(shí)現(xiàn)代碼高亮顯示的代碼示例
代碼高亮是在網(wǎng)頁開發(fā)中常見的需求之一,它可以使代碼在頁面上以不同的顏色或樣式進(jìn)行突出顯示提高可讀性,這篇文章主要介紹了vue3中使用highlight.js實(shí)現(xiàn)代碼高亮顯示的相關(guān)資料,需要的朋友可以參考下2025-04-04

