当前位置: 首页 > 工具软件 > Tracking.js > 使用案例 >

基于tracking.js实现人脸识别

仰翰采
2023-12-01

目录

所依赖js

基本思路

页面

判断设备(pc端)是否有摄像头

浏览器兼容性配置

获取摄像头

唤醒摄像头

配置tracking

canvas绘制图片并转换


所依赖js

tracking-min.js

face-min.js 

下载地址: https://github.com/eduardolundgren/tracking.js/

基本思路

  1. 判断设备是否有摄像头
  2. 获取设备摄像头
  3. 唤醒摄像头
  4. tracking监听捕捉面部事件
  5. 用canvas作画布写入捕捉到的图片
  6. 将绘制的图片转为base64格式传给后台比对结果

页面

  <div class="wrapper">
    <video id="video" autoplay muted width="400" height="400"></video>
    <canvas id="canvas" width="400" height="400"></canvas>
    <canvas id="screenshotCanvas" width="400" height="400"></canvas>
  </div>

判断设备(pc端)是否有摄像头

    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("有摄像头");
          // flag = true; // 这是我自定义的一个状态,初始值为false
        }
        console.log(deviceList);
      })
      .catch(function (err) {
        alert(err.name + ": " + err.message);
      });

浏览器兼容性配置

      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {}
      }
      // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
      // 使用getUserMedia,因为它会覆盖现有的属性。
      // 这里,如果缺少getUserMedia属性,就添加它。
      if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function (constraints) {
          // 首先获取现存的getUserMedia(如果存在)
          var getUserMedia =
            navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia ||
            navigator.getUserMedia
          // 有些浏览器不支持,会返回错误信息
          // 保持接口一致
          if (!getUserMedia) {
            return Promise.reject(
              new Error('getUserMedia is not implemented in this browser')
            )
          }
          // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
          return new Promise(function (resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject)
          })
        }
      }

获取摄像头

      const videoArr = []
      await navigator.mediaDevices.enumerateDevices().then(function (devices) {
        console.log(devices, '浏览器设备信息')
        devices.map(function (device) {
          if (device.kind === 'videoinput') {
            // 获取所有摄像头
            videoArr.push({
              label: device.label,
              id: device.deviceId
            })
          }
        })
      })

唤醒摄像头

      const videoDoM = document.getElementById('video')
      const constraints = {
        audio: false,
        video: {
          deviceId: videoArr[0].id,
          width: videoDoM.offsetWidth,
          height: videoDoM.offsetHeight,
          transform: 'scaleX(-1)'
        }
      }
      await navigator.mediaDevices
        .getUserMedia(constraints)
        .then(function (stream) {
          // 旧的浏览器可能没有srcObject
          if ('srcObject' in videoDoM) {
            videoDoM.srcObject = stream
          } else {
            // 避免在新的浏览器中使用它,因为它正在被弃用。
            videoDoM.src = window.URL.createObjectURL(stream)
          }
          videoDoM.onloadedmetadata = function (e) {
            videoDoM.play()
          }
        })
        .catch((err) => {
          console.log(err)
        })

配置tracking

      // 固定写法
      let trackerTask
      const tracker = new window.tracking.ObjectTracker('face')
      const context = canvas.getContext('2d')
      tracker.setInitialScale(4)
      tracker.setStepSize(2)
      tracker.setEdgesDensity(0.1)
      trackerTask = window.tracking.track('#video', tracker)
      tracker.on('track', function (event) {
        context.clearRect(0, 0, canvas.width, canvas.height)
        if (event.data.length === 0) {
          // 没有检测到
        }
        else if (event.data.length > 1) {
          _this.$message.error({ content: '检测到多个人脸!', key: this.key, duration: 2})
          _this.$message.error('检测到多个人脸!', 2)
        }
        else {
          event.data.forEach(function (rect) {
            context.strokeStyle = '#00bc12'
            context.lineWidth = 3
            context.strokeRect(rect.x, rect.y, rect.width, rect.height)
            // 上传图片
            // uploadLock 避免重复上传定义的flag
            // _this.uploadLock && _this.screenshotAndUpload()
          })
        }
      })

canvas绘制图片并转换

      this.uploadLock = false

      // 绘制当前帧图片转换为 
      const canvas = document.getElementById('screenshotCanvas')
      const video = document.getElementById('video')
      const ctx = canvas.getContext('2d')
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
      this.base64Img = canvas.toDataURL('image/jpeg')
      // 使用 base64Img 请求接口即可
      console.log('base64Img:', this.base64Img)
      this.$set(this.infoData, 'faceImgBase64', this.base64Img)
      this.infoData.faceImgBase64 = this.base64Img
      console.log(this.infoData)
      // do something  可以上传图片了
      // this.$store.commit('SET_CHECKED', true) // 接口请求成功后再改变该值,测试需提前变更
      // 请求接口成功以后打开锁
      // this.uploadLock = true;

 类似资料: