見出し画像

インターンが1ヶ月でハンドトラッキング作ってみた

はじめまして、REALITY株式会社でインターンとして参加したフーヨンハオと申します。学校の研究や普段の趣味でXRやアバターを触っており、メタバースについても関心を持っています。メタバース社会の実現を目指すREALITY社のB2B事業部であるXR cloud事業部(現在REALITY XR cloud株式会社)に入り、メタバース界隈の企業が今どんな事業を行なっているかを体験し、実際の開発にも携わらせておりました。最後の一ヶ月はREALITYアプリを開発するPlatform & Avatar事業本部 Platform & Avatar事業部に移動し、アバターを使って「なりたい自分」になれる、ユーザーに直接感動を与えるようなB2Cコンテンツの開発を体験させていただきました。

この度、この一ヶ月をかけて所属のチームの皆さんで頑張ってきた企画の開発について紹介したいと思います。

エイプリルフール!

REALITYでは2021年のエイプリルフールに100人のコラボレーションが可能な企画がありました。今年のエイプリルフールにもユーザーさんにサプライズをお届けしたいということで、REALITYで既存のフェイストラッキングに加えてハンドトラッキング機能を期間限定公開することになりました!

おてて振ってるのかわいい

そういえばMediaPipeは何?

MediaPipeはGoogleが開発したオープンソースの機械学習ソリューションで、顔、指、全身ポーズを含むトラッキングをウェブカメラやスマホのカメラ一台だけで実現できるという便利なものです!
ホームページ:https://google.github.io/mediapipe/

MediaPipeにはいくつかのソリューションが入っています。特に今回の記事にかかわるものは以下になります:

  • Face Mesh:顔の特徴点の推定

  • Hand:指のポーズの推定する

  • Pose:体のポーズの推定する

  • Holistic:Face Mesh + Hand + Poseの感じで、顔の表情と全身のポーズの推定

そしてREALITYも先日、MediaPipeのFace Meshを利用したフェイストラッキング機能を実装しました!
つまり現在あなたのスマホでREALITYアプリを開いたら、あなたの顔をトラッキングしてアバターを動かしているのはMediaPipeかもしれない(機種による)ですよ!
これに関する記事はこちらになります:

今回のエイプリルフール企画の実装においては、このフェイストラッキングの実装が重要な基盤になっています。

いざ実装へ!

事前準備

  1. MediaPipe Unity Pluginを再ビルド

  2. HolisticとFace Meshの推論グラフを合体するようにカスタマイズ

顔・腕(体)・指のトラッキングをしたいので今回はHolisticメインにしました。

MediaPipeの推論グラフをカスタマイズ

現在REALITYのフェイストラッキングで使われているFace Mesh推論グラフ(そのソリューションを構成したモジュールの接続関係を定義するもの)によれば、以下が出力されます:

  • 顔の特徴点(ランドマーク):REALITYではアバターの顔の表情と向きの計算に使われている

  • 顔の範囲を検出する正方形:REALITYでは顔の奥行き、目の移動量などの補正のために使われている

しかし、Holisticは顔の特徴点も体の特徴点も同時に取れますが、Holisticの推論グラフの公式サンプルには顔の範囲を検出する正方形が出力されていなく、そのHolisticのサンプルをそのまま使うと、Holisticでのフェイストラッキングの出力が現在REALITY上で動いているフェイストラッキングの出力と異なるようになり、特に顔の奥行きや目の移動量の補正がなくなります。

REALITYのフェイストラッキングの品質を担保するため、HolisticとFace Meshの推論グラフを合体し、Holisticでも顔に関して同じ出力をするようにしました。

ランドマークからアバターポーズへの変換

ランドマークをアバターのそれぞれの関節にそのまま渡してポーズを設定してしまうと、自分の実際の体の姿勢と合わなかったり、不自然なポーズをしてしまったり、ブレがひどかったりしていましたため、頑張って変換を補正する必要があります。

開発初期段階で撮った録画

腕はそれぞれの関節のランドマークを用いて計算・補正した関節の位置情報をアバターの関節に渡すことで逆運動学的な制御を実現しました。

MediaPipeで取ったランドマークを、そのままアバターの関節の位置として設定してしまうと、アバターのサイズや腕の長さなどが合わないため、アバターの腕が引っ張られるように見えたり、思い通りに動かないです。

その問題を回避するために肩・肘・手首の位置は、ランドマークで計算した腕の長さとアバターの腕の長さの割合でランドマークを補正しています。例えば左肘は以下のように計算しています:

長さ補正割合 = (アバターの左肩から左肘の長さ) ÷ (左肘のランドマークから左肩のランドマークの距離)
左肘の位置 = アバターの左肩の位置 + (左肘のランドマーク - 左肩のランドマーク) × 長さ補正割合

以上の計算結果を踏まえてさらに、頭に嵌め込まないように頭のランドマークを用いて補正してから、アバターのポーズに反映させています。

なお、手首の回転は指と手首のランドマークで外積を取って決めるようにしています。

両手を頭の高さまで上げる時のトラッキング結果(左:補正前、右:補正後)

