参考文章:vue实现拍照人脸识别功能带人脸选中框
vue项目中使用trackingjs人脸识别
使用tracking js 实现
安装
npm install tracking --save
demo
<template>
<el-dialog
title="请直视摄像头方向并保持2秒时间"
width="700px"
custom-class='login-face-dialog'
:visible.sync="dialogVisible"
:close-on-click-modal='false'
:destroy-on-close='true'
@opened='hanldleOpen'
@close="handleClose"
>
<div class="testTracking" >
<video
id="video"
width="600"
height="400"
preload
autoplay
loop
muted
></video>
<canvas id="canvas" width="600" height="400"></canvas>
</div>
<div class="auth-tip" v-if='authType === "wait"'>
<i class='el-icon-loading'></i>
<span>认证中,请稍后...</span>
</div>
<div class="auth-failed" v-else-if='authType === "failed"'>
<div class='text'>人脸识别认证失败,请重新识别</div>
<el-button @click='handleClose'>取消</el-button>
<el-button type='primary' @click='hanldleOpen'>开始检测</el-button>
</div>
</el-dialog>
</template>
<script>
require("tracking/build/tracking-min.js");
require("tracking/build/data/face-min.js");
import { throttle } from '@/utils';
export default {
name: "testTracking",
props: {
visible: {
type: Boolean
}
},
created() {
this.submit = throttle(this.submit, 3000);
},
data() {
return {
trackerTask: null,
video: null,
authType: 'video', // video 正在识别中 wait 请求中 failed 认证失败
};
},
methods: {
hanldleOpen() {
this.authType = 'video';
this.getCompetence();
},
handleClose() {
this.de();
this.$emit('update:visible', false);
},
// 检测人脸
checkFace() {
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var tracker = new tracking.ObjectTracker("face");
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
this.trackerTask = tracking.track("#video", tracker, { camera: true });
tracker.on("track", event => {
if (event.data.length <= 0) {
return;
}
context.clearRect(0, 0, canvas.width, canvas.height);
event.data.forEach(function (rect) {
context.strokeStyle = '#a64ceb';
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
context.font = '11px Helvetica';
context.fillStyle = "#fff";
context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
});
setTimeout(() => {
this.submit();
}, 2000);
});
},
// 提取照片
submit() {
let that = this;
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let video = document.getElementById("video");
context.drawImage(video, 0, 0, 600, 400);
this.authType = 'wait';
canvas.toBlob((blob) => {
// axios.post({ faceUrl: URL.createObjectURL(blob) }).then((res) => {
// console.log("上传成功");
// });
// console.log(URL.createObjectURL(blob));
var reader = new FileReader();
if (blob) {
reader.onload = event => {
console.log(event.target.result);
setTimeout(() => {
this.authType = 'failed';
}, 2000);
}
}
reader.readAsDataURL(blob);
});
this.de();
},
// 打开摄像头
getCompetence() {
let _this = this;
this.video = document.getElementById("video");
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
// 使用getUserMedia,因为它会覆盖现有的属性。
// 这里,如果缺少getUserMedia属性,就添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
// 首先获取现存的getUserMedia(如果存在)
var getUserMedia =
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.getUserMedia;
// 有些浏览器不支持,会返回错误信息
// 保持接口一致
if (!getUserMedia) {
return Promise.reject(
new Error("getUserMedia is not implemented in this browser")
);
}
// 否则,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
var constraints = {
audio: false,
video: {
width: this.videoWidth,
height: this.videoHeight,
transform: "scaleX(-1)",
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
// 旧的浏览器可能没有srcObject
if ("srcObject" in _this.video) {
_this.video.srcObject = stream;
} else {
// 避免在新的浏览器中使用它,因为它正在被弃用。
_this.video.src = window.URL.createObjectURL(stream);
}
_this.video.onloadedmetadata = function (e) {
_this.video.play();
};
_this.checkFace();
})
.catch((err) => {
console.log(err);
});
},
// 关闭摄像头
de() {
this.video.srcObject.getTracks()[0].stop();
this.trackerTask.stop();
},
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(flag) {
this.$emit('update:visible', flag);
}
}
},
destroyed() {
this.de();
}
};
</script>
<style>
.auth-failed .text {
margin-bottom: 20px;
}
.auth-failed .el-button {
width: 98px;
}
.testTracking {
height: 420px;
width: 100%;
position: relative;
}
.testTracking > * {
position: absolute;
left: 0;
right: 0;
margin: auto;
}
.testTracking video, .testTracking canvas {
top: 0;
}
.testTracking .buttonDiv {
bottom: 10px;
}
</style>
export function throttle(fn, interval = 500) {
let lastTime = 0;
return function(...args) {
if (Date.now() - lastTime < interval) {
return;
}
lastTime = Date.now();
fn.apply(this, args);
};
}