face-api.jsによる顔検出・認識

face-api.jsによる顔検出・認識

顔認識システムは、デジタル画像またはライブ画像内の顔から、顔面画像データベースと照合して人物を識別するための技術として知られています。現在、研究者たちは顔認識システムが機能する様々な方法を開発しています。ID検証サービスを用いることで利用者を認証する際にも使われる最先端の顔認識方法は、顔画像から目立つ特徴を測定・特定することで機能しています。

そもそも、顔認識システムがコンピューター用アプリケーションでしたが、最近、スマホや、ロボット工学などのテクノロジーで広く使われるようになりました。コンピューター化された顔認識は、人間の身体特徴を測定することに関係するため、バイオメトリックスという生体認証として分類されました。生体認証としての顔認識システムは精度が虹彩認識や指紋認識より低いものの、ヒューマン・コンピューター・インタラクションや監視カメラや画像の自動索引生成といった分野で広く適用されています。

(Wikipediaより引用)

この顔認識ためのアルゴリズムをサポートしてくれるライブラリが沢山ありますが、この記事ではface-api.jsライブラリを使用して紹介させて頂きます。

FACE-API.JSとは?

Face-api.jsは、ブラウザおよびNodeJSで顔を検出し認識するための、Tensorflow.jsを活用したJavaScript APIです。

以下に、幾つかの主な機能を示します。

– 顔認識

– 顔ランドマーク検出

– 顔表情の認識

– 年齢性別の推定

この記事では、顔認識機能を紹介させて頂きます。

顔認識には顔検出と顔認識を含めます。

簡単にいうと、我々のやりたい目的としては、提供してくれた顔の画像を基に人物を識別できることです。そのため、認識したい人の名前をラベル付けした画像(参照データ)を、各人につき1枚(または複数枚)与えます。そして、入力画像と参照データを比較して、一番似ている参照画像を見つけます。画像が十分に類似していれば、その人物の名前を出力します。それに対して、判断できない場合は不特定として出力します。

以下の例を見てみましょう。

まず、管理するためのディレクトリ構造を作成します。

mkdir face
touch index.html
touch script.js
mkdir data // 入力画像データのドロップに使われる
mkdir images // テストに使われる画像
mkdir models // pre-trainedモデルが含まれる
face-api-js.min.js // githubからダウンロード

つぎ、face-api.jsが提供してくれるモデルをダウンロードします。

https://github.com/justadudewhohacks/face-api.js/tree/master/weightsからモデルのデータをダウンロードします。

以下のように、htmlファイルに、画像を入れて、バウンディングボックスという枠線で顔を囲むためのcanvasタグを追加します。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="./face-api.min.js"></script>
    <script src="./script.js"></script>
    <title>Face Recognition</title>
    <style>
        canvas {
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <img id="myImg" src="images/huu.jpg" />
    <canvas id="myCanvas">
</body>

</html>

プロジェクトへモデルをロードします。ここで、以下の3つの主なモデルを使います。

  • ssdMobilenetV1 Model:顔検出に使われるpre-trainedモデル
  • faceLandmark68Net Model:顔のポイントの表示に使われるpre-trainedモデル
  • FaceRecognitionNet Model:顔認識に使われるpre-trainedモデル

script.jsファイルにて、以下のの3つのモデルをロードしておきます。

(async () => {
  // Load model
  await faceapi.nets.ssdMobilenetv1.loadFromUri("/models");
  await faceapi.nets.faceRecognitionNet.loadFromUri("/models");
  await faceapi.nets.faceLandmark68Net.loadFromUri("/models");
})();

detectSingleFace()関数を使って画像の顔を検出します。

対象モデルをロードしたら、以下のように顔検出の処理を実装します。

(async () => {
  // Load model
  await faceapi.nets.ssdMobilenetv1.loadFromUri("/models");
  await faceapi.nets.faceRecognitionNet.loadFromUri("/models");
  await faceapi.nets.faceLandmark68Net.loadFromUri("/models");

  // Detect Face
  const input = document.getElementById("myImg");
  const result = await faceapi
    .detectSingleFace(input, new faceapi.SsdMobilenetv1Options())
    .withFaceLandmarks()
    .withFaceDescriptor();
  const displaySize = { width: input.width, height: input.height };
  // resize the overlay canvas to the input dimensions
  const canvas = document.getElementById("myCanvas");
  faceapi.matchDimensions(canvas, displaySize);
  const resizedDetections = faceapi.resizeResults(result, displaySize);
  console.log(resizedDetections);
})();

detectSingleFace()関数からは、顔検出の結果を返却し、顔のパーツの座標をも返却します。

FaceMatcher()関数とfindBestMatch()関数を使って顔を認識します。

顔検出を実装した後、顔を認識するdetectFace()関数を実装しましょう。

async function detectFace() {
  const label = "Huu";
  const numberImage = 5;
  const descriptions = [];
  for (let i = 1; i <= numberImage; i++) {
    const img = await faceapi.fetchImage(
      `/data/Huu/${i}.jpg`
    );
    const detection = await faceapi
      .detectSingleFace(img)
      .withFaceLandmarks()
      .withFaceDescriptor();
    descriptions.push(detection.descriptor);
  }
  return new faceapi.LabeledFaceDescriptors(label, descriptions);
}

それから、detectFace()関数を使って顔を認識して枠線で顔を囲むように実装します。

(async () => {
  // Load model
  await faceapi.nets.ssdMobilenetv1.loadFromUri("/models");
  await faceapi.nets.faceRecognitionNet.loadFromUri("/models");
  await faceapi.nets.faceLandmark68Net.loadFromUri("/models");

  // Detect Face
  const input = document.getElementById("myImg");
  const result = await faceapi
    .detectSingleFace(input, new faceapi.SsdMobilenetv1Options())
    .withFaceLandmarks()
    .withFaceDescriptor();
  const displaySize = { width: input.width, height: input.height };
  // resize the overlay canvas to the input dimensions
  const canvas = document.getElementById("myCanvas");
  faceapi.matchDimensions(canvas, displaySize);
  const resizedDetections = faceapi.resizeResults(result, displaySize);
  console.log(resizedDetections);

  // Recognize Face
  const labeledFaceDescriptors = await detectFace();
  const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.7);
  if (result) {
    const bestMatch = faceMatcher.findBestMatch(result.descriptor);
    const box = resizedDetections.detection.box;
    const drawBox = new faceapi.draw.DrawBox(box, { label: bestMatch.label });
    drawBox.draw(canvas);
  }
})();

これでJavaScriptで開発した簡単な認識システムの完成です!

Gitlabへアクセスしてソースコードを参照することができます。

結論

この記事では簡単にface-api.js及びその使い方について紹介させて頂いたものです。できれば、この記事に言及していない、年齢や性別、気分(表情)といった顔認識機能の調査も可能です。なお、顔認識システムは、pre-trainedモデルからのデータを転送する等の処理なしでpre-trainedモデルをそのまま流用するので、精度が相対的になります。

参照元

https://en.wikipedia.org/wiki/Facial_recognition_system

https://github.com/justadudewhohacks/face-api.js#getting-started

https://itnext.io/face-api-js-javascript-api-for-face-recognition-in-the-browser-with-tensorflow-js-bcc2a6c4cf07

画像出典元:https://www.pexels.com/license/