NtKinect: Kinect V2 C++ Programming with OpenCV on Windows10

Kinect V2 で関節の位置+手の平の状態を認識する


2016.07.16: created by
Japanese English
目次へ

前提として理解しておくべき知識


手の平の状態の認識

手の平の状態は、Kinect for Windows SDK 2.0 では次のように定義されています。

Kinect for Windows SDK 2.0 の Kinect.h(抜粋)
enum _HandState {
    HandState_Unknown= 0,
    HandState_NotTracked= 1,
    HandState_Open= 2,
    HandState_Closed= 3,
    HandState_Lasso= 4
};

enum _TrackingConfidence {
    TrackingConfidence_Low= 0,
    TrackingConfidence_High= 1
};

NtKinect では、 setSkeleton() を呼び出して骨格情報を取得したときに、 手の平の状態(パー、グー、チョキ)を取得することができます。

NtKinect

NtKinect の手の状態に関するメソッド

返り値の型 メソッド名 説明
pair<int,int> handState(int id =0, bool isLeft = true)

setSkeleton()関数を呼び出した後で呼び出して、手の状態を取得できる。

引数
id
skeleton[id ] の手の状態を取得する。
isLeft
左手の場合はtrue, 右手の場合falseを指定する。
返り値は「手の状態」と「確信度」のpair
手の状態: HandState 列挙型
HandState_{Unknown,NotTracked,Open,Closed,Lasso}
確信度: TrackingConfidence 列挙型
TrackingConfidence_{Low,High}

プログラム作成の手順

  1. NtKinect: Kinect V2 で骨格を認識する」 の Visual Studio のプロジェクト KinectV2_skeleton.zipを用いて作成します。
  2. main.cppの内容を以下のように変更します。
  3. kinect.setSkeleton()メソッドを呼び出してkinect.skeleton に骨格情報をセットします。 各人間の手の状態を取得するための handState()関数では、 第1引数に 「kinect.skeleton ベクタのindex」 を指定する仕様になっているので、 各人間の骨格情報にアクセスするのに制御変数 i を 用いたfor文でループしています。

    左右の手の平の位置情報は kinect.skeleton[i ][JointType_HandLeft] および kinect.skeleton[i ][JointType_HandRight] にあります。各関節の位置を 制御変数 j でループして 赤い四角形で表示していますが、 j の値が JointType_HandLeft または JointType_HandRight の場合は 手の平の状態を表す大きめの四角形も表示しています。

    main.cpp
    #include <iostream>
    #include <sstream>
    
    #include "NtKinect.h"
    
    using namespace std;
    
    void doJob() {
      NtKinect kinect;
      cv::Scalar colors[] = {
        cv::Scalar(255,0,0),  // HandState_Unknown
        cv::Scalar(0,255,0),  // HandState_NotTracked
        cv::Scalar(255,255,0), // HandState_Open
        cv::Scalar(255,0,255), // HandState_Closed
        cv::Scalar(0,255,255),  // HandState_Lass
      };
      while (1) {
        kinect.setRGB();
        kinect.setSkeleton();
        for (int i = 0; i < kinect.skeleton.size(); i++) {
          auto person = kinect.skeleton[i];
          for (int j = 0; j < person.size(); j++) {
            Joint joint = person[j];
            if (joint.TrackingState == TrackingState_NotTracked) continue;
            ColorSpacePoint cp;
            kinect.coordinateMapper->MapCameraPointToColorSpace(joint.Position,&cp);
            cv::rectangle(kinect.rgbImage, cv::Rect((int)cp.X-5, (int)cp.Y-5,10,10), cv::Scalar(0,0,255),2);
            if (j == JointType_HandLeft || j == JointType_HandRight) {
              pair<int, int> handState = kinect.handState(i, j == JointType_HandLeft);
              cv::rectangle(kinect.rgbImage, cv::Rect((int)cp.X - 8, (int)cp.Y - 8, 16, 16), colors[handState.first], 4);
            }
          }
        }
        cv::imshow("rgb", kinect.rgbImage);
        auto key = cv::waitKey(1);
        if (key == 'q') break;
      }
      cv::destroyAllWindows();
    }
    
    int main(int argc, char** argv) {
      try {
        doJob();
      } catch (exception &ex) {
        cout << ex.what() << endl;
        string s;
        cin >> s;
      }
      return 0;
    }
    
  4. プログラムを実行するとRGB画像が表示されます。'q' キーで終了します。
  5. RGB画像の上に、認識された関節が赤い四角形で示されます。 手の平状態に応じて次の色で四角が書かれます。

    手の平の状態cv::Scalarの引数
    Unknown255,0,0
    追跡不可0,255,0
    パーシアン255,255,0
    グーマゼンタ255,0,255
    チョキ黄色0,255,255



  6. サンプルのプロジェクトはこちら KinectV2_skeletonPalm.zip
  7. 上記のzipファイルには必ずしも最新の NtKinect.h が含まれていない場合があるので、 こちらから最新版をダウンロードして 差し替えてお使い下さい。



http://nw.tsuda.ac.jp/