書籍転載:Intel RealSense SDKセンサープログラミング(4)
Unity+RealSenseで作るノンゲームアプリ「スマイルトレーニング」
― Chapter 8 Unityで作る「ゲーム/ノンゲーム」アプリケーション ―
インテル RealSense SDKとUnityを使ったサンプルアプリケーションを実際に作成してみる。
前回は、インテル RealSense SDK Unity Toolkitの概要とUnity用機能を紹介しました。
書籍転載について
本コーナーは、翔泳社発行の書籍『Intel RealSense SDKセンサープログラミング』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『Intel RealSense SDKセンサープログラミング』の詳細や購入は翔泳社のサイトや目次ページをご覧ください。プログラムのダウンロードも、翔泳社のサイトから行えます。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
■
8-3 ノンゲームアプリ「スマイルトレーニング」
「Unity」といえばゲームエンジン、ゲームの開発環境として知られていますが、ゲーム以外の領域でもUnityを使うと豊かな表現力を持った生活に役立つアプリケーションを簡単に作ることができます。ここでは、インテル RealSense SDKとUnityを使ったサンプルアプリケーションをご紹介します。
8-3-1 センサーアプリケーションとヘルスケア
にっこりと笑う「スマイル」は、いろんな面で良い影響があると言われています。免疫機構が活性化して健康や病気の予防になるだけでなく、ストレス解消やメンタル面での健康にも役立つと言われています。あと、やはり笑顔の素敵な人は魅力的で好印象を他の人に与えますよね。
そんな良いこと尽くしの「スマイル」ですが、笑おう笑おうと思っても自由にすぐできるものでもありません。そこで、毎日少しでもスマイルするトレーニングを行うことで、自然に笑顔が出るようにサポートするアプリケーションを、画像認識が可能なセンサーであるRealSenseを利用して作ってみましょう。
人の動きを認識する3D認識センサーは医療・ヘルスケア分野と親和性が高く、大きな注目を浴びている分野の一つです。そこにUnityを組み合わせれば、これまで医療・ヘルスケア分野とは無縁と思われていた「楽しさ」を伴った、より継続的で効果的なアプリケーションを手軽に構築することができますので、ぜひその入り口を体験してみましょう。
8-3-2 アプリケーションの概要
今回構築するアプリケーションは、「毎日短時間で楽しくスマイルの練習をする」という狙いで図8.39のような流れを構築することとします。淡々と進行するだけでなく楽しい要素も盛り込んでいきます。ユーザーの表情とキャラクターの表情を同期させて、スマイルが一定の基準を超えるとエフェクトが表示されるというものにしようと思います。
今回キュートなキャラクターとして、ユニティ・テクノロジーズ・ジャパンが提供する開発者のためのオリジナルキャラクター「ユニティちゃん」を利用することにします。
ユニティちゃんのデータファイルは「UNITY-CHAN!OFFICIAL WEBSITE」からダウンロードすることができます。利用に際してはライセンス条項に同意し、遵守することが必要です。本サンプルプログラムについても下記クレジットを標記の上、解説を行っていきます。今回は「SDユニティちゃん3Dモデルデータ」をダウンロードして利用します。
8-3-3 アプリケーションの構築
>シーン構成
まずは、Unityで下記のようなシーンを作っていきましょう。オブジェクトの位置は正確でなくても構いませんので、特筆すべき点があるオブジェクトのみ解説していきます。
>Image
ユーザーの顔の映像をリアルタイムに映し出すSDK Unity ToolkitのImageプレファブのインスタンスです。位置・サイズ以外は変更していません。Main Cameraの子オブジェクトとすることで、カメラが移動することがあっても追従するようにしています。
>SD_unitychan_generic
SDユニティちゃんのパッケージをインポートしたのち、Assets/UnityChan/SD_unitychan/Prefabs/SD_unitychan_generic
プレファブをインスタンス化したものです。図8.42のように、いくつかの設定変更を加えます。
>Directional light for UnityChan
SDユニティちゃんのパッケージのAssets/UnityChan/Prefabs/Directional light for UnityChan
プレファブをインスタンス化したものです。
>Controller
アプリケーションの進行を管理するコントローラーです。空のGameObjectをひとまず用意しておいてください。詳しくは後述します。
>Particle System
グッドなスマイルを決めたときに再生されるパーティクルです。一例として図8.43のように設定していますが、好みに合わせて設定を変更してみると楽しめるでしょう。
>Canvas
ガイダンスのテキストやユニティちゃんロゴなどを表示するUIレイヤーです。Unity 4.6からサポートされたuGUIのパーツを配置しています。
>表情のシンクロ
ユーザーの表情の状態とユニティちゃんの表情を同期する処理を作ります。インテル RealSense SDKでは、表情(笑っている、怒っているなど)とその表情の強さのレベルを認識することができます。一方、ユニティちゃんの顔には「ブレンドシェイプ」という、指定する重みレベルに応じて連続的に変形するオブジェクトが用意されています。これらを紐付けることで、表情のシンクロを行います。具体的な処理はFaceSync.csスクリプトを作成し、SD_unitychan_genericにアタッチさせることで行っています。
まず、Unityとのインタフェースでブレンドシェイプを保持するSkinnedMeshRenderer
プロパティを作成しています(リスト8.4)。ブレンドシェイプには変形点のリストがあるので、今回操作したい点のインデックスを調べて定数化しておきます。
public class FaceSync : MonoBehaviour {
public SkinnedMeshRenderer faceMeshRenderer; //顔のメッシュオブジェクト
private int mouthSmileIndex = 17; //口の笑顔ブレンドシェイプ
private int mouthLeftIndex = 24; //口の左引っ張りブレンドシェイプ
private int mouthRightIndex = 25; //口の右引っ張りブレンドシェイプ
private int eyeSmileIndex = 1; //目の笑顔ブレンドシェイプ
private int browSmileIndex = 2; //眉の笑顔ブレンドシェイプ
|
faceMeshRendererプロパティにはSDユニティちゃんオブジェクト内の_face
というオブジェクトを設定します(図8.45)。これでブレンドシェイプとスクリプトのリンクができました。
毎フレーム呼び出されるUpdateメソッドでは、インテル RealSense SDK、Unity SDK ToolkitのSenseToolkitManager
のインスタンスから顔の情報を取得します。複数の顔が認識されていても最初に見つかった顔を対象としてQueryExpressions
メソッドで表情の情報ExpressionData
を取得します。
void Update()
{
if (SenseToolkitManager.Instance.FaceModuleOutput == null)
{
return;
}
// 検出した顔の一覧を取得する
var faces = SenseToolkitManager.Instance.FaceModuleOutput.QueryFaces();
if (faces.Length == 0)
{
return;
}
// 最初の顔の表情を取得する
var face = faces[0];
var expression = face.QueryExpressions();
if (expression == null)
{
return;
}
if (this.faceMeshRenderer != null)
{
this.SyncMouth(expression);
this.SyncEye(expression);
}
}
|
ExpressionData
からQueryExpression
メソッドにEXPRESSION_SMILE
値を渡して呼び出すとスマイルの情報を取得することができますので、スマイルの強さを表すintensityの値を口元の3点のブレンドシェイプへSetBlendShapeWeight
メソッドを呼び出して設定することでSDユニティちゃんの口元がユーザーの口の動きにシンクロして動きます(リスト8.6)。
/// <summary>
/// 口の表情シンクロ
/// </summary>
/// <param name="expression">表情オブジェクト</param>
private void SyncMouth(PXCMFaceData.ExpressionsData expression)
{
// 口を動かすPXCMFaceData.ExpressionsData.FaceExpressionResult result;
expression.QueryExpression(PXCMFaceData.ExpressionsData.
FaceExpression.EXPRESSION_SMILE, out result);
var level = (int)result.intensity;
this.faceMeshRenderer.SetBlendShapeWeight(this.mouthSmileIndex, level);
this.faceMeshRenderer.SetBlendShapeWeight(this.mouthLeftIndex, level);
this.faceMeshRenderer.SetBlendShapeWeight(this.mouthRightIndex, level);
}
|
目の動きもシンクロしてやると、より自然な雰囲気になりますので、口元と同様に右目と左目の閉じ度合いをシンクロさせます(リスト8.7)。SDユニティちゃんのブレンドシェイプは右目と左目を別々にコントロールすることができないので、左右の平均値を求めて設定をしています。
/// <summary>
/// 目と眉の表情シンクロ
/// </summary>
/// <param name="expression">表情オブジェクト</param>
private void SyncEye(PXCMFaceData.ExpressionsData expression)
{
PXCMFaceData.ExpressionsData.FaceExpressionResult left;
expression.QueryExpression(PXCMFaceData.ExpressionsData.
FaceExpression.EXPRESSION_EYES_CLOSED_LEFT, out left);
PXCMFaceData.ExpressionsData.FaceExpressionResult right;
expression.QueryExpression(PXCMFaceData.ExpressionsData.
FaceExpression.EXPRESSION_EYES_CLOSED_RIGHT, out right);
var level = (int)((left.intensity + right.intensity) / 2);
this.faceMeshRenderer.SetBlendShapeWeight(this.eyeSmileIndex, level);
this.faceMeshRenderer.SetBlendShapeWeight(this.browSmileIndex, level);
}
|
ここまでで実行すると、ユーザーの表情に応じてSDユニティちゃんの表情もシンクロして変化するようになりました。
>ステージ進行
次にアプリケーションのステージ進行を作っていきましょう。ステージ進行をつかさどるのは、シーン内のController
オブジェクトです。Inspectorは図8.46のようになっています。
Controller.csスクリプトが、このサンプルアプリケーションのコアになる部分で、中央で全体のコントロールを行うものとなります。Controller.csスクリプトは新規C#スクリプトとして作成し実装を行ったものです。
まず、Unityとのインタフェース(リスト8.8)ですが、goalGoodSmileCount
はトレーニングのゴールとみなす素敵なスマイルの回数です。デフォルトでは5回の素敵なスマイルでクリアすることになっています。
そのほか、パーティクルやテキストのオブジェクトはシーンから関連付けを行います。
public class Controller : MonoBehaviour {
/// <summary>
/// ゴールに必要なグッドなスマイル回数
/// </summary>
public int goalGoodSmileCount = 5;
/// <summary>
/// スマイル時に再生するパーティクル
/// </summary>
public ParticleSystem smileParticle;
/// <summary>
/// メッセージ表示用テキスト01
/// </summary>
public Text messageText01;
/// <summary>
/// メッセージ表示用テキスト02
/// </summary>
public Text messageText02;
|
続いて、状態管理用の内部列挙型、プロパティを定義します(リスト8.9)。CurrentStage
プロパティは、トレーニングで現在進行中のステージを表します。今回のサンプルではそれほど利用していませんが、複雑なゲームやアプリケーションになると現在のステージ状況は多くの箇所で参照するので、きちんと管理すべき重要なポイントです。
そのほかは現在スマイルしているかどうかを表すIsGoodSmiling
、トータルのスマイル数を保持するGoodSmileCount
プロパティを用意しています。
/// <summary>
/// ステージ定義
/// </summary>
public enum Stage
{
None,
Start,
Practice,
Goal
}
/// <summary>
/// 現在のステージ
/// </summary>
public Stage CurrentStage { get; private set; }
/// <summary>
/// グッドなスマイルフラグ
/// </summary>
public bool IsGoodSmiling { get; private set; }
/// <summary>
/// グッドなスマイル回数
/// </summary>
public int GoodSmileCount { get; private set; }
|
フレーム処理は、リスト8.10のようになります。
Start
メソッドでは、現在のステージプロパティを初期化するだけです。Update
メソッドでは、現在のステージが初期状態ならステージ進行を開始します。
このサンプルアプリケーションではゴール後ステージ状態は初期状態に戻すようにしますので、繰り返しステージ進行が始まる動きになります。
// Use this for initialization
void Start()
{
this.CurrentStage = Stage.None;
}
// Update is called once per frame
void Update()
{
if (this.CurrentStage == Stage.None)
{
//一連のステージ進行を繰り返す
this.StartCoroutine(this.ProcessStart());
}
}
|
リスト8.11は、素敵なスマイルをインテル RealSense SDKが検出したときにスマイル回数をカウントアップする部分です。カウントアップはトレーニング中のステージ以外は行ってはいけないので、条件判定を行って制御を行っています。また、カウントアップ時にはパーティクルを再生して気分を盛り上げます。
/// <summary>
/// グッドなスマイル検出時
/// </summary>
void OnGoodSmile()
{
if ((this.CurrentStage == Stage.Practice) && !this.IsGoodSmiling)
{
//スマイル回数を増やしてパーティクルを再生
this.GoodSmileCount++;
this.smileParticle.Play();
}
this.IsGoodSmiling = true;
}
/// <summary>
/// グッドじゃないスマイル検出時
/// </summary>
void OnBadSmile()
{
this.IsGoodSmiling = false;
}
|
さて、このメソッドとインテル RealSense SDKはどのようにリンクするのでしょうか。それがController
にアタッチされた2つのSendMessageActionです(図8.47)。
1つは、表情を検出した際にTriggerを発動するFacialExpressionDetected Ruleを設定しています。Fire Over Intensityを80
とすることで、かなり素敵なスマイルをしないとTriggerは発動しないようになっています。そしてTriggerが発動すると、Unityのメッセージング機構が呼び出されController.csのOnGoodSmile
メソッドがコールされます。
もう1つのSendMessageActionは、FacialExpressionLost Ruleを付与して逆の認識をさせることでスマイルをやめたことを検出してTriggerを発動させるようになっています。
あとは、ステージごとの処理をUnityのフレーム処理にブロックをかけないコルーチンとして定義していきます。
練習スタートステージではキー入力待ちをし、キー入力があったら練習ステージへ移行します(リスト8.12)。
/// <summary>
/// スタートステージ
/// </summary>
/// <returns></returns>
private IEnumerator ProcessStart()
{
this.CurrentStage = Stage.Start;
this.GoodSmileCount = 0;
this.messageText01.color = Color.white;
this.messageText02.color = Color.white;
this.messageText01.text = "スマイルの練習を始めるよ! ";
this.messageText02.text = "Enterを押したらスタートだよ! ";
while (!Input.GetKeyDown(KeyCode.Return)
&& !Input.GetKeyDown(KeyCode.KeypadEnter))
{
yield return 0;
}
yield return this.StartCoroutine(this.ProcessPractice());
}
|
練習ステージでは、スマイル回数がゴール条件を満たすまでループします(リスト8.13)。
/// <summary>
/// 笑顔練習ステージ
/// </summary>
/// <returns></returns>
private IEnumerator ProcessPractice()
{
this.CurrentStage = Stage.Practice;
this.messageText01.color = Color.white;
this.messageText02.color = Color.yellow;
while (this.GoodSmileCount < this.goalGoodSmileCount)
{
this.messageText01.text = string.Format("あと{0}回", this.goalGoodSmileCount - this.GoodSmileCount);
this.messageText02.text = this.IsGoodSmiling? "素敵なスマイルだね! " : "にっこり笑って! ";
yield return 0;
}
yield return this.StartCoroutine(this.ProcessGoal());
}
|
最後にゴール時のステージです(リスト8.14)。お礼を伝えて少し待機したら、ステージを初期状態に戻します。
/// <summary>
/// 笑顔練習ステージ
/// </summary>
/// <returns></returns>
private IEnumerator ProcessPractice()
{
this.CurrentStage = Stage.Practice;
this.messageText01.color = Color.white;
this.messageText02.color = Color.yellow;
while (this.GoodSmileCount < this.goalGoodSmileCount)
{
this.messageText01.text = string.Format("あと{0}回", this.goalGoodSmileCount - this.GoodSmileCount);
this.messageText02.text = this.IsGoodSmiling? "素敵なスマイルだね! " : "にっこり笑って! ";
yield return 0;
}
yield return this.StartCoroutine(this.ProcessGoal());
}
|
以上で、スマイルトレーニングアプリケーションをUnityとインテル RealSense SDKを組み合わせて作成することができました。さらに音楽を付けたり、ステージクリア時の表現を豊かにしたりするなど、簡単なカスタマイズでもっと楽しいものにできると思いますので、ぜひトライしてみて頂ければと思います。
■
次回は、インテル RealSenseを活用したサンプルアプリケーション開発の第2弾として、Visual Studio(WPFデスクトップ)とRealSenseを組み合わせる方法を紹介します。
※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
1. インテル RealSenseテクノロジーとは? 構成要素/SDK/動作環境
インテル RealSenseテクノロジーが登場するまでの流れ、RealSenseの仕様やSDKの概要について紹介する。
3. RealSense SDK Unity ToolkitによるUnityアプリ開発の基礎
インテル RealSense SDK Unity Toolkitの概要と、それがUnity向けに用意している各種機能を紹介する。
4. 【現在、表示中】≫ Unity+RealSenseで作るノンゲームアプリ「スマイルトレーニング」
インテル RealSense SDKとUnityを使ったサンプルアプリケーションを実際に作成してみる。
5. WPF(Visual Studio)+RealSenseで作る表情感知アプリ
インテル RealSenseを活用したサンプルアプリケーション開発の第2弾として、Visual StudioとRealSenseを組み合わせる方法を紹介する。