face-api.jsで顔認識

Pocket
LinkedIn にシェア
LINEで送る
Facebook にシェア

tensorflow.jsを使って顔認識がしたいと思っていたら、face-api.jsなるものを発見。簡単に使えたのでメモとデモ。

face-api.js: 0.10.0
tensorflow/tfjs-core: 0.11.9

試したのはRails上のReactだけれども、単なるnode.jsでも同じ。

1.プロジェクトへpackageの追加

yarn install face-api.js

2.modelsの取得
face-api.jsのweightsに置いてくれているものを利用
public/modelsにでも配置

3.任意のjsxでface-api.jsを読み込み

import * as faceapi from 'face-api.js/dist/face-api.js';

4.modelsの読み込み

faceapi.loadMtcnnModel('/models')

(補足)以下の方式がある(ざっくりメモ、詳しくはface-api.jsのgithub参照)
SSD Mobilenet v1・・・速度、認識率のバランス
Tiny Yolo v2・・・速度を犠牲に認識率寄り
MTCNN・・・認識率を犠牲に速度寄り

5.顔認識(訳あってasync, await使わず)

detection(video) {
  return new Promise((resolve, reject) => {
    const params = { maxNumScales: 10, scaleFactor: 0.709, scoreThresholds: [0.6, 0.7, 0.7], minFaceSize: 20 }
    faceapi.mtcnn(video, params)
    .then(result => resolve(result))
    .catch(error => reject(error))
  })
}

6.認識結果をcanvasに描画する場合に、canvasのサイズに結果をリサイズする関数

resize(descriptions, width, height) {
  return descriptions.map(m => m.faceDetection.forSize(width, height))
}

7.認識結果をcanvasに描画する関数(face-api.jsに実装してくれている)

draw(descriptions, canvas) {
  descriptions.map(f => faceapi.drawDetection(canvas, f, { withScore: true }))
}

8.video要素

<video id='video' className={styles.video} autoPlay playsInline muted></video>

9.それぞれの呼び出し

const video = document.getElementById('video')
const canvas = document.getElementById('canvas')
detection(video)
.then((result) => {
  // canvasサイズをvideo(streamではなくhtml要素の方)に合わせる
  canvas.width = video.clientWidth
  canvas.height = video.clientHeight
  // 映像をcanvasに描画
  canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)
  // 検出結果をリサイズ
  const resized = resize(result, canvas.width, canvas.height)
  // 検出結果をcanvasに描画
  draw(resized, canvas)
})

10.デモ

https://matchup.lizefield.com/demo/face

上記サイトにアクセスするとカメラデバイスの許可確認が表示されるので「許可」を行うとカメラデバイスからの映像が左側に表示される。
「Change Camera」でカメラデバイスの変更
「Start Face Detection」で顔認識開始、認識結果を右側に表示
「Stop Face Detection」で顔認識終了

これらをリモートワークのツールに組み込んだりすることで作業実績記録とするなど、色々な使い方がありそう。