前回まででKinect for Windows SDKでプログラミングするための開発環境が整ったので、今回は実際のソースコードを示します。ウィンドウのサイズや青いボールなど、GUIの要素を定義するXAML*1ファイルがリスト1、C#のコードがリスト2(その1、その2)です。
初期化でイベントハンドラを登録
アプリが起動し、ウィンドウが生成されるときに、ウィンドウのコンストラクタ「MainWindow」が呼ばれるので、この中にKinectの初期化処理を記述します。
まず、Runtimeクラスのオブジェクト「runtime」を生成した後、「Initializeメソッド」で利用する機能を指定し(リスト2の(1))、「VideoStream.Openメソッド」で動画機能を開始します(リスト2の(2))。(1)の「RuntimeOptions.UseSkeletalTracking」で関節の追跡機能の利用を、「RuntimeOptions.UseColor」でRGB画像の利用を設定しています。 なお、深度画像を使う場合は「RuntimeOptions.UseDepth」を、“プレイヤーのインデックス付き深度画像”を使う場合は「RuntimeOptions.UseDepthAndPlayerIndex」を指定します。
プレイヤーのインデックス付き深度画像とは図4左上のような画像です。この画像では1ピクセルが2バイトで表現されます。そのうち、最初の3ビットでプレイヤーのインデックスを表します。つまり、そのピクセルがどのプレイヤーに属しているかを3ビットで最大6人まで示すわけです。図4左上はプレイヤーのインデックスを色分けしたものです。RGB画像と比較すればプレイヤーがほぼ正しく識別されていることがわかるでしょう。
RGB画像、深度画像およびプレイヤーのインデックス付き深度画像で取得できるデータのサイズなどを表4にまとめました。
次はイベントハンドラの登録です(リスト2の(3))。これは.NET Frameworkの「EventHandlerジェネリックデリゲート」機能を使って行います。前述のように、登録するのは「画像を表示する準備ができたとき」に呼ばれるイベントハンドラと、「関節(骨格)のデータを提供する準備できたとき」に呼ばれるイベントハンドラです。イベントハンドラのメソッド名は自由に決められるので、前者は「nui_ColorFrameReady」に、後者は「nui_SkeletonFrameReady」にしました。
Kinectのカメラは30FPS(フレーム/秒)で動作するので、処理落ちがなければnui_ColorFrameReadyイベントハンドラは1秒間に30回呼ばれます。nui_SkeletonFrameReadyイベントハンドラも、処理落ちがなければ1秒間に30回呼ばれるようです(少しまぎらわしいかもしれませんが、実際には関節を追跡できていなくても呼ばれます。追跡状態はリスト2の(4)のような記述で確認できます)。
初期化の最後では、追跡する関節の軌跡を平滑化する設定を記述しています(リスト2の(5))。関節の生データ(座標値)は変化が激しいので、そのまま使うと常に“振動”しているように見えてしまいます。そのため、データを平滑化して滑らかに動くようにするのです。