如何使用VUE+faceApi.js实现摄像头拍摄人脸识别
作者: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摄像头拍摄人脸识别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!