如何使用VUE+faceApi.js实现摄像头拍摄人脸识别

 更新时间:2023年05月04日 11:59:27   作者:BarryKerrigan  
Face-api.js是一个JavaScript API,是基于tensorflow.js核心API 的人脸检测和人脸识别的浏览器实现,这篇文章主要给大家介绍了关于如何使用VUE+faceApi.js实现摄像头拍摄人脸识别的相关资料,需要的朋友可以参考下

需求:

前端获取到摄像头信息,通过模型来进行判断人像是否在镜头中,镜头是否有被遮挡。

实现步骤:

1、通过video标签来展示摄像头中的内容

2、通过canvas来绘制视频中信息进行展示

3、在拍照时候将canvas的当前帧转成图片

第一步:下载引入必要包

下载依赖

face-api.js是核心依赖必须要下

npm install face-api.js

element-ui为了按钮好看一点(可以不下) ,axios用于请求发送

npm istall element-ui axios -S

 element-ui根据官方文档进行引入使用

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({
  el: '#app',
  render: h => h(App)
});

下载model

下载地址: 模板地址

将项目中的model放入VUE中的public文件加下

第二步:先把HTML写上去 

<template>
    <div>
        <el-button type="primary" @click="useCamera">打开摄像头</el-button>
        <el-button type="plain" @click="photoShoot">拍照</el-button>
        <el-alert
            :title="httpsAlert"
            type="info"
            :closable="false"
            v-show="httpsAlert !== ''">
        </el-alert>
        <div class="videoImage" ref="faceBox">
            <video ref="video" style="display: none;"></video>
            <canvas ref="canvas" width="400" height="400" v-show="videoShow"></canvas>
            <img ref="image" :src="picture" alt="" v-show="pictureShow">
        </div>
    </div>
</template>

第三步 可以开始代码了

首先引入下载好的face-api.js包

import * as faceApi from 'face-api.js'

 以下是需要用到的属性

1、视频和图片不同时出现

videoShow: false,
pictureShow: false,

2、生成图片后用于保存图片路径

picture: '',

3、因为在操作时会用到DOM所以将要用到虚拟DOM保存在data中

canvas: null,
video: null,
image: null,

 4、模型识别时直接传入此属性,在初始化时赋值(可省略,直接卸载逻辑代码中)

options: ''

 5、在人脸识别时对结果进行反馈(识别出人像数量大于1或小于1时给出提示)

noOne: '',
moreThanOne: '',

6、如果用户不是在https下进行使用摄像头调用给出提示

httpsAlert: ''

属性准备好之后就可以开始初始化了

1、初始化模型

2、获取需要用到的虚拟DOM

async init() {
    await faceApi.nets.ssdMobilenetv1.loadFromUri("/models");
    await faceApi.loadFaceLandmarkModel("/models");
    this.options = new faceApi.SsdMobilenetv1Options({
        minConfidence: 0.5, // 0.1 ~ 0.9
    });
    // 视频中识别使用的节点
    this.video = this.$refs.video
    this.canvas = this.$refs.canvas
    this.image = this.$refs.image
}

调用摄像头

通过navigator.mediaDevices.getUserMedia()

useCamera(){
    this.videoShow = true
    this.pictureShow = false
    this.cameraOptions()
},
cameraOptions(){
    let constraints = {
        video: {
            width: 400,
            height: 400
        }
    }
    // 如果不是通过loacalhost或者通过https访问会将报错捕获并提示
    try{
        let promise = navigator.mediaDevices.getUserMedia(constraints);
        promise.then((MediaStream) => {
            // 返回参数
            this.video.srcObject = MediaStream;
            this.video.play();
            this.recognizeFace()
        }).catch((error) => {
            console.log(error);
        });
    }catch(err){
        this.httpsAlert = `您现在在使用非Https访问,
        请先在chrome://flags/#unsafely-treat-insecure-origin-as-secure中修改配置,
        添将当前链接${window.location.href}添加到列表,
        并且将Insecure origins treated as secure修改为enabled,
        修改完成后请重启浏览器后再次访问!`
    }
}

识别视频中的人像

这里通过递归的方式将视频中的内容用canvas显示

将canvas的节点传入到faceApi的方法中进行识别

通过faceApi返回的数组可以得到当前人脸的识别状况(数组长度0没有识别到人脸,长度1识别到一个人脸...以此类推)

async recognizeFace(){
    if (this.video.paused) return clearTimeout(this.timeout);
    this.canvas.getContext('2d', { willReadFrequently: true }).drawImage(this.video, 0, 0, 400, 400);
    const results = await faceApi.detectAllFaces(this.canvas, this.options).withFaceLandmarks();
    if(results.length === 0){
        if(this.moreThanOne !== ''){
            this.moreThanOne.close()
            this.moreThanOne = ''
        }
        if(this.noOne === ''){
            this.noOne = this.$message({
                message: '未识别到人脸',
                type: 'warning',
                duration: 0
            });
        }
    }else if(results.length > 1){
        if(this.noOne !== ''){
            this.noOne.close()
            this.noOne = ''
        }
        if(this.moreThanOne === ''){
            this.moreThanOne = this.$message({
                message: '检测到镜头中有多个人',
                type: 'warning',
                duration: 0
            });
        }
    }else{
        if(this.noOne !== ''){
            this.noOne.close()
            this.noOne = ''
        }
        if(this.moreThanOne !== ''){
            this.moreThanOne.close()
            this.moreThanOne = ''
        }
    }
    this.timeout = setTimeout(() => {
        return this.recognizeFace()
    });
},

拍照上传 

async photoShoot(){
    // 拿到图片的base64
    let canvas = this.canvas.toDataURL("image/png");
    // 拍照以后将video隐藏
    this.videoShow = false
    this.pictureShow = true
    // 停止摄像头成像
    this.video.srcObject.getTracks()[0].stop()
    this.video.pause()
    if(canvas) {
        // 拍照将base64转为file流文件
        let blob = this.dataURLtoBlob(canvas);
        let file = this.blobToFile(blob, "imgName");
        // 将blob图片转化路径图片
        let image = window.URL.createObjectURL(file)
        this.picture = image
        return
        let formData = new FormData()
        formData.append('file', this.picture)
        axios({
            method: 'post',
            url: '/user/12345',
            data: formData
        }).then(res => {
            console.log(res)
        }).catch(err => {
            console.log(err)
        })
    } else {
        console.log('canvas生成失败')
    }
},

需要用到的图片格式转换方法 

方法1:先将base64转为文件

方法2:设置新的文件中的参数信息

dataURLtoBlob(dataurl) {
    let 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
    });
},
blobToFile(theBlob, fileName) {
    theBlob.lastModifiedDate = new Date().toLocaleDateString();
    theBlob.name = fileName;
    return theBlob;
},

完整代码

import bingImage from '@/assets/bbt1.jpg';
import BingWallpaper from '@/assets/BingWallpaper.jpg';
import * as faceApi from 'face-api.js'
export default {
    name: 'Recognize',
    data(){
        return{
            videoShow: false,
            pictureShow: false,
            // 图片地址
            picture: '',
            // 用于视频识别的节点
            canvas: null,
            video: null,
            image: null,
            timeout: 0,
            // 模型识别的条件
            options: '',
            // 提示控制
            noOne: '',
            moreThanOne: '',
            // 不是通过Https访问提示
            httpsAlert: '',
        }
    },
    mounted() {
        // 初始化
        this.init()
    },
    beforeDestroy() {
        clearTimeout(this.timeout);
    },
    methods: {
        async init() {
            await faceApi.nets.ssdMobilenetv1.loadFromUri("/models");
            await faceApi.loadFaceLandmarkModel("/models");
            this.options = new faceApi.SsdMobilenetv1Options({
                minConfidence: 0.5, // 0.1 ~ 0.9
            });
            // 视频中识别使用的节点
            this.video = this.$refs.video
            this.canvas = this.$refs.canvas
            this.image = this.$refs.image
        },
        /**
         * 使用视频来成像摄像头
         */
        useCamera(){
            this.videoShow = true
            this.pictureShow = false
            this.cameraOptions()
        },
        /**
         * 使用摄像头
         */
        cameraOptions(){
            let constraints = {
                video: {
                    width: 400,
                    height: 400
                }
            }
            // 如果不是通过loacalhost或者通过https访问会将报错捕获并提示
            try{
                let promise = navigator.mediaDevices.getUserMedia(constraints);
                promise.then((MediaStream) => {
                    // 返回参数
                    this.video.srcObject = MediaStream;
                    this.video.play();
                    this.recognizeFace()
                }).catch((error) => {
                    console.log(error);
                });
            }catch(err){
                this.httpsAlert = `您现在在使用非Https访问,
                请先在chrome://flags/#unsafely-treat-insecure-origin-as-secure中修改配置,
                添将当前链接${window.location.href}添加到列表,
                并且将Insecure origins treated as secure修改为enabled,
                修改完成后请重启浏览器后再次访问!`
            }
        },
        /**
         * 人脸识别方法
         * 通过canvas节点识别
         * 节点对象执行递归识别绘制
         */
        async recognizeFace(){
            if (this.video.paused) return clearTimeout(this.timeout);
            this.canvas.getContext('2d', { willReadFrequently: true }).drawImage(this.video, 0, 0, 400, 400);
            const results = await faceApi.detectAllFaces(this.canvas, this.options).withFaceLandmarks();
            if(results.length === 0){
                if(this.moreThanOne !== ''){
                    this.moreThanOne.close()
                    this.moreThanOne = ''
                }
                if(this.noOne === ''){
                    this.noOne = this.$message({
                        message: '未识别到人脸',
                        type: 'warning',
                        duration: 0
                    });
                }
            }else if(results.length > 1){
                if(this.noOne !== ''){
                    this.noOne.close()
                    this.noOne = ''
                }
                if(this.moreThanOne === ''){
                    this.moreThanOne = this.$message({
                        message: '检测到镜头中有多个人',
                        type: 'warning',
                        duration: 0
                    });
                }
            }else{
                if(this.noOne !== ''){
                    this.noOne.close()
                    this.noOne = ''
                }
                if(this.moreThanOne !== ''){
                    this.moreThanOne.close()
                    this.moreThanOne = ''
                }
            }
            // 通过canvas显示video信息
            this.timeout = setTimeout(() => {
                return this.recognizeFace()
            });
        },
        /**
         * 拍照上传
         */
        async photoShoot(){
            // 拿到图片的base64
            let canvas = this.canvas.toDataURL("image/png");
            // 拍照以后将video隐藏
            this.videoShow = false
            this.pictureShow = true
            // 停止摄像头成像
            this.video.srcObject.getTracks()[0].stop()
            this.video.pause()
            if(canvas) {
                // 拍照将base64转为file流文件
                let blob = this.dataURLtoBlob(canvas);
                console.log(blob)
                let file = this.blobToFile(blob, "imgName");
                console.info(file);
                // 将blob图片转化路径图片
                let image = window.URL.createObjectURL(file)
                this.picture = image
                // 将拍照后的图片发送给后端
                let formData = new FormData()
                formData.append('file', this.picture)
                axios({
                    method: 'post',
                    url: '/user/12345',
                    data: formData
                }).then(res => {
                    console.log(res)
                }).catch(err => {
                    console.log(err)
                })
            } else {
                console.log('canvas生成失败')
            }
        },
        /**
         * 将图片转为blob格式
         * dataurl 拿到的base64的数据
         */
        dataURLtoBlob(dataurl) {
            let 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
            });
        },
        /**
         * 生成文件信息
         * theBlob 文件
         * fileName 文件名字
         */
        blobToFile(theBlob, fileName) {
            theBlob.lastModifiedDate = new Date().toLocaleDateString();
            theBlob.name = fileName;
            return theBlob;
        },
    }
}

