码迷,mamicode.com
首页 > 其他好文 > 详细

基于浏览器的人脸识别标记

时间:2017-09-25 21:57:41      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:点击   wim   htm   red   object   参数   dictd   foreach   col   

最近,Chrome在Chrome中集成了一套与图形识别相关的 API——Shape Detector API,只需要少量代码就能够实现人脸识别、二维码/条形码识别和文本识别。虽然这些 API 还处于实验阶段,只要条件允许,还是可以一下的。在 Windows 10 Chrome Canary 和 安卓 Chrome 等应用中,开启 chrome://flags/#enable-experimental-web-platform-features 功能,在控制台下输入

window.FaceDetector

window.BarcodeDetector

window.TextDetector

若得到“[native code]”,那么就可以使用这些 API 了。亲测 Windows7  Chrome 61 开启了 enable-experimental-web-platform-features 之后,虽然 window 包含以上三个 API,但调用 new FaceDetector.detector 时会报错:Face detection service unavailable.

 

这是一个面部标记的 demo代码。Ps:js 含有 ES6,没有转为 ES5,只能在支持 ES6 的浏览器上体验。

 

本来只是想简单的体验一下这个 API,没想到一不小心就写了这么多。。。

技术分享

 

在这个 demo 中,一共有三个类:

  (1)FaceTag:所有的逻辑操作(人脸识别、搜索面部、面部标记)都在该类中实现。

  (2)ShowImg:实现图片按原比例绘制、缩放图片、获取 base64、清除功能。

  (3)SignTool:实现绘制方框、绘制文字、清除功能。

实际上,ShowImg 完全可以用 <img> 代替的,我只是为了能够缩小图片,缩短人脸检测的时间。由于图片一旦确定后,在检测和标记阶段是不变的,为了方便操作,ShowImg 和 SignTool 各包含一个 canvas。为了减少代码的重复,将创建 canvas 和获取 ctx 的任务交给了 FaceTag 。

 

面部检测

FaceDetector 真的很简单。

创建实例的时候,可以给它传递 FaceDetectorOptions,这个对象只含两个有效参数:
  maxDetectedFaces:检测人脸的最大数目。
  fastMode:是否优先考虑速度。

而它只提供了 detect(img) 一个方法,传入待检测的图像,结果以 Promise 的形式返回,是包含一组 DetectedFace 元素的数组,若检测不到则返回一个空数组。DetectedFace 的相关信息:x,y,left,top,right,bottom 等都包含在 boundingBox 中。

至于检测结果的话,正脸的精确度挺高的,但是侧脸基本检测不到。
class FaceTag {

  constructor(opt={}){
    ...
    this.detector = new FaceDetector(orignOpt.detectorOpt);
    ...
  }
  ...
  faceDetector(aspect = 1) {     return new Promise((resolve, reject) => {       let img = this.img.getImage();       this.detector.detect(img)         .then(faces => {           if(faces.length === 0) {             reject(‘检测不到面部哦‘);           }else {             this.faces = faces;             resolve(this.faces);           }         })         .catch(err => {           reject(err);         })     })   }
  ...
}

根据检测到的结果信息在 signTool 的 canvas 中绘制出来。

class SignTool {
  ...
  /*
   * 标识面部
   * param {Array} faces 需要标识的部分
   */
  drawFaces(faces=[], aspect = 1) {
    faces.length > 0 && faces.forEach(face => {
      this.drawRect(face.boundingBox, aspect);
    })
  }

  /*
   * 绘制 rect
   * param {object} rect 需要绘制的 rect
   */
  drawRect(rect={}, aspect = 1) {
    this.ctx.save()
    this.ctx.beginPath();
    this.ctx.lineWidth = rect.lineWidth || 2;
    this.ctx.strokeStyle = rect.color || ‘red‘;
    this.ctx.rect(Math.floor(rect.x * aspect),
      Math.floor(rect.y * aspect),
      Math.floor(rect.width * aspect),
      Math.floor(rect.height * aspect)
    );
    this.ctx.stroke();
    this.ctx.restore();
  }
  ...
}

 

选择面部

本 demo 中为 signTool  的 canvas添加点击事件,通过鼠标坐标与检测到的所有面部信息进行比较,判断是否选中面部。选中之后,重新绘制一遍所有的面部,在将选中面部高亮。

class FaceTag {
  ...  
  /*
   * signTool 的 canvas 添加点击事件
   */
  addEvent() {
    if(!this.signTool.canvas) {
      return;
    }

    let canvas = this.signTool.canvas;
    let canvasBox = canvas.getBoundingClientRect();

    canvas.addEventListener(‘click‘, e => {
    // 计算鼠标在canvas中的位置
    let eX = e.clientX - canvasBox.left;
    let eY = e.clientY - canvasBox.top;

    this.findFace(this.img.getImage(), eX, eY)
      .then(face => {
        this.signTool.drawFaces(this.faces);
        this.heightLighRect(face);
        // 保存选中的面部                            
        this.beTagFace = face;
      })
    })
  }  
  ... }

最后,beTagFace 的信息,将文字标注在方框附近 ,对面部的标记就完成啦。

 

基于浏览器的人脸识别标记

标签:点击   wim   htm   red   object   参数   dictd   foreach   col   

原文地址:http://www.cnblogs.com/xxhuan/p/7593757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!