web移动端h5使用tracking.js实现人脸识别

背景

产品经理想要在H5项目上实现人脸识别功能,一开始用的是navigator.mediaDevices.getUserMedia方法,但效果实在一般,最终我找到了第三方库tracking.js。大致的流程为:获取摄像头权限->识别到人脸->截取图片并转码->调用接口发送后端。

原文地址

一、下载并引入第三方库文件

git地址

1. 引入

放在合适的地方
image.png
在vue文件中引入

import '@/common/tracking/build/data/face-min.js';

二、使用步骤

1. 获取视频流,创建检测

    init() {
      // 初始化设置
      this.video = document.getElementById('video');
      this.screenshotCanvas = document.getElementById('screenshotCanvas');

      let canvas = document.getElementById('canvas');
      let context = canvas.getContext('2d');

      // 固定写法
      let tracker = new window.tracking.ObjectTracker('face');
      tracker.setInitialScale(4);
      tracker.setStepSize(2);
      tracker.setEdgesDensity(0.1);
      this.tra = window.tracking.track('#video', tracker, {
        camera: true
      });

      tracker.on('track', function (event) {
        if (!this.tipFlag) {
          // 检测出人脸 绘画人脸位置
          context.clearRect(0, 0, canvas.width, canvas.height);
          if (event.data.length === 0) {
            if (!this.faceflag) {
              // 未检测到人脸
            }
          } else {
            event.data.forEach(function (rect) {
		// 标记人脸的位置
              context.strokeStyle = '#0764B7';
              context.strokeRect(rect.x, rect.y, rect.width, rect.height);
            });
            // 当检测到人脸时并且uploadLock锁为true时,自动触发
            this.uploadLock && this.screenshotAndUpload();
          }
        }
      });
    }

2. 利用canvas画出人脸,并渲染在页面上

<template>
  <div class="content">
    <div class="video-box">
      <video class="vd" id="video" width="480" height="360" preload autoplay loop muted playsinline></video>
      <canvas id="canvas" width="480" height="360"></canvas>
    </div>
    <canvas id="screenshotCanvas" width="480" height="360"></canvas>
    <van-overlay :show="show" @click="show = false" style="display: flex;justify-content: center;align-items: center;">
      <van-loading size="24px" vertical>{{ jumpTitle }}</van-loading>
    </van-overlay>
  </div>
</template>

3. 当检测到人脸时触发方法

   screenshotAndUpload() {
      // 上锁避免重复发送请求
      this.uploadLock = false;
      this.show = true
      // 绘制当前帧图片转换为base64格式
      let canvas = this.screenshotCanvas;
      let video = this.video;
      let ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      let base64Img = canvas.toDataURL('image/jpeg');

      // 请求接口
      faceId({
        picture: base64Img
      }).then(res => {
        // 请求接口成功以后打开锁
        if (res.status === 'success') {
          this.uploadLock = true
        } else {
          this.$toast.fail('认证失败')
          setTimeout(() => {
            this.uploadLock = true;
          }, 1000);
        }
      })
    }

4. 关闭摄像头及取消监听

// 关闭摄像头
 facevideo.srcObject.getTracks().forEach(track => track.stop());
// 取消监听
 tra.stop()

三、完整代码

<template>
  <div class="content">
    <div class="video-box">
      <video class="vd" id="video" width="480" height="360" preload autoplay loop muted playsinline></video>
      <canvas id="canvas" width="480" height="360"></canvas>
    </div>
    <canvas id="screenshotCanvas" width="480" height="360"></canvas>
    <van-overlay :show="show" @click="show = false" style="display: flex;justify-content: center;align-items: center;">
      <van-loading size="24px" vertical>{{ jumpTitle }}</van-loading>
    </van-overlay>
  </div>
</template>

<script>
import '@/common/tracking/build/data/face-min.js';

export default {
  data() {
    return {
      video: null,
      screenshotCanvas: null,
      uploadLock: true, // 上传锁
      tipFlag: false,
      faceflag: false,
      tra: null
    }
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      // 初始化设置
      this.video = document.getElementById('video');
      this.screenshotCanvas = document.getElementById('screenshotCanvas');

      let canvas = document.getElementById('canvas');
      let context = canvas.getContext('2d');

      // 固定写法
      let tracker = new window.tracking.ObjectTracker('face');
      tracker.setInitialScale(4);
      tracker.setStepSize(2);
      tracker.setEdgesDensity(0.1);
      this.tra = window.tracking.track('#video', tracker, {
        camera: true
      });

      tracker.on('track', function (event) {
        if (!this.tipFlag) {
          // 检测出人脸 绘画人脸位置
          context.clearRect(0, 0, canvas.width, canvas.height);
          if (event.data.length === 0) {
            if (!this.faceflag) {
              // this.tipTitle = '未检测到人脸'
            }
          } else {
            event.data.forEach(function (rect) {
              // context.strokeStyle = '#0764B7';
              // context.strokeRect(rect.x, rect.y, rect.width, rect.height);
            });
            // 上传图片
            this.uploadLock && this.screenshotAndUpload();
          }
        }
      });
    },
    // 上传图片
    screenshotAndUpload() {
      // 上锁避免重复发送请求
      this.uploadLock = false;
      this.show = true
      // 绘制当前帧图片转换为base64格式
      let canvas = this.screenshotCanvas;
      let video = this.video;
      let ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      let base64Img = canvas.toDataURL('image/jpeg');

      // 请求接口
      faceId({
        picture: base64Img
      }).then(res => {
        // 请求接口成功以后打开锁
        if (res.status === 'success') {
          this.uploadLock = true
        } else {
          this.$toast.fail('认证失败')
          setTimeout(() => {
            this.uploadLock = true;
          }, 1000);
        }
      })
    }
  }
}
</script>
  
<style lang="less" scoped>

/* 绘图canvas 不需显示隐藏即可 */
#screenshotCanvas {
  display: none;
}

.video-box {
  width: 9rem;
  height: 9rem;
  border-radius: 50%;
  overflow: hidden;
}

.vd {
  transform: rotateY(180deg);
  width: 100%;
  object-fit: fill
}
</style>
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值