总结

到此这篇关于如何使用VUE+faceApi.js实现摄像头拍摄人脸识别的文章就介绍到这了,更多相关VUE faceApi.js摄像头拍摄人脸识别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue 导入js中的两种方法(示例详解)

    vue 导入js中的两种方法(示例详解)

    这篇文章主要介绍了vue 导入js中的方法,本文通过两种方法结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • vue3中sync修饰符的使用详解

    vue3中sync修饰符的使用详解

    .sync修饰符是Vue中用于实现子组件修改父组件传递的props值并更新到父组件的功能,它实际上是一个语法糖,将子组件的props绑定到一个名为update:propName的自定义事件上,本文给大家介绍了vue3中sync修饰符的使用,需要的朋友可以参考下
    2023-10-10
  • Vue 日期获取的示例代码

    Vue 日期获取的示例代码

    moment.js是一款现在对时间处理的强大的函数,这篇文章主要介绍了Vue 日期获取的示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • vue 如何使用递归组件

    vue 如何使用递归组件

    这篇文章主要介绍了vue 如何使用递归组件,帮助大家更好的理解和使用vue,完成开发需求,感兴趣的朋友可以了解下
    2020-10-10
  • 详解Vue2和Vue3的区别以及其钩子函数的使用

    详解Vue2和Vue3的区别以及其钩子函数的使用

    Vue.js 3 和 Vue.js 2 是两个主要版本的流行前端框架,它们之间有很多区别,包括性能优化、新特性和改进的API等,下面就跟随小编一起来看看他们的使用区别吧
    2024-01-01
  • Vue2.x 项目性能优化之代码优化的实现

    Vue2.x 项目性能优化之代码优化的实现

    这篇文章主要介绍了Vue2.x 项目性能优化之代码优化的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Vue3实现获取验证码按钮倒计时效果

    Vue3实现获取验证码按钮倒计时效果

    这篇文章主要介绍了Vue3实现获取验证码按钮倒计时效果,用户点击获取验证码按钮,发送请求给后端,按钮失效,并且开始倒计时60秒;在此期间,用户无法再次点击按钮,即使用户刷新页面,倒计时依然存在,直到倒计时完毕,按钮恢复,感兴趣的小伙伴跟着小编一起来看看吧
    2024-10-10
  • Vue CLI 命令行打包配置自定义参数方式

    Vue CLI 命令行打包配置自定义参数方式

    这篇文章主要介绍了Vue CLI 命令行打包配置自定义参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 基于vue2.x的电商图片放大镜插件的使用

    基于vue2.x的电商图片放大镜插件的使用

    本篇文章主要介绍了基于vue2.x的电商图片放大镜插件的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • vue项目纯前端实现的模板打印功能示例代码

    vue项目纯前端实现的模板打印功能示例代码

    在Vue项目中,通过使用vue-print-nb插件,可以实现页面的打印功能,这篇文章主要介绍了vue项目纯前端实现的模板打印功能的相关资料,需要的朋友可以参考下
    2024-10-10

最新评论