※当サイトの記事には、広告・プロモーションが含まれます。

Webカメラの情報から顔認識をして顔認証の前のバリデーションに必要な情報を取得する

gigazine.net

⇧ まぁ、膨大な数のプロジェクトに取り組んでいると思われるので、気になるところは出てきますよね。

顔認識(Facial Recognition)と顔認証(Facial Authentication)の違い

このあたり、

顔認識システム(かおにんしきシステム、英語Facial Recognition System)とは、カメラのデジタル画像から、人を自動的に識別するためのコンピュータシステムである。顔認証システムともいう。ライブ画像内のと思われる部分を抜き出し、顔面画像データベースと照合することで識別を行う。世界最高の顔認識システムでは1200万人分の静止画での「1:N認証」で、認証エラー率が0.22%に達する。

顔認識システム - Wikipedia

Wikipediaだと、一緒くたにされてしまってるっぽいのですが、

bioconnect.com

⇧ 上記サイト様だと、区別されている。

自分も、上記サイト様の説明の方が納得感があり、Wikipediaの説明のように「顔認識」と「顔認証」を同じと捉えるのには違和感を感じますと。

何となくですが、「顔認識」は、人間の「顔」を検出するだけであって、「顔」が特定の個人であるかどうかを検証して認証するのが「顔認証」だとイメージしているので。

「顔認証」については、特定の個人の「顔」の画像情報をデータベースとかに保存しておいて、Webカメラ、ないしは、「顔」画像などのユーザーからの情報と比較検証することが必要になってくる気がしますな。

マイナンバーカードの一意なIDとかと紐づけられたら、管理がしやすいのかもしれないですが、加齢による影響を受けにくいらしい「虹彩認証」で利用される眼の「虹彩」の方がより良いのかしら?

何やら、

innovationatwork.ieee.org

⇧ 漏洩した場合に、再登録の難しさがありそうですかね...

よく、入館証の作成とかで顔写真を撮ったりするのも、「顔」画像の情報をIDなどと紐づけてデータベースに登録したりしていそうな気がしますが、「生体情報」以外の情報と紐づけておくと多少はリスクヘッジになるんですかね?

紐づけていた情報毎流出した場合は、万策尽きた感がありそうで、実際に対面で対応するぐらいしか無さそうかしら...

Webカメラの情報から顔認識をして顔認証の前のバリデーションに必要な情報を取得する

前回の記事で、

ts0818.hatenablog.com

⇧ FIDO2(Fast Identity Online 2)で「バイオメトリクス(生体認証)」にも対応しているということは分かったのですが、「顔認証」を実現するための前段階として、Webカメラの情報から「顔認識」をしてみたいと思います。

「顔認識」の処理は、「顔認証」前のバリデーションみたいなものですかね。

なので、「顔認証」を実現する上で、必須というわけでは無いと思うのですが、全く関係の無い情報を弾くという意味では実装しておくのも良いのかなと。

「顔認識」については、

qiita.com

⇧ 上記サイト様にありますように、「face-api.js」というJavaScriptのライブラリがOSSとして公開されているようです。

なので、Webカメラからの情報をJavaScriptで取得して、「face-api.js」の機能で処理すれば「顔認識」は実現できる模様。

勿論、画像ファイルとかでも実現できますと。

画像情報が人間の「顔」と認識されたら、「顔認証」のために、サーバーサイド側の「顔認証」の処理を行うAPIのエンドポイントに対して、リクエストで画像情報を送る感じですかね。

今回は、「顔認識」なので、「顔認証」を行うかどうかを判定するための情報を取得するところまでですね。

ふと思ったのだけど、「Authenticator(認証器)」は、サーバーサイド側になるような気がしたんだけど、

engineering.mercari.com

秘密鍵がある場所が「Authenticator(認証器)」になるということらしい。

そもそも、初回のFIDO2 による認証のための情報の登録のための認証が必要になるような...

それとも、ユーザーから送られてくる画像を初回のみ無条件で信頼するということになるんかね?

だとすると、間違えて、全く関係ない画像で登録してしまった場合、画像の変更ができなくならないのか...

登録内容を変更する時はメールアドレスとかで認証するんかな?

脱線しましたが、Webカメラの情報から「顔認識」を試してみますか。

まずは、適当なディレクトリを用意して、ディレクトリに移動しておいたら、git cloneで、face-api.jsのプロジェクトをダウンロードしてきます。

Windowsの場合は、Git for Windowsとかインストールしておけば、gitコマンドを利用できます)

