kinect for windows v2 + Visual Gesture Builder
ソニックジャム 研究開発部のkimです。 今回はKinect v2 のVirtual Gesture Builder をopenFrameworksの環境で使ってみたので、その説明をします。
概要
今まではkinectを使って人のジェスチャーを取るためには、プログラムの内部でアルゴリズムを作って判断していましたが、このやり方は、結構間違えが多かったり、コードの量もそのアルゴリズムによって増えたりして複雑でした。 しかし、kinect SDK 2.0のVisual Gesture Builderを使うことで、より簡単で正確な結果を得ることができました。 Visual Gesture Builderは、サンプルになる映像を分析しデータベースファイル(.gbd)を作ってくれます。 ジェスチャーの精度を上げるためには、もっと大量のサンプルを用意し、データベースをアップデートすれば可能です。
参考ーVisual Gesture Builderの仕組みや使い方が良く分かります。 http://channel9.msdn.com/Blogs/k4wdev/Custom-Gestures-End-to-End-with-Kinect-and-Visual-Gesture-Builder http://channel9.msdn.com/Blogs/k4wdev/Custom-Gestures-End-to-End-with-Kinect-and-Visual-Gesture-Builder-part-2-
addonの使い方
Visual Gesture Builderの一番いいところは、1つのgbdファイルに複数ジェスチャーを入れられる事です。 つまり、ジェスチャーが増えてもコードはそこまで増えません。 今回のaddonも1つのgbdファイルで複数のジェスチャーを検知する事ができるように作りました。 まずはC:\Program Files\Microsoft SDKs\Kinect\v2.0-PublicPreview1409\Redist\VGB\x86\にあるKinect20.VisualGestureBuilder.dllをプロジェクトのbinフォルダーにコピーします。 そして中にあるvgbtechsフォルダーをそのままbinフォルダーにコピーします。 これは以下のコマンドでも可能です。⬇︎
xcopy "$(KINECTSDK20_DIR)\Redist\VGB\$(Platform)\vgbtechs" "$(TargetDir)\vgbtechs" /S /R /Y /I
これをプロジェクトの プロパティ -> ビルドイベント -> ビルド後に入れればいい話なんですが、これがうまくいかず、今回は直接入れました。 これが今回一番の落とし穴でした。
参考 https://social.msdn.microsoft.com/Forums/it-IT/588c0f7c-9483-463d-addf-4c99113fc4b3/error-adding-gesture-to-visualgesturebuilderframesource?forum=kinectv2sdk
このaddonはofxKinectForWindows2をベースにしてるので、基本はofxKinectForWindows2を使う時と同じです。 変更したのはDeviceとsource/Bodyのclassです。DeviceのsetDatabaseメソッドを使いgbdファイルを読み込みます。
bool setDatabase(wstring _gbd);
gbdファイルは基本binフォルダー以下ならどこに置いても大丈夫です。 そして_gbdにはその経路をwstringで(ファイルの拡張子は無し)書くとデータベースがロードされます。 (setDatabase関数を使う前に必ずinitBodySource()を呼ぶ必要があります。) ジェスチャーを判断するのに使うメソッドは以下のものです。
const int &getGestureID(int n) { return getGestureResult(n) ? gestureResults[n].id : -1; }
nにはbodyの番号を入れます。 bodyがジェスチャーをするとそのジェスチャーのidを出力してくれます。 なんのジェスチャーも発見できない場合は-1の値を返します。 Visual Gesture Builder使う前は以下のようなコードを書いて、値を修正したり、ジェスチャーが変わる度にアルゴリズムやメソッドを変えたりしました。
ofVec2f checkClap(int n){ float dis = player[n].leftHandPos.distance(player[n].rightHandPos); float h = player[n].leftHandPos.y - player[n].leftShoulderPos.y; float hl = player[n].rightHandPos.y - player[n].rightShoulderPos.y; float x = -1; float y = -1; float back = ofMap(player[n].headPos.z, 1.0, 3.0, 300, 98, true); float clapArea = ofMap(player[n].headPos.z, 1.0, 3.0, 98, 35, true); if (bClapMode){ if(bAddClaps[n] && dis >= back){ bAddClaps[n] = false; } //複数のユーザーのための修正必要!! if (dis >= 0 && dis < clapArea && !bAddClaps[n]){ setClap(n); } }else{ if(bAddClaps[n]){ if(h >= 0 && hl >= 0){ bAddClaps[n] = false; } } //複数のユーザーのための修正必要! if (!bAddClaps[n]){ if (h < 0 || hl < 0) { setClap(n); } } return ofVec2f(x, y); }
Visual Gesture Builderを使うことでこれが結構楽になり、mainのプログラムではこのようにif文の中にジェスチャーの種類別にアクションを書くことだけに集中すればいいようになりました。
for (int i = 0; i < kinect.getBodySource()->getBodies().size(); i++){ int id = kinect.getBodySource()->getGestureID(i); if(id == -1){ //ジェスチャーをしてない cout<<"no gesture"<<endl; }else { //何かのジェスチャーをしてる switch (id){ case 0: //ジェスチャーid cout<<"bang love"<<endl; //アクション break; } } }
今回作ったaddonはgithubからダウンロードできます。














