閱讀858 返回首頁    go 阿裏雲 go 技術社區[雲棲]


用瀏覽器做人臉檢測,竟然這麼簡單?(附代碼)

1.背景與場景


人臉檢測(Face Detection)算是老生常談的課題了,在諸多行業應用廣泛,例如金融、安防、電子商務、智能手機、娛樂圖片等行業。其中涉及的技術也在不斷的演變,下麵簡要介紹幾種思路:


  • 基於特征的人臉檢測


例如opencv中內置了基於Viola-Jones目標檢測框架的Harr分類器,隻需要載入一個配置文件(haarcascade_frontalface_alt.xml)就能直接調用detectObject去完成檢測過程,同時也支持其他特征的檢測(如鼻子、嘴巴等)。


  • 基於學習的人臉檢測


其實也是需要通過算子提取圖像中的局部特征,通過對其進行分類、統計、回歸等方式得到的具備更精確和快響應的分類器。


2.套路集錦


2.1 後端處理


前端通過網絡將資源傳輸到後端,後端統一處理需要檢測的圖像或視頻流,對後端的架構有一定的挑戰,同時網絡的延時往往不能給用戶帶來實時的交互效果。


2.2 客戶端處理


得益於OpenCV在跨語言和跨平台的優勢,客戶端也能以較低的開發成本提供人臉檢測的能力,並且可以通過JsBridge等方式向web容器提供服務,然而一旦脫離這個容器,孤立的頁麵將失去這種能力。直到有一天……


2.3 開放服務


不知道從啥時候開始,雲計算等概念拔地而起,計算的成本日益降低。各大研發團隊(如阿裏雲、Face++)都蠢蠢欲動又不緊不慢上架了人臉檢測服務,甚至還帶上了各種特!殊!服!務!人臉識別、活體識別、證件OCR及人臉對比等等等。

盡管不僅提供了客戶端的SDK以及前後端的API,但是,怎麼說也要講講我純前端的方案吧。


3.時代帶來了什麼


好吧,人臉識別在前端依然是在刀耕火種的遠古時代,然而,我們的基礎建設已經起步,希望後續的一些相關介紹能為各位看官帶來一定的啟發。


3.1 Shape Detection API


隨著客戶端硬件的計算能力逐漸提高,瀏覽器層麵得到的權限也越來越多,由於圖像處理需要耗費大量的計算資源,實際上瀏覽器上也能承擔圖像檢測的一些工作,因此就搞出了個Shape Detection API。


以下幾個簡單的例子介紹了基本的用法,在嚐試編輯並運行這些代碼之前,請確保在你的Chrome版本以及該新特性已經被激活,另外該API受同源策略所限製:


chrome://flags/#enable-experimental-web-platform-features


  • 條形碼:Barcode Detection (For Chrome 56+)

var barcodeDetector = new BarcodeDetector();

barcodeDetector.detect(image)

  .then(barcodes => {

    barcodes.forEach(barcode => console.log(barcodes.rawValue))

  })

  .catch(err => console.error(err));


  • 人臉:Face Detection (For Chrome 56+)


var faceDetector = new FaceDetector();

faceDetector.detect(image)

  .then(faces => faces.forEach(face => console.log(face)))

  .catch(err => console.error(err));


  • 文本:Text Detection (For Chrome 58+)


var faceDetector = new FaceDetector();

faceDetector.detect(image)

  .then(faces => faces.forEach(face => console.log(face)))

  .catch(err => console.error(err));


3.2 圖像中的人臉檢測


圖像的人臉檢測比較簡單,隻需要傳入一個圖片的元素,就能直接調起該API進行人臉識別了。然後接住canvas我們可以將檢測的結果展示出來。


640?wx_fmt=png&wxfrom=5&wx_lazy=1


核心代碼如下:

var image = document.querySelector('#image');

var canvas = document.querySelector('#canvas');

var ctx = canvas.getContext("2d");

var scale = 1;

image.onload = function () {

  ctx.drawImage(image,

    0, 0, image.width, image.height,

    0, 0, canvas.width, canvas.height);

  scale = canvas.width / image.width;

};

function detect() {

  if (window.FaceDetector == undefined) {

    console.error('Face Detection not supported');

    return;

  }

  var faceDetector = new FaceDetector();

  console.time('detect');

  return faceDetector.detect(image)

    .then(faces => {

      console.log(faces)

      // Draw the faces on the <canvas>.

      var ctx = canvas.getContext("2d");

      ctx.lineWidth = 2;

      ctx.strokeStyle = "red";

      for (var i = 0; i < faces.length; i++) {

        var item = faces[i].boundingBox;

        ctx.rect(Math.floor(item.x * scale),

          Math.floor(item.y * scale),

          Math.floor(item.width * scale),

          Math.floor(item.height * scale));

        ctx.stroke();

      }

      console.timeEnd('detect');

    })

    .catch((e) => {

      console.error("Boo, Face Detection failed: " + e);

    });

}



3.3 視頻中的人臉檢測


