一、前言
1.主要内容:使用tracking.js实现捕捉到人脸后拍照功能。
2.tracking.js
Tracking.js 是一个独立的JavaScript库,用于跟踪从相机实时收到的数据。跟踪的数据既可以是颜色,也可以是人,也就是说我们可以通过检测到某特定颜色,或者检测一个人体/脸的出现与移动,来触发JavaScript 事件。它是非常易于使用的API,具有数个方法和事件(足够使用了)。 —— 努力挣钱的小鑫
3.实现效果实例
二、功能实现
1.引入tracking.js
这里使用的方式是在tracking.js官网下载,将tracking-min.js与face.js文件直接放到项目中。
使用人脸跟踪器核心代码
// 创建一个人脸跟踪器对象
var objects = new tracking.ObjectTracker('face');
// 创建监听事件
objects.on('track', function(event) {
if (event.data.length === 0) {
// No objects were detected in this frame.
} else {
event.data.forEach(function(rect) {
// rect.x, rect.y, rect.height, rect.width
});
}
});
2.拍照组件
<template>
<div class="face_recognition">
<div class="video_box">
<video
id="video"
preload
autoplay
loop
muted
x5-video-player-type="h5-page"
webkit-playsinline="true"
playsinline="true"
width="250"
height="250"
></video>
<!-- canvas用来绘制识别出人脸的矩形框 -->
<canvas id="canvas" width="250" height="250"></canvas>
<!-- canvas1用来截取video中识别到人脸的某一帧照片 -->
<canvas id="canvas1" width="250" height="250"></canvas>
</div>
</div>
</template>
<script>
import './tracking-min.js';
import './face-min.js';
import { Toast } from 'vant';
export default {
name: 'faceRecognition',
data() {
return {
deviceId: '',
saveArray: {},
trackerTask: null,
tracker: null,
canvasContext: null,
canvas: null,
videoEl: {}
};
},
methods: {
openVideo() {
this.steps = 'screen';
this.canvas = document.getElementById('canvas');
this.canvasContext = this.canvas.getContext('2d');
// 创建一个人脸跟踪器对象
this.tracker = new tracking.ObjectTracker('face');
// 设置识别的放大比例
this.tracker.setInitialScale(4);
// 设置步长
this.tracker.setStepSize(2);
// 边缘密度
this.tracker.setEdgesDensity(0.1);
// 打开相机
this.trackerTask = tracking.track('#video', this.tracker, {
camera: true
});
this.videoEl = document.getElementById('video');
this.isUndefinedForGetuserMedia();
},
// 判读是否支持getUserMedia api
isUndefinedForGetuserMedia() {
tracking
.promiseInitUserMedia_(this.videoEl, {
camera: true
})
.catch(() => {
Toast('暂不支持自动人脸识别,请点击拍照识别');
this.$emit('isAutoRecognition', false);
});
},
judgeFace() {
let tipFlag = false; // 是否检测
let faceflag = false; // 是否进行拍照
const that = this;
// 创建监听 每帧都会触发
this.tracker.on('track', function (event) {
if (!tipFlag) {
// 擦除一个透明的矩形区域
that.canvasContext.clearRect(
0,
0,
that.canvas.width,
that.canvas.height
);
if (event.data.length === 0) {
// 未检测到人脸
if (!faceflag) {
Toast('未检测到人脸');
}
} else if (event.data.length === 1) {
// 长度为多少代表检测到几张人脸
// 检测到一张人脸
if (!tipFlag) {
Toast('识别成功,正在拍照,请勿乱动~');
// 给检测到的人脸绘制矩形
event.data.forEach(function (rect) {
that.canvasContext.strokeStyle = '#a64ceb';
that.canvasContext.strokeRect(
rect.x,
rect.y,
rect.width,
rect.height
);
});
if (!faceflag) {
// 检测到人脸进行拍照,延迟三秒
faceflag = true;
setTimeout(() => {
that.getPhoto(); // 拍照
tipFlag = true;
}, 3000);
}
}
} else {
// 检测到多张人脸
if (!faceflag) {
Toast('只可一人进行人脸识别!');
}
}
}
});
},
// 获取人像照片
getPhoto() {
try {
const canvas1 = document.getElementById('canvas1');
const context2 = canvas1.getContext('2d');
// 在canvas1上绘制video中的人像照片
context2.drawImage(this.videoEl, 0, 0, 250, 250);
this.keepImg();
} catch (error) {}
},
// 将canvas转化为图片
convertCanvasToImage(canvas) {
const image = new Image();
image.src = canvas.toDataURL('image/jpeg');
return image;
},
// 保存图片
keepImg() {
const canvas1 = document.getElementById('canvas1');
const base64 = this.convertCanvasToImage(canvas1).src;
// 拿到检测到人脸图片的base64编码,可根据后续业务场景转换类型
this.$emit('videoChange', base64);
},
closeFace() {
try {
this.clearCanvas();
// 关闭摄像头
if (typeof window.stream === 'object') {
this.videoEl.srcObject = null;
window.stream.getTracks().forEach((track) => track.stop());
}
// 停止侦测
this.trackerTask.stop(); // this.trackerTask.run(); 重新执行侦测
} catch (error) {
// eslint-disable-next-line no-console
console.log('err', error);
}
},
clearCanvas() {
const c = document.getElementById('canvas');
const c1 = document.getElementById('canvas1');
const cxt = c.getContext('2d');
const cxt1 = c1.getContext('2d');
cxt.clearRect(0, 0, 250, 250);
cxt1.clearRect(0, 0, 250, 250);
}
}
};
</script>
<style lang="scss" scoped>
.face_recognition {
height: 250px;
.video_box {
align-items: center;
display: flex;
height: 250px;
justify-content: center;
margin: auto;
position: relative;
width: 250px;
#video {
border-radius: 50%;
height: 100%;
object-fit: cover;
width: 100%;
}
#canvas {
height: 100%;
left: 0;
position: absolute;
top: 0;
transform: rotateY(180deg);
width: 100%;
}
#canvas1 {
opacity: 0;
position: absolute;
}
}
}
</style>
3.tracking-min.js
// 需要将错误抛出到调用层
(tracking.promiseInitUserMedia_ = function (
r,
n,
facingMode = { facingMode: { exact: 'environment' } } // 场景需要强制使用后置摄像头,如果要用前置将这里改为'user'
) {
return new Promise((resolve, reject) => {
t.navigator.mediaDevices
.getUserMedia({
video: facingMode,
audio: !(!n || !n.audio)
}) // 使用navigator.mediaDevices.getUserMediaAPI打开相机
.then(function (t) {
r.srcObject = t;
window.stream = t; // 关闭摄像头需要
resolve(true);
})
['catch'](function (t) {
reject('Cannot capture user camera.');
});
});
}),
三、其他
1.base64、file、blob类型转换与使用compressorjs进行图片压缩
使用compressorjs进行图片压缩 - 掘金 (juejin.cn)
2.参考文章
【tracking.js】前端人脸识别框架 Tracking.js 活体检测/拍照实现 - 努力挣钱的小鑫 - 博客园 (cnblogs.com)