見出し画像

【技術解説】AutoPifu : 自動人物3Dモデル生成システムを作ってみた

HoloLabの斎藤です。今回GWの時間を使って、Azure KinectとPifuを用いた自動人物3Dモデル生成システムを作ってみました。カメラの前に立って特定のポーズを取るだけで、自分の3Dモデルが作成されるシステムになっています。

自己紹介

noteに書くのは初めてなので軽く自己紹介します。
HoloLabという会社でエンジニアをしています。HoloLabではxR領域におけるアプリケーション開発を行っており、主にMicrosoft HoloLensなどのMR(Mixed Reality)デバイスを用いた開発やMicrosoft Azure Kinect, Intel Realsenseなどのセンサーデバイスを用いた開発を行っています。

私自身としてですが、機械学習の分野、特に人物行動認識の領域に興味があります。xR領域と機械学習の組み合わせによる新しい価値の創造ができればと考えています。

KirinUtilの導入について

AutoPifuの説明を行う前に、KirinUtilについて紹介します。
今回のアプリケーションは、Kinectを使ったインタラクションが含まれるため、デザイニウムのノウハウが詰まったKirinUtilを使ってみました。

1. サクッと試したいことを試す(Unityカメラ画像の保存機能)
人物領域の画像を生成する際、初めにUnityカメラに描画された映像を使えないかと考えていました。(結果的には、人物領域のImageをTexture2Dに変換する形を取りましたが。)
そこで、KirinUtilのCaptureManagerを用いることで、ほとんど新しいコードを書くことなく、素早く試作→確認を行うことができました。

2. インタラクションでよく使う機能の利用(カウントダウン機能)
体験者に準備の余裕をもたせるため、Tポーズをとるという条件からすぐにシャッターを切るのではなく、カウントダウンを挟んでシャッターを切るようにしています。この際、KirinUtilのCountDown機能を使っており、こちらもまたほとんど新しいコードを書くことなく、実装ができました。


AutoPifuについて

さて、ではAutoPifuの解説に戻ります。
まず、全体像として、下図にシステムフローを載せておきます。
また解説の順序としては、Pifuに必要な入力と出力を踏まえた上で、Azure Kinectを用いて入力画像を作成する方法、さらにPifuから出力されたモデルデータを表示する方法について触れていきます。

画像1

1. Pifuに必要な入力と出力

1-1 . Pifuとは
一枚もしくは複数枚の画像から人物の3Dモデルを生成するための深層学習の手法を指します。また、本手法の学習済みモデルとサンプルコードも公開されています。本システムにおいても、サンプルのコードを加工したものを利用しています。

余談ですが、Pifuについては様々な方々が遊んでいたり解説記事を書いていたりします。

miyamoさん
https://github.com/dmiyamo3/miyamo-notebook/blob/master/works.md

龍 lileaさん
https://twitter.com/lileaLab/status/1257267334164578305

1-2 . Pifuの入力と出力
Pifuの入力として最低限必要なのは、人物領域画像と、人物領域を白く塗りつぶしたマスク画像の二つです。また、二つの画像の幅と高さを合わせる必要があります。

2. Azure Kinectによる人物領域画像の抽出と
 Mask画像作成

2-1. 人物領域の抽出
Azure Kinect センサーデバイスおよびAzure Kinect SDKを用いて人物領域を抽出しています。ここで、人物領域を抽出するために、Microsoft.Azure.Kinect.BodyTracking.FrameクラスのBodyIndexMapを用います。BodyIndexMapには1フレームの画像において、1画素ごとに人物を表すIndex値が格納されています。今回は簡単に、一人だけセンサーの前に立つという前提で、以下のようなコードにしています。

Capture bodyFrameCapture = frame.Capture;
Image bodyIndexMap = frame.BodyIndexMap;

Image colorImage = transformation.ColorImageToDepthCamera(bodyFrameCapture);
BGRA[] colorArray = colorImage.GetPixels<BGRA>().ToArray();
byte[] bodyIndexrArray = bodyIndexMap.Memory.ToArray();

