6

前端捕获人脸识别实践

 2 years ago
source link: https://iiong.com/front-end-capture-face-recognition-practice/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前端捕获人脸识别实践

Jaxson Wang • 2021年07月02日 • 奇淫技巧 • 阅读量 5 次 • 评论量 0 个

公司有个项目涉及人脸识别,需要前端能力支持,需要用户进入摄像头后识别人脸进行截图,然后上传后端进行数据交换。不过目前主流摄像头支持调用,开源社区有个 trackingjs 类库问题解决计算机视觉解决方案。

trackingjs 很多工作量帮你做好,只需要引入他的库就可以用了:

<div class="app-container">
      <video ref="videoRef" class="video-wrapper" preload autoplay loop muted />
      <canvas ref="captureFaceRef" width="600" height="560" class="capture-face-wrapper" />
    </div>
    <div class="result-wrapper">
      <h3>捕获到人脸数据:</h3>
      <canvas ref="shortCutRef" class="short-cut-wrapper" />
    </div>
markup

想实现功能至少需要 videoRefshortCutRef 节点,videoRef 主要是调用摄像头获取流媒体进行播放,而 shortCutRef 节点就是人脸截图,你可以拿到里面的图片进行提交,至于图片转 base64 数据流根据需求定吧。上面多一个 captureFaceRef 主要是捕获人脸的状态圈,告知用户捕获状态,而这个状态 trackingjs 事件回调里包含其中。

本项目是 vue3 项目,所以先初始化相关的业务:

const videoRef = ref(null)
const captureFaceRef = ref(null)
const shortCutRef = ref(null)

// 捕捉人脸坐标对象
const saveArray = {}
let captureFaceCanvas = null
let captureFaceContext = null
let shortCutRefCanvas = null
let shortCutRefContext = null
// tracking 实例化对象
let tracker = null
javascript

然后在 mounted 生命周期拿到 dom 节点信息和初始化 trackingjs

onMounted(() => {
  captureFaceCanvas = captureFaceRef.value
  shortCutRefCanvas = shortCutRef.value
  captureFaceContext = captureFaceCanvas.getContext('2d')
  shortCutRefContext = shortCutRefCanvas.getContext('2d')

  initTracker()
  captureFacePhoto(shortCutRefCanvas)
 })
javascript

initTracker 方法要注意下声明 face 的模块,因为 trackingjs 机器学习模型很多,我这边只用到人脸,所以声明该模型:

const initTracker = () => {
  // 实例化 face 模块
  tracker = new window.tracking.ObjectTracker('face')
  // 初始化抓取人脸边框配置
  tracker.setInitialScale(4)
  tracker.setStepSize(2)
  tracker.setEdgesDensity(0.1)
	// 摄像头开启
  window.tracking.track(videoRef.value, tracker, {
      camera: true
  })
  // 追踪事件回调
  tracker.on('track', event => {
      captureFaceContext.clearRect(0, 0, captureFaceCanvas.width, captureFaceCanvas.height)
      event.data.forEach(function (rect) {
          captureFaceContext.strokeStyle = 'red'
          captureFaceContext.strokeRect(rect.x, rect.y, rect.width, rect.height)
          captureFaceContext.fillStyle = 'red'
          saveArray.x = rect.x
          saveArray.y = rect.y
          saveArray.width = rect.width
          saveArray.height = rect.height
      })
  })
}
javascript

上面就是根据配置进行个性化配置,具体可以查阅官方文档。

然后制作截图功能:

const captureFacePhoto = canvas => {
  // 将video对象内指定的区域捕捉绘制到画布上指定的区域,实现拍照
  shortCutRefContext.drawImage(videoRef.value, 140, 70, 340, 340, 0, 0, 140, 140)
  const getImage = canvas.toDataURL('image/png')
  console.log(getImage)
}
javascript

至此为止基本功能已经实现了,不过在人脸识别过程中,却发现人脸识别经常失误,比如识别到侧边脸以及截图文件不完整。

const bestCaptureTimer = () => {
  if (saveArray.x > 130 &&
    saveArray.x + saveArray.width < 460 &&
    saveArray.y > 58 &&
    saveArray.y + saveArray.height < 388 &&
    saveArray.width < 330 &&
    saveArray.height < 330) {
    captureFacePhoto(shortCutRefCanvas)
    for (const key in saveArray) {
      delete saveArray[key]
    }
  }
}
javascript

这个定时器让用户在画布中央进行截图,提高人脸识别率。

对于需要检验摄像头设备完全可以用浏览器的 api 实现:

if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {}
}
// 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
// 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
  navigator.mediaDevices.getUserMedia = constraints => {

    // 首先,如果有getUserMedia的话,就获得它
    const getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia

    // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
    }

    // 否则,为老的navigator.getUserMedia方法包裹一个Promise
    return new Promise((resolve, reject) => {
      getUserMedia.call(navigator, constraints, resolve, reject)
    })
  }
}

navigator.mediaDevices.getUserMedia({ video: true }).then(() => {
  // 人脸识别业务初始化
  const tracker = new window.tracking.ObjectTracker('face')
  // 一些业务...
}).catch(err => {
  console.warn(err.name + ": " + err.message)
  ElMessage.error({
    message: '没有检验到摄像头,请插入摄像头设备!',
    showClose: true,
    duration: 0
  })
})
javascript

demo 如下,记得授权摄像头访问


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK