你好,我是Vam的金豆之路,可以叫我豆哥。2019年年度博客之星、技术领域博客专家。主要领域:前端开发。我的微信是 maomin9761,有什么疑问可以加我哦,自己创建了一个微信技术交流群,可以加我邀请你一起交流学习。最后自己也创建了一个微信公众号:前端历劫之路,欢迎关注。


欢迎阅读本博文,本博文主要讲述【Vue回炉重造之封装一个实用的人脸识别组件】,文字通俗易懂,如有不妥,还请多多指正。

前言

人脸识别技术现在越来越火,那么我们今天教大家实现一个人脸识别组件。

资源

  • element UI
  • Vue.js
  • tracking-min.js
  • face-min.js

源码

由于我们的电脑有的有摄像头,有的没有摄像头,所以我们需要根据不同的场景来封装这个组件。先放个图吧,大家可以看得更加直观一些。

有摄像头的话,我们就显示(需要人像识别组件):

没有摄像头的话,我们就显示(这个直接上传人像即可):

判断有无摄像头,我们可以使用这个方法:

// 判断有无摄像头,推荐放在created里var deviceList = [];navigator.mediaDevices.enumerateDevices().then(devices => {devices.forEach(device => {deviceList.push(device.kind);});if (deviceList.indexOf("videoinput") == "-1") {console.info("没有摄像头");return false;} else {console.info("有摄像头");this.videoinput = true; // 这是我自定义的一个状态,初始值为false}}).catch(function(err) {alert(err.name + ": " + err.message);});

完整代码:

index.vue

