face-api.jsで複数の顔を検出する


はじめに

先日face-api.jsを使ってみました。
前回の記事↓

今回はface-api.jsについてもう少し調べてみたいと思います。

face-api.jsとは?

繰り返しになりますが、face-api.jsはブラウザで顔検出(face detection:人の顔を自動的に見つける)と顔認識(face recognition:個人を識別する)ができるJavaScript APIです
機械学習用のライブラリTensorFlow.jsが利用されています
face-api.js

face-api.jsを使う準備

前回参照。
まだNode.jsは勉強中なので
今回も自分のプロジェクトにスクリプトを含める方法です。

今回試すもの

「トラニナル」はとにかく動くものを短時間で作る。という
マッチョな目標があったので読み飛ばしましたが
face-api.jsの内容をもう少し読んでいきます。

⇒読んだ結果、複数顔の検出を試しました!

Available Models

Face Detection Models

顔検出モデルについて書かれています。

SSD Mobilenet V1

画像内の各顔の位置を計算し、
各顔の確率とともにバウンディングボックスを返します。

face-api.js内で一番標準的な(?)顔検出のモデルだと思われます。
よく見かけるコードではこちらが使われていることが多いので、
私も「トラニナル」では思考停止状態でこちらを使用しました。

Tiny Face Detector

パフォーマンスの高いリアルタイムの顔検出器。
SSD Mobilenet V1顔検出器と比較して、高速・小型・リソース消費が少なく、
パフォーマンスはわずかに低下します。
モバイルデバイスやクライアントのリソースが限られているときはこちらを使用すべき。

「トラニナル」は使用者から「重い」という声を聞きました。
というか、自分でもテストして「重いなぁ」と思ったんですが
その時点で12/27だったので諦めました。
そんな問題を解決してくれそうな話がさっそく書いてあります!
これは使ってみたい。

MTCNN

MTCNN:マルチタスクカスケード畳み込みニューラルネットワーク。
(Google翻訳頼みですが合ってるのかな?)
一般に、他の顔検出器の方がパフォーマンスが優れている。

実験のためにリポジトリに入っている顔検出器のようです。
試すのはもちろんOK。

顔検出ついては上記3つについて書かれていました。

68 Point Face Landmark Detection Models

68点面顔ランドマーク検出モデル。
デフォルトのモデル(face_landmark_68_model)は350KB
小さなモデル(face_landmark_68_tiny_model)は80KB

顔ランドマーク検出の検出器にも小さいものがあることが分かりました!
これまた朗報ですね。

Face Recognition Model

顔認識のモデル。あらゆる人物の顔認識に使用できます。
ResNet-34のようなアーキテクチャが実装され、
人物の顔の特性を記述するために
任意の顔画像から顔記述子(face descriptor:128個の値を持つ特徴ベクトル)が計算されます。
2つの任意の顔の類似性は、それらの顔記述子を比較することによって
(たとえばユークリッド距離を計算することによって)決定できます。

ResNetとはニューラルネットワークのモデルのようですね。
難しいところは理解できなかったのですが
このモデルを使えば特定人物のお顔を認識出来るようです。

Face Expression Recognition Model

顔の表情認識モデル。
軽量、高速で、適度な精度を提供。
眼鏡をかけると、予測結果の精度が低下する可能性がある。

表情認識も気になりますよね~
笑顔の瞬間で撮影してくれたら面白いなぁ。

Detecting Faces

「トラニナル」で使ったのは
detectSingleFaceと言うメソッドでした。

ここも他の方法について調べる時間が無かっただけなので、
今回もう少し調べてみます。

画像内で最も信頼度の高い顔を検出する

const detection = await faceapi.detectSingleFace(input)

FaceDetection が返ってきます。

画像内のすべての顔を検出する

const detections = await faceapi.detectAllFaces(input)

Array < FaceDetection >が返ってきます。

detectAllFacesとdetectSingleFaceはデフォルトではSSD Mobilenet V1顔検出モデルを利用します。
対応するオプションオブジェクトを渡すことで、顔検出器を指定することができます。

const detections1 = await faceapi.detectAllFaces(input, new faceapi.SsdMobilenetv1Options())
const detections2 = await faceapi.detectAllFaces(input, new faceapi.TinyFaceDetectorOptions())
const detections3 = await faceapi.detectAllFaces(input, new faceapi.MtcnnOptions())

顔のランドマーク検出

「画像内で最も信頼度の高い顔を検出」し
「その顔の68点顔ランドマークを計算」

const detectionWithLandmarks = await faceapi.detectSingleFace(input).withFaceLandmarks()

「画像内のすべての顔を検出」し、
「検出された顔ごとに68点顔ランドマークを計算」

const detectionsWithLandmarks = await faceapi.detectAllFaces(input).withFaceLandmarks()

detectSingleFaceを使うかdetectAllFacesを使うか、と言うことですね。

デフォルトのモデルではなく小さなモデルを使うには

const useTinyModel = true
const detectionsWithLandmarks = await faceapi.detectAllFaces(input).withFaceLandmarks(useTinyModel)

と、withFaceLandmarks()の引数にtrueを与えればよさそうです。

複数顔検出をやってみる

ということで、色々試してみたくはなったのですが、
今回は「複数の顔を検出する」ことにします。


早速結果です。

やったことは
detectSingleFacedetectAllFaces
だけです!
あとは返ってきたFaceDetectionのデータが配列に入っているので
複数人分の描画を行うように書き換えました。

今回はココまで。

おわりに

用意されている顔モデルについて確認し、
複数人の顔検出・顔ランドマーク検出が出来ました。

小さいサイズのモデルも使ってみたいですし、
顔認識や表情検出も気になります。
次の機会に試してみたいと思います。