Kinectというマイクロソフトから販売されたXbox 360向けのゲームデバイスでプレイヤーの位置、動き、声、顔を認識することができたりする。このデバイスを知って、自分は XBox 360 を持っていませが、思わず欲しくなってしまったので、購入しました。
今回は、このkinectの本当の凄いところである骨格情報について取得してみようと思う。
きっかけ
OpenNI のサイトが更新され、ソフトウェアも更新されていました。
unstable版も出て OpenNIのC#バインディングなども出てきたみたいなので、こちらを試してみました。
参照指定
"C:\Program Files\OpenNI\Bin\OpenNI.net.dll" が新たに追加されています。 このアセンブリを参照設定してください。

参照設定 posted by (C)k1ha410
コード
今回は、Windows Form でプロジェクトを作りました。コンソールベースでもよいのですが、 骨格情報とか出力する上でこちらを採用しました。 (今回は表示コードまで記載していません)
初期化コード
using xn;
public partial class Form1 : Form
{
Context context;
DepthGenerator depthGenerator;
UserGenerator userGenerator;
PoseDetectionCapability poseDetectionCapability;
SkeletonCapability skeletonCapbility;
public Form1()
{
InitializeComponent();
context = new Context(@"C:\Program Files\OpenNI\Data\SamplesConfig.xml");
depthGenerator = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
userGenerator = new UserGenerator(context);
userGenerator.NewUser += new UserGenerator.NewUserHandler(userGenerator_NewUser);
userGenerator.LostUser += new UserGenerator.LostUserHandler(userGenerator_LostUser);
poseDetectionCapability = new PoseDetectionCapability(userGenerator);
poseDetectionCapability.PoseDetected += new PoseDetectionCapability.PoseDetectedHandler(poseDetectionCapability_PoseDetected);
skeletonCapbility = new SkeletonCapability(userGenerator);
skeletonCapbility.CalibrationEnd += new SkeletonCapability.CalibrationEndHandler(skeletonCapbility_CalibrationEnd);
skeletonCapbility.SetSkeletonProfile(SkeletonProfile.All);
userGenerator.StartGenerating();
OpenNiThread = new Thread(new ThreadStart(OpenNiLoop));
OpenNiThread.Start();
}
上記コードで以下のような事をしました。
- xn.Context の作成 (context)
- xn.DepthGeneratorの取得 (depthGenerator)
- xn.UserGeneratorの作成 (userGenerator)
- 新しいユーザの検出、ユーザのロストイベントの追加(userGenerator.NewUser,userGenerator.LostUser)
- xn.PoseDetectionCapabilityの生成(poseDetectionCapability)
- ポーズ検出イベントの追加(poseDetectionCapability.PoseDetected)
- xn.SkeletonCapabilityの生成(skeletonCapbility)
- ガッツボーズ[キャリブレーション]の検出イベントの追加(skeletonCapbility.CalibrationEnd)
- SkeletonProfileの設定
- userGeneratorの開始
- OpenNi用のスレッド開始
これで初期設定が終わりました。
スレッドのメイン処理
次に、OpenNi用のスレッドの処理です
void OpenNiLoop()
{
while (!isDone)
{
var updated = false;
try
{ //1.深度センサー用ジェネレータの更新の待ち
this.context.WaitOneUpdateAll(depthGenerator);
}
catch (Exception)
{
}
//2.検出済みユーザー数の取得
var users = userGenerator.GetUsers();
foreach (uint user in users)
{
Console.WriteLine("User id {0}", user);
//3.検出ユーザがトラッキングできてるか?
if (skeletonCapbility.IsTracking(user))
{
//ここでスケルトン情報が取得できます
}
}
}
}
どのようにスケルトン情報を取得するかというと、 次のようなコードで取得できます。
SkeletonJointPosition Joint(uint user, SkeletonJoint joint)
{
var pos = new SkeletonJointPosition();
skeletonCapbility.GetSkeletonJointPosition(user, joint, ref pos);
if (pos.position.Z == 0)
{
pos.fConfidence = 0;
}
else
{
pos.position = depthGenerator.ConvertRealWorldToProjective(pos.position);
}
return pos;
}
第一引数のuserは、先ほどトラッキングできたか調べていたユーザidです。
SkeletonJointとは
- SkeletonJoint.Head(頭)
- SkeletonJoint.Neck(首)
- SkeletonJoint.LeftShoulder(左肩)
- SkeletonJoint.LeftElbow(左肘(ひじ))
- SkeletonJoint.LeftHand(左手)
- SkeletonJoint.RightShoulder(右肩)
- SkeletonJoint.RightElbow(右肘(ひじ))
- SkeletonJoint.RightHand(右手)
- SkeletonJoint.Torso(胴)
- SkeletonJoint.LeftHip(左尻)
- SkeletonJoint.LeftKnee(左膝(ひざ))
- SkeletonJoint.LeftFoot(左足)
- SkeletonJoint.RightHip(右尻)
- SkeletonJoint.RightKnee(右膝(ひざ))
- SkeletonJoint.RightFoot(右足)
などです。詳しくはSkeletonJointを参照ください。
SkeletonJointPosition.positionが、Point3Dを返却するので、 このX,Y,Zで各部位の座標を取得する事が出来ます。
イベントハンドラ
void userGenerator_NewUser(ProductionNode node, uint id)
{//新しいユーザを検出した時
System.Diagnostics.Trace.WriteLine(String.Format("New User {0}", id));
//新しいユーザのポーズ検出を開始します
poseDetectionCapability.StartPoseDetection(skeletonCapbility.GetCalibrationPose(), id);
}
void userGenerator_LostUser(ProductionNode node, uint id)
{//ユーザをロストした時
System.Diagnostics.Trace.WriteLine(String.Format("Lost User {0}", id));
}
void poseDetectionCapability_PoseDetected(ProductionNode node, string pose, uint id)
{//ガッツボーズを検出した時
System.Diagnostics.Trace.WriteLine(String.Format("PoseDetected {1} {0}", id, pose));
//新しいユーザのポーズ検出を終了し
poseDetectionCapability.StopPoseDetection(id);
//キャリブレーションを開始します
skeletonCapbility.RequestCalibration(id, true);
}
void skeletonCapbility_CalibrationEnd(ProductionNode node, uint id, bool success)
{//キャリブレーション完了した時
System.Diagnostics.Trace.WriteLine(String.Format("CalibrationEnd {1} {0}", id, success));
if (success)
{//成功したなら、トラッキング開始
skeletonCapbility.StartTracking(id);
}
else
{//失敗したなら、再度検出開始
poseDetectionCapability.StartPoseDetection(skeletonCapbility.GetCalibrationPose(), id);
}
}
上記のようにすることで、ユーザの各部位の位置情報が取得できます
おわりに
上記のように、Kinectでユーザの骨格情報が取得できます。かなりの粒度で値が 取得できるので、色々なことに応用できるかと思います。
楽天さんの紹介
これを見て、Kinect買ってみたいという方は 以下をチェックしてみてはいかがでしょうか?
(楽天さんのサイトです)
【Joshinは平成20/22年度製品安全優良企業 連続受賞・プライバシーマーク取得企業】送料0 ★Xbo... 価格:12,980円(税込、送料込) |
【在庫あり】【18時までのご注文完了で当日出荷可能!】MICROSOFT [Xbox360用]Kinectセンサー 価格:12,967円(税込、送料別) |
【送料無料】Xbox360 Kinect センサー 【対象ゲーム機本体と同時購入で300ポイント対象1201】 価格:12,283円(税込、送料別) |


TEAと申します
C#のキネクトのソースが大変参考になりました
ありがとうございます
失礼ですが、参考になさった資料などあれば乗せて頂けると助かります
画面に取り込んだイメージを表示しようとして
苦労しているもので・・・