３D姿勢推定＋Unityでリアルタイム３Dトラッキングするシステムについて現状まとめ

#何をした？
3D人物姿勢推定機械学習モデルを用いてWEBカメラの画像から人物の各関節位置（姿勢）をリアルタイムで推定し、得られた3D位置を使用してUnity上の3Dモデルを動かすシステムを作成

#成果
**1.複数人のリアルタイムトラッキング**
GoogleColaboratory上の3D姿勢推定モデル
入力：WEBカメラの画像をYoutubeLive経由で送信
出力：カメラ位置を原点とした各関節の3D位置（10~15FPS程度）

↓　UDP通信

ローカルPC上のUnity
入力：カメラ位置を原点とした各関節の3D位置（関節間の角度をモデルに適用）
出力：3Dモデルのモーション（リアルタイム表示・BVH形式出力）

https://twitter.com/i/status/1353343868817686530

**2.指のトラッキング**
MediaPipeのHand Trackingモデルを追加して指のトラッキングを追加

https://twitter.com/i/status/1355845071770320898

#使用した機械学習モデルについて（複数のモデルのパイプライン）
選定基準：モデル・データセット共に商用利用可能であること（将来のサービス化などを目指して）

###人物検出（YOLO　V4)
https://github.com/Tianxiaomo/pytorch-YOLOv4.git

人物を矩形範囲で検出するモデル。検出した範囲でクリッピングした画像が人物追跡・2D姿勢推定の入力となる。

パラメータ数が少ないTinyモデルを採用。本来はマルチクラスの検出に対応しているが、人物検出のために1クラスのみで学習することでそれなりの精度が出ることを確認した。

