VRChatで表情認識をしたい（願望）：1日目

##はじめに
この記事はVRChatを先日始めた初心者が「VRChatで表情認識をしてみたい！」と思い立ち、
1日目に実現のために調べた内容、参考にした記事について纏めたものです。
・なぜ誰もやっていない（あまりやられていない）のか？
・どこが技術的に難しいのか？
を自分なりにまとめておきたかったので、実現までの過程を記事にしていきたいと思っています。

また、この記事は2019/10/23時点で調べた結果のまとめであり、
引用元に関してはそれよりも古い情報を含む可能性があります。

##目標
以下のような環境を実現するのが目標となります。
・VRChat自体はデスクトップ画面に表示される（HMDを被ると表情認識できないため）
・両手の動きはコントローラのようなものでトラッキングできる。
・コントローラでVRChat内での前後移動・屈伸操作などができる。
・表情はWebカメラで認識する。認識したものがアバターにも反映される。
![EHg_wirUwAAEwB2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518315/5d0584b6-598b-f606-8034-358e5ff5b9e1.png)

##開始時点の学習状況
・VRChat2日だけプレイした
・3Dほとんどわからない
・Unityでは簡単なゲームぐらいなら作ったことがある
・[どうやらUnityで表情認識ができるらしい](https://qiita.com/akihiro01051/items/3146b9a377bf360f58f5)ということは記事で読んだことがある
・VR機器は友達の家で触らせてもらったことがある程度（自宅に無い）

##VRChatで自作アバターを使えるようにするには？
めちゃめちゃ大風呂敷を広げておきながら、自作アバターを上げたことすらなかったので、
まずは自作アバターを使えるようにしました。

ほとんど以下の記事を参照することで解決しました。

>“窓辺とおこ”に変身！VRChatでオリジナルアバターを使ってみた
>https://akiba-pc.watch.impress.co.jp/docs/sp/1145261.html

要点は以下3点です。
・VRChatにアバターをアップロードするためにはユーザーランクを上げる必要がある
・ユーザーランクを上げるために、VRChat内のフレンドを増やす必要がある
・VRChatへのアバターアップロードは、専用のSDKをインポートしたUnityプロジェクトから行う

上記の記事で紹介されている”窓辺とおこ”さんに関してはすでに3Dモデルの配布を停止されていますが、
無料配布3Dモデルを代用することで解決できます。
私の場合は、「拾い部屋」様が配布されている以下のモデルを拝借しました。

>VR用3Dモデル「2A-7/2ERO　(ニアナ/ニエロ装備)」
>https://booth.pm/ja/items/1197108

上記のモデルをUnityプロジェクトに導入する際は、"窓辺とおこ"さんの記事にあるやり方ではなく、
DL・解凍したフォルダ内にある、以下のパスに置かれた画像の手順での導入が必要でした。
`2A-7_LC_190521ver\アップロードのやり方(初めてアバターアップする人向け)\PC版アバターのアップロード方法`

![test_vr.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518315/c5cf4547-365b-04b9-7312-35545a24e84d.jpeg)

##さっそくUnityプロジェクトを編集してみる
###Unityプロジェクト上に配置したオブジェクトについて
Unityプロジェクト上に配置したオブジェクトについては、ほとんどそのままVRChat上に反映されるようです。
試しにただのCubeをプロジェクト内の適当な場所に配置したところ、そのまま反映されました。（可愛い）
![EHgF1nuUwAAQrZ0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518315/4f860184-c06c-e8e2-2fc6-a1098ca6bdbc.png)

##Unityプロジェクトの制限
結構素直に反映されるプロジェクト状況ですが、反映されないものがいくつかあるようでした。

###スクリプトが使えない
VRChatのアバターにはスクリプトを使えないようです。
ただし、シェーダーは反映されるので、シェーダー内にスクリプトを書いて、特殊な挙動を実装することはできるようです。
また、「アニメーションオーバーライド」で特定のキーを押したときにアニメーションを再生することはできるようです。

>アニメーションオーバーライドで表情をつけよう
>http://shiasakura.hatenablog.com/entry/2018/03/30/190811

###ほとんどのコンポーネントが使えない
スクリプトと同様に、ほとんどのコンポーネントが使えません。
以下の公式ドキュメントに記載されたコンポーネントのみが使えます
https://docs.vrchat.com/docs/whitelisted-avatar-components

例えば、AudioLisnerは上記のリストに含まれているので、音声を流すことはできます。
ただし、スクリプトは使えないので外部のマイクから音声は取得できず、プロジェクトに含まれる音声ファイルを流すだけ、となります。

Webカメラの画像取得ができるのであれば、シェーダー内で上手くやりくりすれば……なども考えていましたが、
どうやらそういった手法は難しい様子……。

また補足として、ワールド側には使えるが、アバター側には使えないものも多いとのこと。
例えば、ワールド側ではWeb_Panelというオブジェクトでブラウザを開くことができるため、
間接的にJavaScriptを実行できるらしいです。

##制限を踏まえて実現方法を考えてみる
上記踏まえて、顔認識の実装方法を検討しましたが、
・顔に仮想トラッカーを付け、直接トラッキングする
・アニメーションオーバーライドを魔改造し、表情認識に合わせてキー入力する
という2つの手段が取れそうでした。

###顔トラッキング
Unityプロジェクト上で実装することが難しそうなのは分かったので、
「顔にトラッカーが付いていると仮定して、顔トラッキングする」ことを考えてみました。

フルトラッキングで全身を動かせるなら、顔に数百個のトラッカーを付ければ
細かい表情をトラッキングできるはずです。

調べてみると、尻にトラッカーを5個付けている先駆者が居ました。（強い）

>Youtube：【検証】VIVEトラッカーを尻に5個付けるとどうなるの？
>https://www.youtube.com/watch?v=VGZysnUDkQg&feature=youtu.be

と、ここでわかりましたが、どうやらVRChatでは7個までしかトラッカーを使えない模様。
ので、いったん下記5つのパラメータをVRChatに持ち込むことを目指します。

・両目の開閉
・口の開閉
・右目の上下左右
・左目の上下左右
・笑顔（口角・目頭の上がり具合）

####顔トラッキングに向けた先行事例
ここで、Webカメラでフルトラッキングした事例を見つけました。

>参考：Webcamで全身フルトラッキング for SteamVR
>https://qiita.com/TenteEEEE/items/9bf5c65f33d0b818c31d

上記の記事では、「OpenVR Input Emulator」で仮想トラッカーを追加して、
その位置情報を別のアプリケーションから上書きすることで、
モーション認識によって取得した位置情報をVRChatに持ち込んでいるようです。

これが可能なら、顔認識した位置情報をVRChatに持ち込むこともできるかもしれません。

###アニメーションオーバーライドの魔改造
顔トラッキングとは別の手法として、アニメーションオーバーライドを使う手もありそうです。
追加のアニメーションは結構な数を登録できるようなので、
「特定の表情を認識したら、特定のキーを入力するマクロ」をたくさん作れば、疑似的に表情認識ができるかもしれません。

「アニメーションを同時に適用する」といったことができるなら、より細かい表情も作れるかも……。

##1日目終了とこれから
###まとめ
1日目はここまで調査しました。
顔トラッキングはいちばん自然な表情認識ができそうでしたが、
そもそもVR機器を持っていないことから検証が難しそうだったので、後に回します。

アニメーションオーバーライドの魔改造については比較的実現が簡単そうだったので、
まずはこの方法を試してみて、また課題を見つけてみようかと思います。

###わからないこと
デスクトップモードで両手のトラッキングをする方法についても調べてみたのですが、それらしいものが出てきませんでした。
そもそもサポートされていないのかもしれません。

逆に、VRモードでHMDではなくデスクトップにアプリを表示する方法はあるかもしれないですが、
そもそもVRモードで起動するためにVR機器が必要そうなので、これも後回しにします。