使用Vue封装一个实用的人脸识别组件

Jacquelyn38
• 阅读 1795

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

使用Vue封装一个实用的人脸识别组件

在这里插入图片描述

前言

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

资源

  • element UI

  • Vue.js

  • tracking-min.js

  • face-min.js

源码

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

有摄像头的话,我们就显示(需要人像识别组件):使用Vue封装一个实用的人脸识别组件)没有摄像头的话,我们就显示(这个直接上传人像即可):使用Vue封装一个实用的人脸识别组件判断有无摄像头,我们可以使用这个方法:

// 判断有无摄像头,推荐放在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-upload  
          v-if="!videoinput"  
          class="upload-demo"  
          action  
          multiple  
          :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-undef  
      var tracker = new window.tracking.ObjectTracker("face");  
      tracker.setInitialScale(4);  
      tracker.setStepSize(2);  
      tracker.setEdgesDensity(0.1);  
      // eslint-disable-next-line no-undef  
      this.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>  

使用Vue封装一个实用的人脸识别组件

在这里插入图片描述

结语

这样,一个简单又实用的人像识别就这样完成了。下面是库文件链接:

face-min.js「链接:」 https://pan.baidu.com/s/1gB0Yd178a\_8a\_Bp3zKunHg**「提取码:」** 9q7q

tracking-min.js「链接:」 https://pan.baidu.com/s/1LP7pZIbAgfYdAqp-NchQLw**「提取码:」** qx75


作者:「Vam的金豆之路」

主要领域:「前端开发」

我的微信:「maomin9761」

微信公众号:「前端历劫之路」

使用Vue封装一个实用的人脸识别组件


本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/6bQdDGh6iK4YChot2Xwkgw,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这