DirectXの話 第115回

KINECTを使ってみた

今回は KINECT と OpenNI を使って戦車を動かしてみました。

DirectX 関係なくね? って言われそうですが、いつものことなので気にしないでください。

今更説明するまでもありませんが、KINECT は Microsoft が開発したモーションセンサーシステムです。

現状はXbox360で正式対応されているだけですが、春には非商用のSDKがWindows7で配布される予定です。

KINECTは発売当初からハックが流行して、自前でドライバを書いていた人も多くいました。

以前にBlogで紹介したOpenKinectもそんな中の1つです。

しかし、12月くらいだったと思いますが、KINECTの元の技術を開発したPrimeSenseという会社からOpenNIというライブラリが公開されました。

これはKINECTやその他のカメラデバイスを利用するもので、OpenKinectにはなかったボーン推定の機能が存在します。

ボーン推定は人間の動きを検知し、人間の骨の位置や方向を推測するもので、KINECTの肝となる機能と言えます。

OpenNIはすでに多くの人が利用していますし、実装も簡単なのであまり解説する部分はありません。

インストールの仕方もググれば簡単に出てきますしね。

一応重要な部分だけ簡単に書いておきます。

まず、ボーン推定を行うには UserGenerator を初期化する必要があります。

これはセンサーの前に立っているユーザを認識し、何人いるか、画面のどの部分がどのユーザかなどの情報を生成するようです。

ボーン推定をするにはこれがスケルトン機能をサポートしている必要があるようです。

g_UserGenerator.IsCapabilitySupported( XN_CAPABILITY_SKELETON );

この命令を利用すると UserGenerator がスケルトンをサポートしているかわかります。

KINECTを使用していればサポートはされるはずなので、これで false が返ってくるようだと色々問題ありですね。

UserGenerator はユーザの認識、キャリブレーション用ポーズの認識、ボーン推定等を自動的に行ってくれます。

ユーザが認識されるとそのユーザにはIDが振られます。基本的には 1~ の整数のようです。

各処理そのものは自動的に行われますが、一部の処理は始動してやらないと動作しません。

それらはすべてコールバックで行います。

コールバックはユーザが認識されたとき、キャリブレーション用のポーズを検知したとき、などで発行されます。

代表的なコールバックは以下の命令で設定します。

// ユーザを認識した、ユーザを見失った場合のコールバック

g_UserGenerator.RegisterUserCallbacks( KinectFuncNewUser, KinectFuncLostUser, NULL, hUserCallbacks );

// キャリブレーションを開始した、キャリブレーションを終了した場合のコールバック

g_UserGenerator.GetSkeletonCap().RegisterCalibrationCallbacks( KinectFuncCalibrationStart, KinectFuncCalibrationEnd, NULL, hCalibrationCallbacks );

// ポーズを検出した、ポーズを見失った場合のコールバック

g_UserGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks( KinectFuncPoseDetected, NULL, NULL, hPoseCallbacks );

KINECTから情報を取得する場合、フレームごとに xn::Context::WaitAndUpdateAll() 命令を呼び出します。

これを呼び出せばボーンの位置や深度情報などを取得できます。

ボーンの位置と回転は以下の命令で取得します。

// ボーンの位置を取得

g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition( userID, XN_SKEL_LEFT_SHOULDER, pos );

// ボーンの回転を取得

g_UserGenerator.GetSkeletonCap().GetSkeletonJointOrientation( userID, XN_SKEL_TORSO, rot );

ボーンの位置は各ボーンの付け根の座標だと思います。

回転は行列で取得でき、いわゆるTスタンスの時に単位行列になるはずです。

しかし、回転はあまり信用してはいけません。少なくとも、ひねりの情報は嘘くさいです。

さて、今回のサンプルでは戦車を動かしていますが、操作方法は腕の前後で前進・後退・左右旋回を行います。

また、右腕を左右に振ることで砲塔を旋回させることが出来ます。

実装方法として、ボーンの位置からベクトルを求め、基準となる姿勢からどの程度回転しているかを入力としています。

基準姿勢は胴体のボーンの回転を用いています。

胴体の下方向を肩から肘の方向の基準 (つまり0度) 、胴体の前方を肘から手の基準としています。

カメラに対する基準ではないので、胴体をひねると腕を突き出す方向が変わるはずです。

しかし、あまりにひねりすぎると砲塔の旋回がうまくいきません。カメラには正対してください。

サンプルは以下からDLしてください。

DirectX11を使用しているので、Windows7+KINECTが必要です。

KINECT は部屋がある程度広くないと厳しいのは事実です。

とはいえ、部屋のレイアウト次第では6畳でもなんとななります。

いろんなもので溢れている6畳だと難しいでしょうね。

とはいえ、いじっていて面白いガジェットですので、興味がある方は是非。