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

Kinect V2 でジェスチャを認識する


2016.08.20: created by
2016.10.20: revised by
Japanese English
NtKinect.h version 1.5 以降に対応しているトピックスです。
目次へ

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


Visual Gesture Builder ファイルを用いたジェスチャ認識

Microsoftが提供している Visual Gesture Builder を用いて、ジェスチャの識別器を機械学習によって生成することができます。 生成されるファイルの拡張子は .gbd または .gba です。

Visual Gesture Builder では、一つのソリューションの中に複数のプロジェクトが存在する形式となっており、 各プロジェクトを Build すると .gba ファイルが得られ、 ソリューション全体を Build すると.gbd ファイルが得られます。 すなわち、個別のジェスチャ識別ファイルの拡張子は ".gba" に、 複数のジェスチャをまとめたファイルの拡張子は ".gbd" になります。

Kinect for Windows SDK 2.0 ではVisual Gesture Builderのジェスチャ認識に関しては次のように定義されています。

Kinect for Windows SDK 2.0 の Kinect.VisualGestureBuilder.h(抜粋)
typedef enum _GestureType GestureType;
  enum _GestureType {
  GestureType_None	= 0,
  GestureType_Discrete	= 1,
  GestureType_Continuous	= 2
};

ジェスチャには Discrete(離散的) と Continuous(連続的)の2種類があり、 前者では confidence(確信度)、後者では progress(進捗度)という0.0から1.0までの 数字が付加されます。

Discreteジェスチャは AdaBoostアルゴリズム によって判定され、結果は真偽値で返ります。 confidenceの値を参照することで判断基準を変更することができます。

Continuousジェスチャは Random Forest アルゴリズム によって判定され、 結果は進捗状況が実数値で返ります。この値が progress です。


USE_GESTURE 定数を define してから NtKinect.h を include する と NtKinect のジェスチャ認識関係のメソッドや変数が有効になります。

Visual Gesture Builder で生成した ジェスチャの識別用ファイル .gbd を利用して Kinect V2 でジェスチャ認識をする ことができます。

NtKinect のジェスチャー認識に関するメソッド

返り値の型 メソッド名 説明
void setGestureFile(wstring& path ) version1.5以降。
ジェスチャーを定義したファイル(*.gbd)へのパスpath を設定する。デフォルトでは L"SampleDatabase.gbd" に設定されている。
void setGesture() version1.5以降。
setSkeleton()を呼び出した後に呼び出すことでジェスチャー認識を行う。
次のメンバ変数に値が設定される。
変数名説明
vector<pair<CComPtr<IGesture>,float>>discreteGestureDiscreteジェスチャと確信度のペアのベクタ
vector<UINT64f>discreteGestureTrackingIdDiscreteジェスチャに対応する骨格 trackingId のベクタ
vector<pair<CComPtr<IGesture>,float>>continousGestureContinuousジェスチャと進捗度のペアのベクタ
vector<UINT64f>continuousGestureTrackingIdContinuous ジェスチャに対応する骨格 trackingId のベクタ
string gesture2string(const CComPtr<IGesture>& gesture ) version1.5以降。
引数で指定されたジェスチャの名前を返す

NtKinect のジェスチャー認識に関するメンバ変数

変数名 説明
vector<pair<CComPtr<IGesture>,float>> discreteGesture version1.5以降。
認識したDiscreteジェスチャを、ジェスチャそのものと信頼度のペア pair<CComPtr<IGesture>,float> であらわす。複数の骨格の複数のジェスチャーを同時に認識するので vector<pair<CComPtr<IGesture>,float>> となる。
vector<UINT64> discreteGestureTrackingId version1.5以降。
Discrete ジェスチャに対応する骨格の trackingId のベクタ。
vector<pair<CComPtr<IGesture>,float>> continuousGesture version1.5以降。
Continuous ジェスチャは、ジェスチャそのものと進捗度のペア pair<CComPtr<IGesture>,float> で表される。 複数の骨格の複数のジェスチャーを同時に認識するので vector<pair<CComPtr<IGesture>,float>> となる。
vector<UINT64> continuousGestureTrackingId version1.5以降。
Continuous ジェスチャに対応する骨格の trackingId のベクタ。

「誰が行った動作であるか」など、認識されたジェスチャ i と骨格 j の 対応を取りたい場合は、

ジェスチャがDiscrete のとき
    kinect.discreteGestureTrackingId[i] == kinect.skeletonTrackingId[j] 
ジェスチャがContinuous のとき
    kinect.continuousGestureTrackingId[i] == kinect.skeletonTrackingId[j] 
で判定できます。


