Kinectでカメラの中心に近い人をトラッキングする。あるいはイマドキのプログラムの作り方。

こんにちは。ヤマヤタケシです。 今となっては古いKinectをいじっています。

Kinectは2人までトラッキングできますし、カメラに2人以上入っているとアプリはどちらを使えばいいのか困ってしまいます。 特に、人が交代するのが困難です。

そうだ、カメラの真ん中に映っている人を優先すればいいじゃない!
やたら普通な発想です。

普通すぎて誰かがもうコードを書いているんじゃないか? キネクトは6人まで認識できますが、関節の状態というかポーズを認識できるのは2人までです。残りの4人は位置だけです。

ポーズを認識する2人を設定する命令があった気がします。
このあった気がするのは、ひと通り目を通していたことに起因しますね。さすが俺。

まずはキネクトのリファレンスに当たります。 INuiSensor::NuiSkeletonSetTrackedSkeletons どうやらこれを使えばいいみたいです。

ここからがインターネット時代の技! NuiSkeletonSetTrackedSkeletons でググります。 その関数を使っているコードが公開されているのじゃないか?コピペはできないにしても、誰かが実現していればとても安心ですし、困ったら解析すれば良いのです。

ありました。
https://github.com/geis/KinectSDKBook4CPP/blob/master/2_apply/SelectSkeleton/main.cpp から引用します。

// 一番中心に近いプレイヤーを探す
    for ( int i = 0; i < NUI_SKELETON_COUNT; ++i ) {
      NUI_SKELETON_DATA& skeletonData = skeletonFrame.SkeletonData[i];
      if ( skeletonData.eTrackingState != NUI_SKELETON_NOT_TRACKED ) {
        FLOAT depthX = 0, depthY = 0;
        ::NuiTransformSkeletonToDepthImage(
          skeletonData.Position, &depthX, &depthY, CAMERA_RESOLUTION );

        if ( abs(minpos - center) > abs(depthX - center) ) {
          minpos = depthX;
          trackedId = skeletonData.dwTrackingID;
        }
      }
    }

    // 現在追跡しているプレイヤーでなければ、中心に近いプレイヤーをアクティブにする
    if ( (trackedId != 0) || (trackedId != activeTrackId) ) {
      DWORD trackedIds[] = { trackedId, 0 };
      kinect->NuiSkeletonSetTrackedSkeletons( trackedIds );
      activeTrackId = trackedId;
    }

あぁ、まさにこういうコードをぼんやりと想像していました。それがすでにgithubにあってなおかつMITライセンス・・・。このコードは本のサンプルコードであり書いたのが誰かを追ってみると、Kaoru Nakamura さんでした。この人の別のKinectの本は持っていたので、多少のお金は間接的に払っています!

このコードでは、毎回セットするのではなく必要な時だけ NuiSkeletonSetTrackedSkeletons を呼び出しています。いいですね。ぼんやり想像していた時にはなかったコードです。やっぱ先人に学ぶ、まねぶのは価値があります。

20140512-104119.jpg

昔は自力でうんうん唸りながらやるしかなかったのですが、ググったら答えが出る時代になっています。良いとか悪いとかじゃなくて、活用するしかないですね!

まだ、先のコードは試していませんが、きっとうまくいくと信じています。さて、やんなきゃ。

そんじゃまた。

軽い気持ちで有名になりたいのでクリックをお願いします!