<template>
<!-- 人脸识别 --><el-dialog:visible.sync="openFaceView"width="581px":show-close="false"v-loading="faceloading"element-loading-text="人脸识别中"><div class="ovf" style="padding:20px;"><el-uploadv-if="!videoinput"class="upload-demo"actionmultiple:limit="1":file-list="fileList":on-change="handleChange":on-exceed="handleExceed":before-remove="beforeRemove":auto-upload="false"><el-button size="small" type="primary">点击上传人像图片</el-button></el-upload><div v-if="videoinput"><el-button size="small" type="primary" @click="checkFace">点击进行人脸识别</el-button><div slot="tip" class="el-upload__tip">此功能需到非IE浏览器进行</div></div><div class="dialog-footer"><el-button @click="openFaceView = false">取 消</el-button><el-button type="primary" @click="postFace()">确 定</el-button></div></div></el-dialog><el-dialog :visible.sync="checkFaceView" width="581px" :show-close="false"><Face :faceView="checkFaceView" @canvasToImage="getImgFile"></Face></el-dialog>
</template>
<script>
import { verifyFace } from "../../request/api"; //引入人脸识别接口
import Face from "./Face"; // 引入人脸识别组件
export default {name: "MyClassRoom",data() {return {openFaceView:true,faceloading: false,videoinput: false,fileList: [],face: "",}},components: {Face},methods: {// 弹出人脸识别框checkFace() {this.checkFaceView = true;},// 限制上传照片handleExceed() {this.$message.warning({message: "不要重复上传!",offset: 380,duration: 1000});},// 移除人像图片beforeRemove(file) {return this.$confirm(`确定移除 ${file.name}?`);},// 上传的文件handleChange(file) {this.face = file.raw;},// 获取截取图片getImgFile(d) {this.face = d;this.checkFaceView = false;},// 人脸识别完毕postFace() {this.faceloading = true;this.checkFaceView=false;let formData = new FormData();formData.append("face", this.face);/*人脸识别接口,把获取到的照片传到后台,我这里使用了封装axios。需要注意使用   config.headers = {'Content-Type':'multipart/form-data'} 传照片*/verifyFace(formData, { isUpload: true }) .then(res => {console.log(res);if (res.code == 0) {this.faceloading = false;this.$message.success({message: "人脸识别成功!",offset: 380,duration: 1000});} else {this.$message.error({message: "人脸识别失败!",offset: 380,duration: 1000});this.faceloading = false;}}).catch(err => {console.log(err);});}},created() {// 判断有无摄像头var deviceList = [];navigator.mediaDevices.enumerateDevices().then(devices => {devices.forEach(device => {deviceList.push(device.kind);});if (deviceList.indexOf("videoinput") == "-1") {console.info("没有摄像头");return false;} else {console.info("有摄像头");this.videoinput = true;}}).catch(function(err) {alert(err.name + ": " + err.message);});},}
</script>

Face.vue

<!-- 人脸识别 -->
<template><div class="face"><div class="container"><video id="video" preload autoplay loop muted></video><canvas id="canvas" width="581" height="436"></canvas><canvas id="canvas1" width="581" height="436"></canvas></div><div class="btns"><el-button type="primary" @click="start">打开摄像头</el-button><el-button type="primary" @click="screenshot">手动截图</el-button><el-button type="primary" @click="keepImg">保存图片</el-button><p class="tips">1、首先打开摄像头;2、将人像放在框中自动截取,也可点击手动截取。截取的图片将会出现在下方未保存图片栏;3、最后点击保存,下方可预览保存后的图片。</p></div><div class="imgs" v-show="imgView"><p>未保存图片</p><canvas id="shortCut" width="140" height="140"></canvas><p>已保存图片</p><div id="img"></div></div></div>
</template>
<script>
import "../../assets/js/tracking-min.js"; // 需要引入(下载链接在文末)
import "../../assets/js/face-min.js"; // // 需要引入(下载链接在文末)
export default {name: "testTracking",props: ["faceView"],data() {return {saveArray: {},imgView: false};},methods: {// 打开摄像头start() {var saveArray = {};var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");// eslint-disable-next-line no-undefvar tracker = new window.tracking.ObjectTracker("face");tracker.setInitialScale(4);tracker.setStepSize(2);tracker.setEdgesDensity(0.1);// eslint-disable-next-line no-undefthis.trackerTask = window.tracking.track("#video", tracker, {camera: true});tracker.on("track", function(event) {context.clearRect(0, 0, canvas.width, canvas.height);event.data.forEach(function(rect) {context.strokeStyle = "#fff";context.strokeRect(rect.x, rect.y, rect.width, rect.height);context.fillStyle = "#fff";saveArray.x = rect.x;saveArray.y = rect.y;saveArray.width = rect.width;saveArray.height = rect.height;});});var canvas1 = document.getElementById("canvas1");var context1 = canvas1.getContext("2d");context1.strokeStyle = "#69fff1";context1.moveTo(190, 118);context1.lineTo(390, 118);context1.lineTo(390, 318);context1.lineTo(190, 318);context1.lineTo(190, 118);context1.stroke();setInterval(() => {if (saveArray.x > 200 &&saveArray.x + saveArray.width < 400 &&saveArray.y > 120 &&saveArray.y + saveArray.height < 320 &&saveArray.width < 180 &&saveArray.height < 180) {console.log(saveArray);this.getPhoto();for (var key in saveArray) {delete saveArray[key];}}}, 2000);},// 获取人像照片getPhoto() {var video = document.getElementById("video");var can = document.getElementById("shortCut");var context2 = can.getContext("2d");context2.drawImage(video, 210, 130, 210, 210, 0, 0, 140, 140);this.imgView = true;},// 截屏screenshot() {this.getPhoto();},// 将canvas转化为图片convertCanvasToImage(canvas) {var image = new Image();image.src = canvas.toDataURL("image/png");return image;},//将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)dataURLtoFile(dataurl, filename) {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 File([u8arr], filename, { type: mime });},// 保存图片keepImg() {var can = document.getElementById("shortCut");var img = document.getElementById("img");var photoImg = document.createElement("img");photoImg.src = this.convertCanvasToImage(can).src;img.appendChild(photoImg);//获取到转化为base64的图片地址this.$emit("canvasToImage",this.dataURLtoFile(this.convertCanvasToImage(can).src, "person.jpg"));console.log(this.dataURLtoFile(this.convertCanvasToImage(can).src, "person.jpg"));},clearCanvas() {var c = document.getElementById("canvas");var c1 = document.getElementById("canvas1");var cxt = c.getContext("2d");var cxt1 = c1.getContext("2d");cxt.clearRect(0, 0, 581, 436);cxt1.clearRect(0, 0, 581, 436);},closeFace() {console.log("关闭人脸识别窗口");this.imgView = false;this.clearCanvas();// 停止侦测this.trackerTask.stop();console.log(this.trackerTask);// 关闭摄像头var video = document.getElementById("video");video.srcObject.getTracks()[0].stop();}},watch: {faceView(v) {if (v == false) {this.closeFace();}},imgView(v) {if (v == true) {this.$message.success({message: "截取成功!点击保存图片",offset: 380,duration: 1000});}}},destroyed() {}
};
</script>
<style scoped lang="scss">
.face {.container {background: #000;position: relative;width: 581px;height: 436px;#canvas1 {position: absolute;}video,#canvas,#canvas1 {position: absolute;width: 581px;height: 436px;}}.btns {padding: 10px;.tips {font-size: 14px;color: #666;margin: 10px 0;line-height: 24px;}}.imgs {padding: 10px;p {font-size: 16px;}}
}
</style>

结语

这样,一个简单又实用的人像识别就这样完成了。

face-min.js
链接: https://pan.baidu.com/s/1gB0Yd178a_8a_Bp3zKunHg
提取码: 9q7q
tracking-min.js
链接: https://pan.baidu.com/s/1LP7pZIbAgfYdAqp-NchQLw
提取码: qx75

谢谢阅读,如果觉得有感触,麻烦帮忙点个赞,关个注吧!

广告时间

豆哥打广告啦!有兴趣的同学可以看看哦~学无止境嘛!


Vue回炉重造之封装一个实用的人脸识别组件相关推荐

  1. Vue回炉重造之封装防刷新考试倒计时组件

    你好,我是Vam的金豆之路,可以叫我豆哥.2019年年度博客之星.技术领域博客专家.主要领域:前端开发.我的微信是 maomin9761,有什么疑问可以加我哦,自己创建了一个微信技术交流群,可以加我邀 ...

  2. Vue回炉重造之搭建考试答卷系统

    本篇章主要讲述系统搭建逻辑,有疑问的可以加微信联系我. 考试系统 资源 Vue.js Element UI 第三方数据接口 业务 答题过程中,防止用户中途退出或者其他不可抗力因素阻碍答题,在每次选择都 ...

  3. 机器人学回炉重造(1-2):各种典型机械臂的正运动学建模(标准D-H法)

    文章目录 写在前面 三连杆平面机械臂 平行四边形操作臂 闭链结构 例:平行四边形操作臂 球形臂 拟人臂 球腕 斯坦福机械臂 带球形手腕的拟人化机械臂 DLR机械臂 参考文献 写在前面 本文所有机械臂均 ...

  4. 《回炉重造 Java 基础》——集合(容器)

    整体框架 绿色代表接口/抽象类:蓝色代表类. 主要由两大接口组成,一个是「Collection」接口,另一个是「Map」接口. 前言 以前刚开始学习「集合」的时候,由于没有好好预习,也没有学好基础知识 ...

  5. 真人电影中的幻想生物迷墙:索尼克为什么被骂到回炉重造?

    <大侦探皮卡丘>上映在即,当网友们对着雷佳音配音的皮卡丘大呼好萌好萌时,我们仿佛又来到了大型真香现场--明明在几个月之前,当人们看到毛茸茸的大叔音皮卡丘时还每个细胞都充满了拒绝. 也有一种 ...

  6. 机器人学回炉重造(2-4):运动学奇异位型分析

    文章目录 什么是运动学奇异位型? 例子:平面二连杆机械手的奇异位型 奇异位型解耦 腕部奇异位型 手臂奇异位型 转载:6轴串联关节机器人的奇异点 参考文献 什么是运动学奇异位型? 在初步系统地了解了机器 ...

  7. 机器人学回炉重造(2-3):基本雅可比矩阵与其他雅可比矩阵

    文章目录 基本雅可比矩阵 定义 求法 其他雅可比矩阵 定义 求法 补充:几何雅可比与解析雅可比 基本雅可比矩阵 定义 用笛卡尔坐标描述线速度(linear velocity)和角速度(angular ...

  8. 回炉重造之数据结构【一】基本概念

    回炉重造之数据结构[一]绪论 文章目录 回炉重造之数据结构[一]绪论 数据结构的基本概念 基本概念和术语 数据结构的三要素 算法和算法评价 算法的基本概念 算法效率的度量 数据结构的基本概念 基本概念 ...

  9. javacript回炉重造之基础细节点

    ascript之回炉重造 var n5=2e5 2*10的五次方 0x开头十六进制 0o开头八进制 0b开头二进制 typeof 用于检测数据类型 值类型(基本类型):字符串(String).数字(N ...

最新文章

  1. jetspeed 安装及数据库配置
  2. 阿里P9架构师讲解从单机至亿级流量大型网站系统架构的演进过程
  3. 第五篇:JMeter 定时器
  4. 常用:javascript字符串函数 收藏
  5. boost::hana::difference用法的测试程序
  6. 以IP段作为监听地址
  7. mysql8 设置了默认值 CURRENT_TIMESTAMP 依然报null问题
  8. 国企营业收入逾17万亿 同比增长24.2%
  9. python - Numpy - matplotlib
  10. 从python的random函数说起
  11. 9,求整数的二进制中1的个数《剑指offer》
  12. FFMpeg学习记录:X264编码器
  13. 2021Java春招,java求职简历模板下载
  14. vue引入高德地图获取经纬度地址
  15. 如何修复uefi引导?这种方法才是最有效的解决方法
  16. 在win7和win10上通过INF文件安装64位WDM驱动
  17. 信息学竞赛NOIACM在线评测题库网站精选【翼虎小微整理】
  18. 将视频截取成图片的C++代码
  19. 计算机上怎么写英语音标,手的英语音标怎么写
  20. js实现文字跑马灯效果

热门文章

  1. MySQL 服务基础
  2. RationalDMIS 2020直线度评价
  3. 爆火上热搜!抖音「变身漫画」特效是如何实现的?
  4. SonarLint插件
  5. 萤火虫算法_萤火虫算法(二)
  6. 解析Java-throw抛出异常详细过程
  7. 微博API接口的调用
  8. 2019湖南对口升学计算机c语言试卷,2019年湖南省中等职业学校对口升学考试:计算机文化基础+计算机应用基础模拟试卷...
  9. 俯仰 (pitch) - 偏摆 (yaw) - 翻滚 (roll)
  10. InnoDB数据库隔离级别