で、参考サイト様にありますように、git cloneしてきたフォルダに同梱されているモデルに関するファイルをコピーして適当なディレクトリに配置しておくのと、face-api-min.jsを読み込んで、Webサーバー上で動作させればOK。

で、Webサーバーについては、

snowsystem.net

⇧ 上記サイト様にありますように、Visual Studio Code拡張機能の「Live Server」を利用するのがお手軽そうなので、導入してみたものの、

残念ながら、警告が出てしまう...

ちなみに、face-api.jsフォルダにあるものは、git cloneしてきたものです。参考サイト様にありますように、weightsフォルダ配下のモデル(「顔認識」の訓練がされたものと思われる)に関するファイルを、新たに作成しておいた「models」というフォルダに配置しています。

Visual Studio Code拡張機能の「Live Server」を利用すると、追加された.vscode/settings.jsonに追加で設定するも、「Live Server」の警告は消えず...

{
    "liveServer.settings.port": 5501
    ,"files.autoSave": "afterDelay"
    ,"files.autoSaveDelay": 1
}    

ソースコードは以下のような感じ。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Face Detect Sample</title>
  <script defer src="./face-api.js/dist/face-api.min.js"></script>
</head>

<body onload="init()">
  <video id="video" autoplay onloadedmetadata="onPlay()"></video>
  <p id="message"></p>

  <script>
    // const MODEL_URL = "./face-api.js/weights";
    // Promise.all([
    //     faceapi.nets.ssdMobilenetv1.loadFromUri(MODEL_URL),
    //     faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL),
    //     faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL),
    // ]).then((val) => {
    //     // console here gives an array of undefined
    //     console.log(val)
    // }).catch((err) => {
    //     console.log(err)
    // })

    const videoElement = document.getElementById("video");
    const init = async () => {

      // Webカメラ初期化
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: {
          width: 400,
          height: 400
        }
      });

      console.log(stream);
      try {
        videoElement.srcObject = stream;
        //videoElement.play();

      } catch (err) {
        videoElement.src = window.URL.createObjectURL(stream);
      }
      // (1)モデル読み込み ※フォルダを指定
      await faceapi.nets.tinyFaceDetector.load("./models/");
    }

    const onPlay = () => {
    //const onPlay = async () => {
      const message = document.getElementById('message');
      const inputSize = 512; // 認識対象のサイズ
      const scoreThreshold = 0.5; // 数値が高いほど精度が高くなる(〜0.9)
      // (2)オプション設定
      const options = new faceapi.TinyFaceDetectorOptions({
        inputSize,
        scoreThreshold
      });
      const detectInterval = setInterval(async () => {
        // (3)顔認識処理
        //var result = await faceapi.detectSingleFace(
        var result = faceapi.detectSingleFace(
          videoElement
         ,options
        );

        //console.log(video);
        console.log(result);
        if (result) {
          message.textContent = "認識されてます";
          
        } else {
          message.textContent = "認識されていません";
        }
      }, 500);
    }

  </script>
</body>
</html>
   

⇧ 何か分からんけど、faceapi.detectSingleFace()メソッドをawait付けてしまうと、返り値がundefinedになってしまって機能しない...

Visual Studio Code拡張機能の「Live Server」がバグってるんかなぁ...

で、一応、awaitを外したら動くようにはなったのだけど、何か、face-api.jsはNode.jsとbrowserのどちらの機能もあるらしく、

qiita.com

⇧ ハマりどころが多そうな感じですかね...

ちなみに、

developer.mozilla.org

blog.netlab.jp

zenn.dev

⇧ 上記サイト様にありますように、サーバサイドに送信するための画像ファイルにするには、Webカメラの情報(<video>タグで取得してる情報)は、<canvas>に変換する必要があると。

今回、実施していない部分も含めて、全体の流れとしては、

Webカメラ(デバイス

JavaScriptの処理

●<video>

JavaScriptの処理

●<canvas>

JavaScriptの処理

●<img>

JavaScriptの処理

●サーバサイドへ送信

という感じになるということですかね。

バリデーションと言っても、

  • ファイル(画像)のサイズ
  • ファイル(画像)の拡張子
  • ファイル(画像)のMIME type(Content-Type)

ファイルのチェックぐらいになってくるのかなぁ...

バリデーションは、フロントエンド側とサーバサイド側で行うことになるとは思うけども。

「顔認証」とかは、機械学習や深層学習のモデルで実現するんだと思われるので、ブラックボックス化されてしまっているでしょうし...

まぁ、「顔認識」の方も「物体検出」とかしてると思われるからして、機械学習や深層学習のモデルで実現してるんでしょうけど...

毎度モヤモヤ感が半端ない...

今回はこのへんで。