vue html5 人脸识别登录

基本原理就是通过浏览器相关api打开本地摄像头,然后把视频流传给video标签播放出来,通过canvas进行图片截取,不断生成图片,进行人脸比对。

1、调取本地摄像头

        <!--展示摄像头视频流-->
        <video ref="video" width="462" height="462" autoplay></video>

        <!-- canvas截取图片 -->
        <canvas class="canv" ref="canvas" width="400" height="300"></canvas>
        // 调用摄像头
        callCamera() {
            // H5调用电脑摄像头API
            let videoObj = { video: true };
            var errBack = function (error) {
                console.log("Video capture error: ", error.code);
            };

            // 这个是最新版浏览器获取视频流的方法
            // 如果不需要兼容旧浏览器只写这一个方法即可
            if (navigator.mediaDevices.getUserMedia) { // Standard
                navigator.mediaDevices.getUserMedia(videoObj).then(stream => {
                    this.$refs["video"].srcObject = stream;
                    this.$refs["video"].play();
                    this.info = '请调整坐姿,对准摄像头!'
                    console.log('摄像头开启');
                    // 开始拍照
                    this.startCap();
                });
            } else if (navigator.getUserMedia) { // WebKit-prefixed
                navigator.webkitGetUserMedia(videoObj, function (stream) {
                    this.$refs["video"].src = window.URL.createObjectURL(stream);
                    this.$refs["video"].play();
                }, errBack);
            } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
                navigator.webkitGetUserMedia(videoObj, function (stream) {
                    this.$refs["video"].src = window.URL.createObjectURL(stream);
                    this.$refs["video"].play();
                }, errBack);
            }
            else if (navigator.mozGetUserMedia) { // Firefox-prefixed
                navigator.mozGetUserMedia(videoObj, function (stream) {
                    this.$refs["video"].mozSrcObject = stream;
                    this.$refs["video"].play();
                }, errBack);
            } 
        },

        // 开始拍照
        // 注意 这里使用了lodash的debounce方法(需要自行安装 lodash)
        startCap: _.debounce(function () {
            console.log('this', this);
            let ctx = this.$refs["canvas"].getContext("2d");
            // 把当前视频帧内容渲染到canvas上
            ctx.drawImage(this.$refs["video"], 0, 0, 400, 300);
            // 转base64格式、图片格式转换、图片质量压缩
            let imgBase64 = this.$refs["canvas"].toDataURL("image/jpeg", 0.7);
            // console.log('img --- ', imgBase64);
            // let str = imgBase64.replace("data:image/jpeg;base64,", "");
            var blob = this.dataURLtoBlob(imgBase64);
            var file = this.blobToFile(blob, Date.now());
            this.handleLogInByFace(file)
            
        }, 800),

        
        

2、canvas截取图片 转换位file文件

// canvas截取到的图片是base64的,如果后台对比支持base64格式的 直接传至后台即可
// 如果后台不支持base64格式的  需要将base64格式的转化位File格式,方法如下:

        // 这两个方法已经在上边的startcap方法中使用到了,目的就是转换为file文件的
        // 将base64转换为blob
        dataURLtoBlob (dataurl) { 
            var arr = dataurl.split(','),
                mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]),
                n = bstr.length,
                u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new Blob([u8arr], { type: mime });
        },
        //将blob转换为file
        blobToFile (theBlob, fileName){
            theBlob.lastModifiedDate = new Date();
            theBlob.name = fileName;
            return theBlob;
        },

3、拿到的图片请求接口 进行比对

// 这里就是开始请求后台接口了
// 需要注意的是  这个拍照是不断在拍的  不断的请求后台 只要比对失败  就继续拍照  直至成功

// 调用接口传图片请求
        async handleLogInByFace (file) {
            try {
                let id = 99;
                var formdata=new FormData();
                formdata.append("file", file);
                formdata.append("deptId", id);
                let res = await doLoginByFace(formdata);
                console.log('人脸请求', res);
                let {
                    code,
                    msg,
                    data
                } = res.data;
                if (code == 200) {
                    this.info = msg;
                    // 注意成功的时候  一定要结束占用摄像头
                    this.closeCamera();
                    sessionStorage.setItem('token', data);
                    this.$router.replace('/home').catch({}); 
                } else if (code == -2) {
                    this.$message({
                        type: 'error',
                        message: `${msg}`
                    })
                    this.$store.commit('CLEAR_LOGIN');
                    this.$router.push('/login').catch({});  
                } else {
                    this.info = msg;
                    var that = this;
                    this.startCap();
                }
            } catch(e) {
                console.log('requestOutStore',e)
            }
        },

        // 关闭摄像头
        closeCamera() {
            if (!this.$refs["video"].srcObject) {
                this.dialogCamera = false;
                return;
            }
            let stream = this.$refs["video"].srcObject;
            let tracks = stream.getTracks();
            tracks.forEach((track) => {
                track.stop();
            });
            this.$refs["video"].srcObject = null;
            this.clearInterval();
        },

最后,注意在页面销毁的时候,为了安全起见,还是再一次清除摄像头的占用。

猜你喜欢

转载自blog.csdn.net/jmszl1991/article/details/120559795
今日推荐