プログラム作成の手順

  1. NtKinect: Kinect V2 で骨格を認識する 」の Visual Studio 2015 のプロジェクト KinectV2_skeleton.zipを用いて作成します。
  2. プロパティに追加の設定を行います。
    1. プロパティを開きます
    2. ソリューションエクスプローラ内のプロジェクト名(この例では KinectV2 )をクリックで選択してから、右ドラッグででプロパティを選択します。

    3. Visual Gesture Builder 用のライブラリをリンクするように設定します。
    4. Kinect20.VisualGestureBuilder.lib
      



    5. Visual Gesture Builder関係の実行ファイルとジェスチャ定義ファイルが、プログラム実行時に適切な場所にコピーされるように設定します。
    6. 「構成プロパティ -> ビルドイベント -> ビルド後イベント -> コマンドライン」 で次の2行を追加する。

      xcopy "$(KINECTSDK20_DIR)Redist\VGB\x64" "$(OutDir)" /e /y /i /r
      if exist "$(ProjectDir)\*.gbd" ( copy "$(ProjectDir)\*.gbd" "$(OutDir)" /y )
      




  3. ジェスチャの定義ファイルをプロジェクトのフォルダ ( maiin.cpp や NtKinect.h と同じフォルダ)にコピーします。
  4. この例では、Kinect for Windows SDK v2.0 で配布されている以下の .gbd ファイルを用いています。

    $(KINECTSDK20_DIR)Tools\KinectStudio\databases\SampleDatabase.gbd
    

  5. main.cppの内容を以下のように変更します。
  6. まず最初に NtKinect 型の変数 kinect を宣言します。

    kinect.setGestureFile(string)を呼び出して、検出すべきジェスチャの定義ファイルを設定します。

    kinect.setSkeleton()メソッドを呼び出してから kinect.setGesture()メソッドを呼び出します。 ジェスチャが認識された場合は、kinect.discreteGesture や kinect.continuousGesture に設定されます。

    main.cpp
    #include <iostream>
    #include <sstream>
    
    #define USE_GESTURE
    #include "NtKinect.h"
    
    using namespace std;
    
    void putText(cv::Mat& img,string s,cv::Point p) {
      cv::putText(img, s, p, cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0,0,255), 2.0, CV_AA);
    }
    
    void doJob() {
      NtKinect kinect;
      kinect.setGestureFile(L"SampleDatabase.gbd");
      //kinect.setGestureFile(L"Seated.gbd");
      while (1) {
        kinect.setRGB();
        kinect.setSkeleton();
        for (auto person: kinect.skeleton) {
          for (auto joint: person) {
    	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);
          }
        }
        kinect.setGesture();
        for (int i=0; i<kinect.discreteGesture.size(); i++) {
          auto g = kinect.discreteGesture[i];
          putText(kinect.rgbImage,kinect.gesture2string(g.first)+" "+to_string(g.second), cv::Point(50,30+30*i));
        }
        for (int i=0; i<kinect.continuousGesture.size(); i++) {
          auto g = kinect.continuousGesture[i];
          putText(kinect.rgbImage,kinect.gesture2string(g.first)+" "+to_string(g.second), cv::Point(500,30+30*i));
        }
        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;
    }
    
    
  7. プログラムを実行するとRGB画像が表示されます。'q' キーで終了します。
  8. RGB画像の上方に、認識されたジェスチャが表示されます。 discrete ジェスチャは信頼度と共に左上に、continuous ジェスチャは進捗度と共にその右に表示されます。







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

  11. Kinect for Windows SDK v2.0 ではサンプルとしてもう一つ別の gbd ファイルが添付されています。 これを使って「座っている」動作を認識するように変更してみて下さい。上記の main.cpp でコメントアウトされている部分です。
  12. $(KINECTSDK20_DIR)bin\Database\Seated.gbd
    
  13. Visual Gesture Builder を用いて、ジェスチャを定義したファイルを自分で生成してみましょう(2016/10/20 追記)。 (注)Kinect Studio や Visual Gesture Builder の使用方法について本稿では簡単にしか触れていません。詳しい使い方はマニュアルや他の文献を参照して下さい。
  14. まず Kinect Studio を用いて「所定のジェスチャを行っている場合と行っていない場合の両方を含む」動画を撮影します。

    "Record"で記録する項目
        o Nui Body Frame
        x Nui Body Index                <--いらないのでcheckをはずす
        o Nui Depth
        o Nui IR
        o Nui Nui Sensor Telemetry
        x Nui Title Audio               <--いらないのでcheckをはずす
        x Nui Uncompressed Color        <--いらないのでcheckをはずす
    




    次に、Visual Gesture Builder を用いて、動画からジェスチャ検出用ファイルを生成します。 ユーザが手動で、 動画のうち「左手を肩よりも上に上げる動作」をしている部分を positive 、 他の部分を negative な状態として定義し、Visual Gesture Builder に機械学習 させると結果として ジェスチャ検出用ファイル LeftHandUp.gba が生成されます。

    ちなみに、このファイルの名前は "LeftHandUp.gbd" ではなく "LeftHandUp.gba"です。




    本稿の Visual Studio 2015 のプロジェクトのジェスチャーの定義ファイルを、 今回生成した LeftHandUp.gba に差し替えて実行してみましょう。

        kinect.setGestureFile(L"LeftHandUp.gba");
    
    「左手だけを肩より上に上げる」動作をdiscrete gestureとして認識し 「右手だけを肩の上に上げる」動作や「両手を肩の上に上げる」動作は 認識しないことを確認して下さい。



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