实现思路
1.利用手机的前置摄像头获取视频流
2.利用第三方插件tracking.js捕获人脸部分
3.捕获到人脸后利用canvas绘制带人脸的照片(业务需要:转为base64编码)
4.将绘制带人脸的照片和其他数据上传到第三方校验平台进行识别对比校验
5.结束完工 (getUserMedia要在https的安全域名下使用)
html
<!DOCTYPE html>
<html lang=en style="font-size: 37.5px">
<head>
<meta charset=utf-8>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>人脸检测</title>
<script src="../vue.min.2.6.js"></script>
<script src="../tracking/tracking.js"></script>
<script src="../tracking/data/face-min.js"></script>
</head>
<style>
.face-capture {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
color: #FF0000;
position: relative;
}
.face-capture .title {
position: absolute;
top: 100px;
color: #FF0000;
font-size: 18px;
z-index: 10;
}
.face-capture .rect {
border: 2px solid #0aeb08;
position: absolute;
z-index: 3;
}
</style>
<body>
<div id="app">
<div v-show="showContainer" class="face-capture" id="face-capture">
<video ref="refVideo" id="video" :width="screenSize.width" :height="screenSize.height" muted webkit-playsinline playsinline></video>
<div class="title">{{scanTip}}</div>
<canvas ref="refCanvas" :width="screenSize.width" :height="screenSize.height" :style="{opacity: 0}"></canvas>
<div class="rect" v-for="item in profile"
:style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}">
</div>
</div>
<img v-show="!showContainer" :src="imgUrl"/>
</div>
</body>
</html>
javascript
const app = new Vue({
el: "#app",
data() {
return {
screenSize: {width: 320, height: 320},
URL: null,
streamIns: null,
showContainer: true,
tracker: null,
tipFlag: false,
flag: false,
context: null,
profile: [],
removePhotoID: null,
scanTip: '加载中...',
imgUrl: ''
}
},
mounted() {
this.playVideo()
},
methods: {
getUserMedia(constraints, success, error) {
window.navigator.getUserMedia = navigator.getUserMedia || navigator.webKitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
navigator.webkitGetUserMedia(constraints, success, error)
} else if (navigator.mozGetUserMedia) {
navigator.mozGetUserMedia(constraints, success, error);
} else if (navigator.getUserMedia) {
navigator.getUserMedia(constraints, success, error)
} else {
this.scanTip = "你的浏览器不支持访摄像头调用"
}
},
success(stream) {
this.streamIns = stream;
this.URL = window.URL || window.webkitURL;
if ("srcObject" in this.$refs.refVideo) {
this.$refs.refVideo.srcObject = stream
} else {
this.$refs.refVideo.src = this.URL.createObjectURL(stream)
}
this.scanTip = '人脸识别中...';
this.$refs.refVideo.play();
this.initTracker()
},
error(e) {
this.scanTip = "访问用户媒体失败" + e.name + "," + e.message
},
playVideo() {
var constraints = {
video: {
width: 320,
height: 320,
facingMode: "user"
}
};
this.getUserMedia(constraints, this.success, this.error);
},
initTracker() {
this.context = this.$refs.refCanvas.getContext("2d");
this.tracker = new tracking.ObjectTracker(['face']);
this.tracker.setStepSize(1.7);
this.tracker.on('track', this.handleTracked);
try {
tracking.track('#video', this.tracker);
} catch (e) {
this.scanTip = "访问用户媒体失败,请重试";
}
},
handleTracked(e) {
console.log(e);
if (e.data.length === 0) {
this.scanTip = '未检测到人脸';
} else {
if (!this.tipFlag) {
this.scanTip = '检测成功,正在拍照,请保持不动2秒';
}
if (!this.flag) {
this.scanTip = '拍照中...';
this.flag = true;
this.removePhotoID = setTimeout(() => {
this.tackPhoto();
this.tipFlag = true
}, 2000)
}
e.data.forEach(this.plot)
}
},
plot({x, y, width: w, height: h}) {
this.profile.push({width: w, height: h, left: x, top: y})
},
tackPhoto() {
this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
this.close()
},
getBlobBydataURI(dataURI, type) {
var binary = window.atob(dataURI.split(',')[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: type
});
},
saveAsPNG(c) {
return c.toDataURL('image/png', 0.3)
},
close() {
this.flag = false;
this.tipFlag = false;
this.showFailPop = false;
this.showContainer = false;
this.tracker && this.tracker.removeListener('track', this.handleTracked)
this.tracker = null;
this.context = null;
this.profile = []
this.scanTip = '人脸识别中...'
clearTimeout(this.removePhotoID)
if (this.streamIns) {
this.streamIns.enabled = false
this.streamIns.getTracks()[0].stop()
this.streamIns.getVideoTracks()[0].stop()
}
this.streamIns = null
}
}
})