教師データセット：[COCO Keypoint Detection Task](https://cocodataset.org/)
 

###人物追跡（deepsort)
https://github.com/ZQPei/deep_sort_pytorch.git

検出された人物にIDを付与し、移動する人物を画像特徴量をもとに追跡するモデル。同時に複数人の姿勢推定を可能とするために採用。

実際に使用してみたところ、歩きなどの動作では追跡が途切れないが、ダンスなどの特殊な動きではちょくちょく追跡が途切れて新しい人物として検出されてしまうことがままあった。（特徴量の距離の閾値や検出が途切れてからそのIDの追跡を打ち切るまでの時間などのパラメータなどで調整することができるが、ひとつの最適な値というよりは、状況に応じた設定が必要という感じ）

データセットが通行人のデータであるため動きの多様性が少ないことにより生じたと思われる。

単純に3D姿勢推定結果の座標を使って追跡する方法もあるが、画像特徴量を使うので、一度画面から消えた人物が再度現れた場合でも別のIDが割り振られることが無いという利点あり。

教師データセット：[MARS Dataset]( http://zheng-lab.cecs.anu.edu.au/Project/project_mars.html)

###2D姿勢推定（Deep High-Resolution Representation Learning for Human Pose Estimation）
https://github.com/leoxiaobin/deep-high-resolution-net.pytorch

画像から直接3D姿勢を直接推定するモデルも多く公開されているが、データセット作成にモーションチャプチャー機材が必要になる関係上、外観の多様性が少なくなり、さまざまな環境への汎化性能が低くなることが考えられるので2D姿勢から3D姿勢を推定する方式を採用。

モデルパイプライン内で最も推定時間の長いモデルのため、精度と速度のトレードオフを考えてモデルの層数を決める必要がある。

教師データセット：COCO Keypoint Detection Task

###2D姿勢⇒3D姿勢推定（Evoskeleton）
https://github.com/Nicholasli1995/EvoSkeleton

人
物の骨格構造の制約を加えた上で複数のポーズを合成して教師データを増やす機能（弱教師あり学習の一種）があるため、教師データに無いようなポーズの推定ができることを期待して採用。
特殊な姿勢でもある程度の推定ができることを確認。

教師データセット：[CMU Graphics Lab Motion Capture Databaseのモーションチャプチャーデータ](http://mocap.cs.cmu.edu/)


#3D姿勢推定結果の後処理について
3D姿勢推定結果の出力は生値だと止まっている状態でも細かい動きが発生してしまっている（時系列データとしては扱わず一つ一つの画像で推定していること・2D→3D推定による誤差の蓄積などが原因と思われる）

今回は通常のモーションチャプチャーの分野でもよく使われている、スムージング処理（複数のフレームの結果を平均した値を使用すること）を採用した。3フレーム分の平均を使うことで、スムーズな動きにすることができたが、もともとFPSが少ない上にスムージングを行うので、素早い動きには追随できないという問題も出来た。


#ローカルPCと機械学習モデル実行環境間の通信について

自前の計算機環境のスペック不足のため、モデルの実行環境は別途リモートで行うことにした。
無料で使える計算機環境のGoogle Colaboratory(以下、Colab)を使用しているため、誰でも使えるように公開することも視野に入れている。

###ローカルのWEBカメラの画像を機械学習モデル実行環境に送る
Colabへ直接通信を行うのはNAT越えが困難なため、不採用とし、YouTubeLiveのカメラ配信を限定公開で開始し、Colab側で開く方法をとった。

###ColabからローカルPCのUnityへ推定結果を送る
ルータのUDPポート開放を行い、Unity上で起動したUDPサーバーにUDP通信で座標を送る方式を採用

#Unity側の処理
###1. 検出された人物のIDと3Dモデルを紐づけ

あらかじめ設定していた人数までは、ID順に順番で3Dモデルに紐づける。また、人物の追跡が途切れ、あらたなIDが付与された人物が現れた際は、途切れた時の座標位置を参考に紐づけなおすようにしている。

場合によっては紐づけが入れ替わったりする場合があるので、手動で紐づけを切り替える機能を別途作成する予定。

###2. 3Dモデルに姿勢を適用
関節間のベクトルを計算し、ボーンがその方向を向くように回転を加える処理を各関節ごとに行うことで姿勢を適用している。

関節位置座標をトラッカーとして使い、IKの機能を使った姿勢の適用方法も検討してみたい。

#指のトラッキング
指のトラッキングを行うモデルの構築を行う予定だったが、商用利用可能なデータセットを用意するのが難しかったため、学習済みモデルと使用するためのライブラリが提供されていて、簡単に利用ができる[MediaPipe](https://google.github.io/mediapipe/)のHandsをひとまず採用した。
データセットが用意でき次第、より精度の出るモデルに置き換える予定。

GPUではなく、CPUを用いて推定を行う軽量なモデルであり、体の姿勢推定と並列化可能のため、並列化ライブラリのRayを使用して並列処理を実装した。



#今後の展望
- 推論の高速化

現状の推論速度は10~15FPSとリアルタイムで使用するためのものとしては高速とは言えない数値なので、推論の高速化をしていきたい。方策としては、現状Pytorchで構築しているモデルをより推論に適した形式のモデルに変換することを考えている。候補としてはNvidia GPUでの推論に適した形式であるTensorRTを採用予定。

- 表情の推定機能追加

FaceRigのように表情の推定機能を追加し、一つのシステムで全身のトラッキングに対応できるようにしたい。
face landmarksの位置を適用するだけではあまりアニメ調のモデルに対しては表情が作れないらしいので、感情分析の結果を表情ブレンドシェイプの値に変換して適用するなど、プラスアルファを入れる予定。

- 3Dのデータセットを用意して各モデルの再学習
3D姿勢推定関連のデータセットの作り方として、リアル調の3Dゲームからデータを作成する方法に期待をしている。とくに[JTA Dataset]
(https://aimagelab.ing.unimore.it/imagelab/page.asp?IdPage=25)はGTA5からModによって教師データセットを作成するという取り組みを行っており、使用したModも公開されているので、実際にデータセット作成を実践してみる予定。
また、これにより外観の多様性を持った3Dの教師データセットが用意できるので、3D姿勢の直接推定を行うモデルの採用も検討する。

#この記事を書いた理由
精度アップに必要な教師データの用意が難しいことにより停滞してしまっていたが、データを用意できる目途がたったことで再開することが出来そうになったため、各機能の要点や課題を復習するため、まとめを行った。
モチベーションがあるうちに、なるべく形にしていきたい。