jeelizFaceFilterを試してみた

顔認識ライブラリjeelizFaceFilterを試してみました。
[jeeliz/jeelizFaceFilter](https://github.com/jeeliz/jeelizFaceFilter)

# 特徴
jeelizFaceFilterはJavaScriptの顔認識ライブラリで、three.js、a-frame、babylon.jsなどのフレームワークと一緒に使えます。
主に下記の機能に対応してます。

- 顔検出
- フェイストラッキング
- 口の開閉認識
- 複数の顔検出
- 3Dモデル対応

READMEの `live demo` からいろいろなデモを体験できます。



![スクリーンショット 2020-08-10 14.58.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37716/c08440fa-16d2-fb87-2a95-4f168a5c76c6.png)
▲GLTF fullscreen demo with HD video
https://jeeliz.com/demos/faceFilter/demos/threejs/gltf_fullScreen/




# 基本的な使い方

headでjeelizFaceFilterのscript読み込みます。

```js
<script src="dist/jeelizFaceFilter.js"></script>
```

bodyにcanvasを設置します。id属性は後ほどinitializeで設定する値と合わせます。

```html

 <canvas width="600" height="600" id='jeeFaceFilterCanvas'></canvas>
</body>
```


ページのローディングが終わったら、下記の関数を実行します。

```js
JEEFACEFILTERAPI.init({
  canvasId: 'jeeFaceFilterCanvas',
  NNCpath: '../../../dist/', //ニューラルネットワーク NNC.jsonへのパス
  callbackReady: function(errCode, spec){
    if (errCode){
      console.log('AN ERROR HAPPENS. ERROR CODE =', errCode);
      return;
    }
  },
  //レンダーされる度に呼ばれるcallback
  callbackTrack: function(detectState){
  }
});
```

## 初期設定のオプション

- `followZRot`:
    - Z軸の回転対応
    - defult: false;
- `maxFacesDetected`:
    - 顔検出の数
    - maxは8
    - default: 1
- `animateDelay`:
    - アニメーションのディレイ
    - canvasを複数設置して顔の動きを検出して別canvasに反映するときなどの遅延を制御する時に使う？
- `onWebcamAsk`:
    - webcameraの利用を確認する前に実行したい関数を定義
- `onWebcamGet`:
    - webcameraの利用を許可された後に実行したい関数を定義
- `videoSettings`:
    - webcameraの設定を上書きする
- `scanSettings` :
    - scanSettingsを上書き
- `stabilizationSettings`
    - stabilization settingsを上書き

## callback

### callbackRedy

イニシャライズ後に呼び出されるcallback関数。第二引数に`spec`を持ちます。

```js
callbackReady: function(errCode, spec){
    console.log('spec=',spec);
  }
```

```js
spec = {
GL: WebGLRenderingContext,
canvasElement: canvas#jeeFaceFilterCanvas,
videoTexture: WebGLTexture,
maxFacesDetected: 1,
videoElement: video
}
```

### callbackTrack

各レンダーのコールバック関数。引数に検出の状態を持ちます。

```jsx
callbackTrack: function(detectState){
    console.log('detectState',detectState);
}
```

```jsx

detectState = {
  detected: 0.002228396574170996,
  expressions: {0: 0.6213956170703576},
  rx: -0.09635881606550778,
  ry: 0.2564969688259624,
  rz: 0,
  s: 0.4952402921953095,
  x: -0.08502883506343717,
  y: -0.28679738562091495,
}
```

### 補足
最終的なレンダリングはcanvasの解像度を使用して計算されます。
nitializeの後にcanvasをリサイズする場合は、

```js
JEEFACEFILTERAPI.resize()
```

をcallします。
また、カメラの解像度とキャンバスの解像度を最適化させるためにヘルパー`JeelizResizer.js`の利用をすすめています。

# 各フレームワーク毎の設定

初期設定に加え、各フレームワーク毎に設定が必要となりますが、これはdemosのJSファイルをベースに適時調整が良いと思います。

例えばthree.jsのBoilerplateはこちらになります。
https://github.com/jeeliz/jeelizFaceFilter/tree/master/demos/threejs/cube

ソースを見てもらうと分かると思うのですが、各フレームワーク毎に追加で読み込むJSがあったり、各ライブラリでオブジェクトを表示させるためのコードや、jeelizFaceFilterと各オブジェクトを連動させるためのコードが含まれていることもあります。
なので、一概に説明するのが難しく、自分が作りたいイメージに近いデモのサンプルコードをベースに調整していくのが間違いがないと思います。


---



# その他メソッド

- `JEEFACEFILTERAPI.resize()`
    - 要素のサイズを変更した後に呼び出して調整する
- `JEEFACEFILTERAPI.toggle_pause(<boolean> isPause, <boolean> isShutOffVideo)`
    - 停止/再生を切り替える。返り値はPromisオブジェクト。
- `JEEFACEFILTERAPI.toggle_slow(<boolean> isSlow)`
    - 低速モードにする
- `JEEFACEFILTERAPI.set_animateDelay(<integer> delay)`
    - animationDelayを変更する
- `JEEFACEFILTERAPI.set_inputTexture`
    - WebGLテクスチャインスタンスによってビデオ入力を変更する
- `JEEFACEFILTERAPI.reset_inputTexture()`
    - 入力テクスチャとしてユーザーのビデオに戻り
- `JEEFACEFILTERAPI.get_videoDevices(<function> callback)`
    - ビデオデバイスの情報を取得
    - ※`init` メソッドの前に呼び出す
    - コールバック関数は `mediaDevices` と `errorLabel` 2つの引数を持つ。
- `JEEFACEFILTERAPI.set_scanSettings(<object> scanSettings)`
    - scanSettingsの設定を上書き
- `JEEFACEFILTERAPI.set_stabilizationSettings(<object> stabilizationSettings)`
    - stabilizationSettingsを上書き
- `JEEFACEFILTERAPI.update_videoElement(<video> vid, <function|False> callback)`
    - 使用するビデオを変更する
- `JEEFACEFILTERAPI.update_videoSettings(<object> videoSettings)`
    - ビデオの設定を変更する
- `JEEFACEFILTERAPI.set_videoOrientation(<integer> angle, <boolean> flipX)`
    - ビデオの角度等を変更
- `JEEFACEFILTERAPI.destroy()`
    - ライブラリを削除しメモリを開放
    - 返り値はPromisオブジェクト