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畳だと難しいでしょうね。
とはいえ、いじっていて面白いガジェットですので、興味がある方は是非。