for (int i = 0; i < colorImage.WidthPixels * colorImage.HeightPixels; i++)
{
    if (bodyIndexrArray[i] == 255)
    {   
        colorArray[i].B = 0;
        colorArray[i].G = 0;
        colorArray[i].R = 0;
        colorArray[i].A = 0;

    }
}


2-2. 人物領域画像の生成とMask画像作成
ここで、Azure Kinect SDK が提供するImageからTexture2Dに変換後、さらに幅と高さが同じになるように変換します。また、変換した画像からマスク画像を生成し、両方の画像をPNG形式で書き出します。(コードは長くなるので割愛します)

画像2

3. Unityでの結合と人物3Dモデルの表示

3-1. Unity C#での記述とPythonアプリケーションの呼び出し
Pifuに必要な入力画像が揃ったら、次にC#からPifu(Pythonアプリケーション)を呼び出します。ここで、Python側からの出力結果を受け取るためにRedirectStandardOutputをTrueにしています。また実行するPython側の引数はPifu/scripts/eval.shを参考にしています。

    internal void InitializeProcess()
       {
           //外部プロセスの設定
           processStartInfo = new ProcessStartInfo()
           {
               FileName = pyExePath, //実行するファイル(python)
               WorkingDirectory = pifuDir,
               UseShellExecute = false,//シェルを使うかどうか
               CreateNoWindow = true, //ウィンドウを開くかどうか
               RedirectStandardOutput = true, //テキスト出力をStandardOutputストリームに書き込むかどうか
               //実行するスクリプト 引数(複数可)
               Arguments = pyCodePath + " " + "--name pifu_demo "
                       + "--batch_size 1 --mlp_dim 257 1024 512 256 128 1 --mlp_dim_color 513 1024 512 256 128 3 "
                       + "--num_stack 4 --num_hourglass 2 --resolution 256 --hg_down ave_pool --norm group --norm_color group "
                       + "--test_folder_path  " + inputImagePath + " --load_netG_checkpoint_path " + checkpointsPathNetG +" --load_netC_checkpoint_path " + checkpointsPathNetC,
           };

       }

Pythonアプリケーションの実行終了時の通知を行うため、簡単にPifu/apps/eval.pyにおいてprint関数による出力を追加しています。そして、C#側で出力内容から3Dモデル書き出し先のパスを読み取ります。

3-2. 頂点カラーモデルの表示
生成されたOBJファイルの頂点情報は以下のようになっています。
頂点情報を表す"v"コマンドのあと、頂点座標(x, y, z)の値に続いてColor(r, g, b)の値が記述されています。C#のOBJをパースしてUnity上に表示させる際、この頂点カラー情報も読み取るようにします。また、頂点カラーを表示するためのShaderは以下の記事を参考にしています。
http://nn-hokuson.hatenablog.com/entry/2017/03/29/195041

v -0.7972 0.7188 0.1641 0.4479 0.2908 0.2540
v -0.7969 0.7188 0.1621 0.4466 0.2888 0.2516
v -0.7969 0.7180 0.1641 0.4395 0.2838 0.2468
...

まとめ

今回、Azure KinectとPifuを用いて、自動3Dモデル生成システムを作成してみました。また、その時に試作の効率化等にKirinUtilが役立ちました。
今後としては、作成された3Dモデルにリギングするなどの機能追加を考えています。

編集後記

デザイニウム広報のマリコです。今回はミズタニキリンが制作した『KirinUtil』をつかって頂いたというお話から、ホロラボの斎藤さんに記事を寄稿して頂きました✨斎藤さん、ありがとうございます❗「ホロのプーさん(@sai10kundayooo)」というTwitterアカウント名の破壊力がすごくて気づいていなかったのですが、今回同一人物だと知り驚きました(プロフに書いてあるんですけどね!)ホロラボは取締役の秦がCo-Founderもつとめていたり、東京オフィスをシェアしていることもあって、一緒にプロジェクトをすすめたりエンジニア同士の意見交換なども盛んに行われています😊

HoloLab
オフィシャルサイト
Twitter
Facebook

The Designium.inc
オフィシャルサイト
Interactive website
Twitter
Facebook

この記事が気に入ったらサポートをしてみませんか?