はじめに
先日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を与えればよさそうです。
複数顔検出をやってみる
ということで、色々試してみたくはなったのですが、
今回は「複数の顔を検出する」ことにします。
やったことは
detectSingleFace → detectAllFaces
だけです!
あとは返ってきたFaceDetectionのデータが配列に入っているので
複数人分の描画を行うように書き換えました。
今回はココまで。
おわりに
用意されている顔モデルについて確認し、
複数人の顔検出・顔ランドマーク検出が出来ました。
小さいサイズのモデルも使ってみたいですし、
顔認識や表情検出も気になります。
次の機会に試してみたいと思います。