腕と違って、それぞれの関節のランドマークから関節の回転を計算・補正し、回転だけをアバターの指関節に渡すことで、順運動学的な制御を実現しました。

具体的に言えば、ランドマークを用いて関節と関節のベクトルを算出し、さらにそのベクトルを用いて各関節の回転を計算しています。(指の第一関節と第二関節の回転は一軸しかないため、他の方向への回転は0に設定しています)

例えば第二関節は以下のように回転を計算しています:

v1 = 第二関節 - 第三関節
v2 = 第一関節 - 第二関節
第二関節の回転 = Quaternion.Euler(0, v1とv2が挟んだ角度, 0)

さらに、実際にアバターに適用する前に、自然な動きを確保するために、かなり力技で補正をかけています(大変だったそうです)。

指の関節の曲がり具合に関して、Unityのエディター上で手動で回転値を調整しつつ良い感じの値を探し、最大値と最小値を定義しました。

また、ポーズによって(例えば「グー」のポーズでは)指の一部の関節がカメラから見えなくなった場合は、補正しないとその関節がどれくらい回転するか分からなくなるため、見えなくなる前から徐々に補正を入れ、見えなくなったら補正を強め、再び見えるようになったら補正を弱めることをしています。

こうした色々な補正によって指が変な動きをせず自然に動くようになりました!

「グー」ポーズのトラッキング結果(左:補正前、右:補正後)

ブレの制御

いかに補正をかけても、ランドマークのブレが避けられず、特に手の動きが速すぎたり、手がカメラの視野の境界線あたりに掛かったり、他人が自分の後ろを通ったりする際、MediaPipeの誤認識によりトラッキングが荒れてしまうことが多いです。

そこでローパスフィルターを導入しました。ランドマークで計算した位置と回転情報に対し、現在値から目標値に到達する割合を制御することで、速すぎる動きを防ぎ、アバターの動きを滑らかにしています。カルマンフィルターの導入も試みましたが、実装してみた結果計算負荷が高くなり、アプリのパフォーマンスを悪化させる恐れがあるため断念しました。

フィルターなし(ブレが出やすい)
フィルターあり(ブレが少ない)

頑張った結果

このように綺麗なトラッキングができました!

配信でも手を動かそう!

せっかくハンドトラッキングができたし、配信で視聴者と一緒に楽しみたい!コラボでも使いたい!という当たり前の要望に応じて、関節の位置と回転データを同期できるようにしました。

ただ同期するにあたって、配信のクォリティを担保するために通信量を抑える工夫が必要です。
今回は送信するデータをVector3から32bitのuintにし、timestampなどの冗長データを消すことで、半分以上の通信量が減りました(社内テスト:45KB/sec → 20KB/sec)。

ハンドトラッキングでわいわいコラボ!

その他

今まではカメラで撮った映像を入力としてトラッキングを行なっていますが、開発を手軽にするように、動画ファイルを入力として設定することも可能にしました。これで開発中にずっと手を上げながら変なポーズをして周りから変な視線にみられなくて済むようになりました。

感想&終わりに

MediaPipeの導入自体は難しくないと思いますが(Open-sourceでありドキュメントも充実していますし、ネット上にも有用な情報が転がっています)、アバターのポーズへの変換をより自然にするには、開発者がそれぞれの需要を踏まえながら、大変な工夫でカスタマイズしたり補正したりする必要があると考えます。

それでもMediaPipe開発楽しい!と強く思いました。顔と言葉だけでは伝わり切れない情報、体を自由に動かせることで盛り上がるテンションなど、スマホのカメラ一台だけで手軽に実現できるなんて、開発者側の私でさえこんなに楽しんでいたら、この機能を実際に使うユーザーの皆さんはどれほど楽しくなるのか想像がつきません。期間限定の機能ですが、身体性を導入したことによってREALITYという場でいかに新しい形のインタラクションが生まれるのかすごく期待しています。

今回の開発においては、自分はどちらかといえば開発をより楽にする機能の実装といった支援の役割を担っており、メインの機能実装は大体先輩方々が行われました。自分の貢献が少ないと思い、経験も能力もまだまだ浅いなと痛感しました。上長と先輩方々のご指導・ご支援のおかげでなんとか今年のエイプリルフール企画に役に立ちました。本当に大変ありがたく思っております。

悔しいところもありつつ、今回を機に、アバター制御周りの知識、フィルターの実装など、大量の勉強になったと思います。さらに、REALITYというB2Cのコンテンツの開発ため、ユーザーの期待・ニーズや、ユーザーがやってしまいそうな想定外の挙動の可能性や、自分が関わった開発が数百万人ほどまで影響が及ぶという責任などについて色々考える良い機会だと感じました。

エイプリルフール企画のリリースと同時に自分もREALITYでのインターンが終わります。改めまして、XR cloud事業部とPlatform & Avatar事業部の上長と先輩の方々に感謝申し上げます。

話が長くなりましたが、ぜひエイプリルフール期間中にREALITYのハンドトラッキング機能を使い倒してください!そしてプログラミングできる方はぜひMediaPipeを使った開発もやってみてください!