UnityからFaceOSCを使ってVTuberっぽいのをやる(前編)

# はじめに

今回は顔の検出までです。
モデルを動かすのは次回書きます。
一応、成果物のGIFは下の方に載せます。
Unity初心者なので間違いなどがあったら教えていただけると幸いです。

# なぜFaceOSCなのか

Unityで顔検出をしたいと思ったのに、
Facetrackerが有料だし、
OpenCVも有料だったので、
OSSであるFaceOSCを使いました。

そこでUnityからFaceOSCを使う際に、
Unityパッケージを作って公開したので紹介します。
OSCの受信は[UnityOSC](https://github.com/jorgegarcia/UnityOSC)が有名なようですが、
[凹みTips](http://tips.hecomi.com/)さんの[uOSC](https://github.com/hecomi/uOSC)が使いやすかったので、
今回はこちらを使用しています。

# [UFaceOSC](https://github.com/enkatsu/UFaceOSC)

今回作ったUnityパッケージです。
uOSCでFaceOSCから受信したOSCメッセージをパースします。
Unityは経験が少ないので、バグなどあったらプルリクいただければ幸いです。
**まだ`/raw`の取得にバグがあるかもしれません。**

# 環境

- MacOS 10.13.2
- Unity 2017.3.1f1
- [FaceOSC](https://github.com/kylemcdonald/ofxFaceTracker/releases) v1.1
- [uOSC](https://github.com/hecomi/uOSC) v0.0.1
- [UFaceOSC](https://github.com/enkatsu/UFaceOSC) v0.0.1

# 使い方

1. uOSCとUFaceOSC、FaceOSCをそれぞれGitHubからダウンロード
2. 新規Unityプロジェクトを作成
3. `[Assets] => [Import Package] => [Custom Package...]`でuOSCとUFaceOSCをインポート
4. `[GameObject] => [Create Empty]`でゲームオブジェクトを作成
5. 作成したゲームオブジェクトを選択して`Inspector`の`Add Componet`から`[Scripts] => [uOSC] => [uOscServer]`でアタッチ
6. Portには`8338`を入力
7. `Add Componet`から`[New Script]`で新規のスクリプトを作成(今回は`main`という名前で作りました)
8. 作ったスクリプトに以下のサンプルプログラムを入力
9. FaceOSCを起動してrawのチェックボックスをオンにする
10. UnityのRunボタンを押す

```cs:main.cs
using System.Collections;
using UnityEngine;
using uOSC;
using UFaceOSC;

public class main : MonoBehaviour {
  private UFaceOSC.Parser faceOscParser;

  void Start()
  {
    // UFaceOSCのパーサクラスを初期化
    faceOscParser = new UFaceOSC.Parser();
    // uOscServerコンポーネントを取得して受信時のコールバック関数を設定
    var server = GetComponent <uOscServer>();
    server.onDataReceived.AddListener(OnDataReceived);
  }

  void OnDataReceived(Message message)
  {
    // パーサクラスにOSCアドレスとOSCメッセージを渡す
    faceOscParser.SetData(message.address, message.values);
    if(faceOscParser.found == 1) {
      // FaceOSCから受信した顔の頂点情報を取得
      float[] raw = faceOscParser.raw;
      // or Vector2[] rawPoints = faceOscParser.GetRawPoints();
      // FaceOSCから受信した口の高さを取得
      float mouthHeight = faceOscParser.gesture.mouth.height;
    }
  }
}
```

# UFaceOSC詳細

UFaceOSC.Parserクラスのメンバ変数はFaceOSCの下記のOSCメッセージアドレスに基づいています。
口の高さなら`/gesture/mouth/height`なので`faceOscParser.gesture.mouth.height`、
右目の開き具合なら`/gesture/eye/right`なので`faceOscParser.gesture.eye.right`となります。
また、`/pose/position`は`Vector2`、`/pose/orientation`は`Vector3`で返します。
`/raw`に限って`Vector2[]`を返す`GetRawPoints()`メソッドを用意しました。
`raw`のペアの数は66です。この定数は`UFaceOSC.Parser.POINTS_LENGTH`から読み込みも可能です。

- Pose
    - center position: /pose/position
    - scale: /pose/scale
    - orientation (which direction you're facing): /pose/orientation
- Gestures
    - mouth width: /gesture/mouth/width
    - mouth height: /gesture/mouth/height
    - left eyebrow height: /gesture/eyebrow/left
    - right eyebrow height: /gesture/eyebrow/right
    - left eye openness: /gesture/eye/left
    - right eye openness: /gesture/eye/right
    - jaw openness: /gesture/jaw
    - nostril flate: /gesture/nostrils
- Raw
    - raw points (66 xy-pairs): /raw

# 成果物

![mark.gif](https://qiita-image-store.s3.amazonaws.com/0/80816/4ca3b26d-dd5e-d699-ff80-a530578c4aea.gif)

<!--![vtuber.gif](https://qiita-image-store.s3.amazonaws.com/0/80816/61ab5f90-9cd8-30ef-639b-02b8c29cbd0a.gif)-->

今回の環境 + Live2Dを使ってVTuberっぽいのをやってみました。
使用したモデルはLive2Dが公開しているサンプルを使用しています。
長くなってしまったので、その辺は次回書きます。

# 感想

UnityでFaceOSCを使う例はあったが、オープンソースなものは見当たらなかった。
想像以上のUnity疲れ(便利なんだけどね)。
次回はマスコットキャラ的な奴を動かしたい。