Nuitrack 1.5.0
3D スケルトン トラッキング ミドルウェア
|
このチュートリアルでは、Nuitrack とブレンドシェイプからの顔情報を使用して動く絵文字を作成する方法を紹介します。複数のスケルトン (最大数は 6) のトラッキングができ、ユーザーの顔の代わりに、キツネの動く絵文字が表示されます。キツネの顔が、ユーザーの顔の動きを連動して変化します。ユーザーが頭を動かすと、キツネの頭も同様に動きます。キツネの顔が揺れる際、キツネの毛がわずかに揺れていることにお気づきかもしれません。キツネの顔はズームイン、ズームアウトでき、ユーザーが近いほどキツネの顔は大きくなりますし、その逆も同様です。
このプロジェクトを作成するために必要なものは以下の通りです。
完成済みプロジェクトは、Nuitrack SDK: Unity 3D > NuitrackSDK.unitypackage > Tutorials > Animated Emoji にあります。
NuitrackScripts プレハブをシーンにドラッグ アンド ドロップします。必要な Nuitrack モジュール、Color Module On (センサーからの RGB イメージの出力)、Skeleton Tracker Module On (スケルトン トラッキング) を選択します。
新しいキャンバスを作成します。[Create] > [UI] > [Canvas]を選択し、Face Canvas と名前を付けます。Sort Order を 2 に設定します。このキャンバスをキツネの顔を表示するために使用します (キャンバスの上に RGB を表示し、スケルトンを表示)。
キャンバスに子オブジェクトを作成します。[Create] > [UI] > [Raw Image]を選択し、Fox Face と名前を付けます。このオブジェクトの設定を開き、[RectTransform]で、Width = 1、Height = 1 に設定します。[Scale]を適切な値に設定します (以下は一例)。X:100, Y:100, Z:1これは、ピクセルで表されたイメージ サイズで、これを基にキツネの顔が作成されます。1:1 の縦横比を必ず維持してください。そうしないなら、キツネの顔が縦/横に引き伸ばされてしまいます。サイズを小さく設定しすぎると、この段階でプロジェクトを実行した場合に、キツネの顔が見えなくなるので、注意してください。
Fox Face オブジェクトの設定を開き、Face テクスチャを Texture フィールドにドラッグ アンド ドロップします。
Camera オブジェクトの設定 (すぐに使用できるよう用意されている Fox Face Model プレハブ内) を開き、Face テクスチャを Target Texture フィールドにドラッグ アンド ドロップします。
お疲れ様です!これで、ユーザーの顔の表情をまねする 2D のキツネの顔が用意できました。
キツネの顔を管理するための新しいスクリプト FaceAnimController を作成します。UnityEngine.UI 名前空間を追加します。必要なフィールドを追加します (フィールド名で用途がわかるようになっています)。slerpRotation は頭の回転をスムーズにするために使用されます (使用しない場合、顔の回転時、顔が小刻みに動きます)。faceRaw フィールドは、キツネの顔を表示するために使用されます。
Init メソッドで、Canvas を渡すことにより、rawImage を子オブジェクトにします。さらに、最初のセクションで作成したRenderTexture を基にrenderTexture を作成します。renderTexture をCamera と rawImage オブジェクトのテクスチャに渡します。位置を設定し (お互いから離して)、イメージ (キツネの顔) を画面の高さまで引き伸ばします。縦横比を必ず維持してください。rawImage オブジェクトを生成します。
public メソッド UpdateFace を作成し、必要なパラメーター (JSON からのユーザーの顔に関する情報と頭の関節) を指定します。頭の関節の位置を射影座標で Nuitrack から取得し、これらの座標に頭を設定します (X と Y に画面の幅と高さを掛けます)。headRoot 位置を Z軸に沿って変更します (Nuitrack 空の情報を使用)。これが顔のズームを表し、ユーザーとセンサーの距離によって変化します (ユーザーがセンサーに近いほどキツネの顔が大きくなります)。
OnEnable と OnDisable メソッドを作成します。顔が有効な場合、rawImage も有効になり、顔のレンダリングができるようになります。
Fox Face Model プレハブをシーンにドラッグ アンド ドロップします。その後、FaceAnimController をプレハブにドラッグ アンド ドロップします。以下の画像に示されているように、フィールドを入力していきます。その後、[Apply]をクリックし、Fox Face Model をシーンから削除します。
新しいスクリプト、FaceAnimManager を作成します。このスクリプトでは、ユーザーの顔の代わりにキツネの顔を表示する方法を紹介します。nuitrack 名前空間を追加します。キャンバスのための canvas フィールド、キツネの顔のための facePrefab フィールドを追加します。faceCount を 0 から 6 の間で設定します (顔はスケルトンとリンクされており、トラッキング可能なスケルトンの最大数が 6)。faceInfo (Nuitrack からの 構文解析済み JSON、顔に関する情報をすべて取得) と faceAnimControllers の一覧 (顔の一覧) を追加します。
Start では、faceCount で設定した数だけ顔を生成します。キツネの顔をシーンに追加後に、faceAnimController を取得し、Init メソッドを呼び出します。キツネの顔はそれぞれ離すことで、カメラが同時に複数の顔をとらえないようにします。そうしないなら、1ユーザーに対して複数のキツネの顔が表示されてしまうことになります。faceAnimController を faceAnimControllers の一覧に追加します。トラッキングを行うスケルトン数を必要に応じて設定します (顔とスケルトンはリンク付けされますので、ご注意ください)。OnSkeletonUpdateEvent を登録します。
OnSkeletonUpdateEvent メソッドを作成: string json 変数を作成し、JSON からの情報を渡します。JSON からの構文解析済み情報を faceInfo に渡します: 引用符を角括弧に置き換えることで、配列が空 (顔に関する情報がない) の場合のエラーを防ぐことができます。顔の情報がない場合、メソッドの残りの部分は実行されません。
顔が取得されると、faceAnimControllers をループ処理します。検出されるスケルトンと同じ数だけ顔をアクティブにし、その他は、アクティブになりません。デフォルトの設定では、起動時に 6つの顔がアクティブになります。skeleton 変数を作成し、顔に対応するスケルトンを保存します (顔の ID とスケルトンの ID は一緒)。スケルトンが検出されたら、スケルトンから headJoint を取得し、信頼度が 0.5 であれば頭の関節をアクティブにします。faceAnimController, の UpdateFace メソッドを呼び出し、Instance (すべての顔パラメーター) を JSON と headJoint から渡します。スケルトンが検出されない場合、顔はアクティブになりません。
Face Canvas を、このオブジェクトの[Canvas]フィールドにドラッグ アンド ドロップします。Fox Face Model プレハブを [Face Prefab]フィールドにドラッグ アンド ドロップします。
ブレンドシェイプの ID を FaceAnimController に追加します。ブレンドシェイプの総一覧は、Fox_RigFace オブジェクト設定で確認できます。これらのブレンドシェイプのおかげで、キツネの顔の様々な部分を動かすことができます。このプロジェクトでは、キツネが口を開けたり、瞬きしたり、眉毛を上げ下げしたりできます。キツネの顔が動くとき、頬や耳の部分の毛がわずかに揺れ (動き) ます。見ての通り、このプロジェクトでは、7つのブレンドシェイプしか使っていませんが、Fox_RigFace にあるブレンドシェイプの一覧にはもっと多くあります。ポイントは、現段階で、人体計測ポイントを制限なく受け取れるということです (詳細は、「Nuitrack インスタンス ベース API [ベータ版]」 参照)。そのため、他のブレンドシェイプに関する十分な情報がありません。フィールド baseRotation (headRoot の最初の回転位置)、blendshapeWeights (0 から 100%)、newRotation (現在の頭の回転位置) を追加します。
Init メソッドで、baseRotation を保存します (最初の頭の回転、これを使用して現在の頭の回転を計算)。
UpdateFace で、ローカル変数 face を追加し、JSON から取得した顔を保存します。baseRotation を newRotation 変数に渡します。
ユーザーの顔に人体計測ポイントが検出されたら、ブレンドシェイプの重さを設定します (検出するには、ポイントがはっきり見え、他のオブジェクトによって隠れていないことが重要です)。すべて同じ方法、 SetBlendShapeWeight メソッドを使って設定されます: インデックスとブレンドシェイプの重さ (0-100) をこのメソッドに渡します。重さは blendshapeWeights クラスからとられ、該当するメソッドが呼び出され (キツネの口を開けるには GetJawOpenメソッド)、face をこのメソッドに渡します。結果として、各ブレンドシェイプの重さ値を取得できます。頭の回転を計算します: baseRotation (最初の回転位置) の生成物と JSON からの回転位置を newRotation 変数に渡します。
Update で、頭をスムーズに回転させます。