視頻中的人臉檢測跟圖像相差不大,通過getUserMedia 可以打開攝像頭獲取視頻/麥克風的信息,通過將視頻幀進行檢測和展示,即可實現視頻中的人臉檢測。


gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA


核心代碼如下:



navigator.mediaDevices.getUserMedia({

    video: true,

    // audio: true

  })

    .then(function (mediaStream) {

      video.src = window.URL.createObjectURL(mediaStream);

      video.onloadedmetadata = function (e) {

        // Do something with the video here.

      };

    })

    .catch(function (error) {

      console.log(error.name);

    });

  setInterval(function () {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.drawImage(video, 0, 0);

    image.src = canvas.toDataURL('image/png');

    image.onload = function() {

      detect();

    }

  }, 60);


3.4 時光倒流到沒有API的日子


實際上,在很久很久以前,也有不少解決方案存在。由於硬件條件以及沒有硬件加速等限製的情況,一直沒有被廣泛地投入生產。


  • tracking.js


tracking.js 是一款js封裝的圖像處理的庫,為瀏覽器帶來豐富的計算視覺相關的算法和技術,通過它可以實現顏色追蹤、人臉檢測等功能,具體特性如下:


640?wx_fmt=png&wxfrom=5&wx_lazy=1


  • jquery.facedetection


jquery.facedetection 是一款jquery / zepto 人臉檢測插件,基於跨終端能力超強的ccv中的圖像分類器和檢測器。


3.5 Node.js & OpenCv


node-opencv 模塊已經發布了有些年頭,盡管目前還不能完美兼容v3.x,提供的API也比較有限,但能完美兼容opencv v2.4.x。N-API的到來可能會帶來更多的驚喜。

設想一下在一個Electron或者Node-Webkit容器中,我們是否可以通過本地開啟websocket服務來實現實時的人臉檢測呢?實現的思路代碼如下:


  • 後端處理邏輯


import cv from 'opencv';

const detectConfigFile = './node_modules/opencv/data/haarcascade_frontalface_alt2.xml';

// camera properties

const camWidth = 320;

const camHeight = 240;

const camFps = 10;

const camInterval = 1000 / camFps;

// face detection properties

const rectColor = [0, 255, 0];

const rectThickness = 2;

// initialize camera

const camera = new cv.VideoCapture(0);

camera.setWidth(camWidth);

camera.setHeight(camHeight);

const frameHandler = (err, im) => {

  return new Promise((resolve, reject) => {

    if (err) {

      return reject(err);

    }

    im.detectObject(detectConfigFile, {}, (error, faces) => {

      if (error) {

        return reject(error);

      }

      let face;

      for (let i = 0; i < faces.length; i++) {

        face = faces[i];

        im.rectangle([face.x, face.y], [face.width, face.height], rectColor, rectThickness);

      }

      return resolve(im);

    });

  });

};

module.exports = function (socket) {

  const frameSocketHanlder = (err, im) => {

    return frameHandler(err, im)

      .then((img) => {

        socket.emit('frame', {

          buffer: img.toBuffer(),

        });

      });

  };

  const handler = () => {

    camera.read(frameSocketHanlder);

  };

  setInterval(handler, camInterval);

};


  • 前端調用接口



socket.on('frame', function (data) {

  var unit8Arr = new Uint8Array(data.buffer);

  var str = String.fromCharCode.apply(null, unit8Arr);

  var base64String = btoa(str);

  img.onload = function () {

    ctx.drawImage(this, 0, 0, canvas.width, canvas.height);

  }

  img.src = 'data:image/png;base64,' + base64String;

});


4.總結


4.1 未來的發展


這些前沿的技術將會在前端得到更為廣泛的應用和支持是毋庸置疑的,未來的圖像在前端也會隨著傳統圖像處理->學習+圖像處理的方式前進,這一切的功勞離不開基礎設施(硬件、瀏覽器、工具、庫等)的逐漸增強和完善,其中包括但不僅限於:


  • getUserMedia/Canvas => 圖像 / 視頻的操作

  • Shape Detection API => 圖像檢測

  • Web Workers => 並行計算能力

  • ConvNetJS => 深度學習框架


4.2 實際上並沒有那麼樂觀


4.2.1 準確率


對於正臉(多個)的識別率還是比較高的,但是在側臉已經有障礙物的情況下,檢測的效果並不理想。


4.2.2 處理速度


對於圖像中人臉檢測的例子2.2,耗費時間300ms+(實際上無法滿足大分辨率視頻實時處理),是調用Opencv的檢測速度100ms的三倍之多。


4.2.3 特性


還有很多需要完善的地方:如不支持眼鏡狀態、性別、年齡估計、表情識別、人種、笑容、模煳檢測等主流服務提供商提供的服務。




2017-09-18

尹摯

最後更新:2017-10-10 15:03:43

  上一篇:go  獨家 | 環境大數據的應用案例及前景
  下一篇:go  獨家 | 陸化普:大數據、AI解決交通管理難題的新思路