hberp/hb_client/src/components/faceLogin/tracking.vue

177 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="faceLoginWrap">
<div style="height:fit-content;">
<div class="video-box">
<video id="video" width="600" preload autoplay muted></video>
<canvas id="canvas" width="600" height="500"></canvas>
</div>
<canvas id="screenshotCanvas" width="600" height="500"></canvas>
</div>
</div>
</template>
<script>
import {clockRecord} from '@/api/hrm'
import tracking from '@/assets/tracking/build/tracking-min.js';
import '@/assets/tracking/build/data/face-min.js';
export default {
data() {
return {
video: null,
screenshotCanvas: null,
uploadLock: false // 上传锁
}
},
mounted() {
this.openTheCamera();
},
methods: {
openTheCamera() {
this.$nextTick(function () {
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(如果存在)
let 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)
})
}
}
let 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 () {
_this.video.play();
};
_this.init();
}).catch(err => {
console.log(err)
})
});
},
// 初始化设置
init() {
this.screenshotCanvas = document.getElementById('screenshotCanvas');
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
// 实例化tracker对象
let tracker = new window.tracking.ObjectTracker('face');
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
//tracker对象和标签关联
window.tracking.track('#video', tracker, {
camera: true
});
let _this = this;
//添加事件
tracker.on('track', function (event) {
// 检测出人脸 绘画人脸位置
context.clearRect(0, 0, canvas.width, canvas.height);
// 给每个人脸绘制对应的框
event.data.forEach(function (rect) {
context.strokeStyle = '#0764B7';
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
// window.plot(rect.x, rect.y, rect.width, rect.height+20);
// 避免重复发送请求
if (!_this.uploadLock) {
_this.uploadLock = true;
// 上传图片
_this.screenshotAndUpload();
}
});
});
},
// 上传图片
screenshotAndUpload() {
let that = this;
// 绘制当前帧图片转换为base64格式
let canvas = this.screenshotCanvas;
let video = this.video;
let ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
let base64Img = canvas.toDataURL('image/jpeg');
let img = base64Img.split(',')[1];
let imgData = {base64: img,tolerance:0.42};
clockRecord(imgData).then((res) => {
debugger;
if (res.code === 200 && res.data.id) {
this.$message.success(res.data.name + '签到成功!');
setTimeout(() => {
that.uploadLock = false;
}, 5000)
} else {
that.uploadLock = false;
}
}).catch(() => {
// 打开锁
that.uploadLock = false;
});
},
closeCamera() {
this.video.srcObject.getTracks()[0].stop();
},
}
}
</script>
<style scoped>
.faceLoginWrap{
/*padding: 50px;*/
/*width: 600px;*/
/*height: 600px;*/
/*background: #000000;*/
margin:50px auto 0 auto;
/*box-sizing: border-box;*/
}
#screenshotCanvas {
display: none;
}
.video-box {
width: 600px;
height: fit-content;
margin: auto;
position: relative;
}
#video {
object-fit: fill;
-webkit-border-radius: 250px;
-moz-border-radius: 250px;
border-radius: 250px;
}
video, canvas {
position: absolute;
top: 0;
left: 0;
}
</style>