Blog
openFrameworksで、Leap Motionを使ってみた!
待ちに待ったLeap Motionがようやく届いたので、ちょびっとだけ触ってみた。
インストールとセットアップはとにかく簡単。Leap Motionのセットアップページに行って、一式ダウンロードとインストールするだけで、すぐに動作する。デモアプリの完成度もなかなかのもの。ユーザーにストレスを感じさせない環境構築までのナビゲーションのスムーズさに唸らされる。
ひと通り遊んだところで、openFrameworksからLeap Motionを使ってみることに。そのものズバリなofxLeapMotionというアドオンが開発されているので、それをそのまま利用できる。ただし、いくつかバージョンがありいくつか試した中で下記のリポジトリのバージョンが問題なくビルドできて、Leap Motionからのメッセージも受信できた。
まずは、Hello World的なサンプルとして、手を認識して表示してみる。
ofxLeapMotionでは2通りの方法が用意されている。1つ目は、ofxLeapMotion内で定義されているofxLeapMotionSimpleHandというシンプルな手のモデルを利用する方法。2つ目は、LeapMotionの純正のC++ SDKで用意されている機能にアクセスして表示する方法。
まずは、シンプルなofxLeapMotionSimpleHandを利用する方法で描画してみる。やり方はとても簡単で、ofxLeapMotionSimpleHandを認識したら、そのインスタンスに対してdebugDraw()というメソッドを呼びだせば簡単な手の3Dモデルを表示してくれる。
こんな感じ。
testApp.h
#pragma once #include "ofMain.h" #include "ofxLeapMotion.h" class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); void exit(); ofxLeapMotion leap; // Leap Motionのメインクラスをインスタンス化 vector <ofxLeapMotionSimpleHand> simpleHands; // シンプルな手のモデルのvector配列 ofEasyCam cam; //カメラ ofLight light; //ライト };
testApp.cpp
#include "testApp.h" void testApp::setup(){ // 画面設定 ofSetFrameRate(60); ofSetVerticalSync(true); ofBackground(31); // 照明とカメラ ofEnableLighting(); light.setPosition(200, 300, 50); light.enable(); cam.setOrientation(ofPoint(-20, 0, 0)); // GL設定 glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); // Leap Motion開始 leap.open(); } void testApp::update(){ // 検出された手の数だけ、ofxLeapMotionSimpleHandのvector配列に追加 simpleHands = leap.getSimpleHands(); // フレーム更新して、手が検出されたら if( leap.isFrameNew() && simpleHands.size() ){ // 画面の大きさにあわせて、スケールをマッピング leap.setMappingX(-230, 230, -ofGetWidth()/2, ofGetWidth()/2); leap.setMappingY(90, 490, -ofGetHeight()/2, ofGetHeight()/2); leap.setMappingZ(-150, 150, -200, 200); } // ofxLeapMotionに現在のフレームは古くなったことを通知 leap.markFrameAsOld(); } void testApp::draw(){ // 検出された数だけ、手を描画 cam.begin(); for(int i = 0; i < simpleHands.size(); i++){ simpleHands[i].debugDraw(); } cam.end(); }
実行結果はこんな感じ。シンプルだけど、手の平と各指先、そして指先の動きのベクトルが表示されている。
もちろん、ofxLeapMotionSimpleHandを利用して、指先や手の平などそれぞれのパーツの座標を個別にとり出すことも簡単。
testApp.h
#pragma once #include "ofMain.h" #include "ofxLeapMotion.h" class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); void exit(); ofxLeapMotion leap; // Leap Motionのメインクラスをインスタンス化 vector <ofxLeapMotionSimpleHand> simpleHands; // シンプルな手のモデルのvector配列 ofEasyCam cam; //カメラ ofLight light; //ライト vector <ofVec3f> fingerPos; };
testApp.cpp
include “testApp.h”
#include "testApp.h" void testApp::setup(){ // 画面設定 ofSetFrameRate(60); ofSetVerticalSync(true); ofBackground(31); // 照明とカメラ ofEnableLighting(); light.setPosition(200, 300, 50); light.enable(); cam.setOrientation(ofPoint(-20, 0, 0)); // GL設定 glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); // Leap Motion開始 leap.open(); } void testApp::update(){ // 検出された手の数だけ、ofxLeapMotionSimpleHandのvector配列に追加 simpleHands = leap.getSimpleHands(); // フレーム更新して、手が検出されたら if( leap.isFrameNew() && simpleHands.size() ){ //指の位置をクリア fingerPos.clear(); // 画面の大きさにあわせて、スケールをマッピング leap.setMappingX(-230, 230, -ofGetWidth()/2, ofGetWidth()/2); leap.setMappingY(90, 490, -ofGetHeight()/2, ofGetHeight()/2); leap.setMappingZ(-150, 150, -200, 200); // 検出された手の数だけくりかえし for(int i = 0; i < simpleHands.size(); i++){ // 検出された指の数だけくりかえし for(int j = 0; j < simpleHands[i].fingers.size(); j++){ // 位置をvectorに保存 ofVec3f pos = simpleHands[i].fingers[j].pos; fingerPos.push_back(pos); } } } // ofxLeapMotionに現在のフレームは古くなったことを通知 leap.markFrameAsOld(); } void testApp::draw(){ cam.begin(); // 検出された指の数だけくりかえし for(int i = 0; i < fingerPos.size(); i++){ // 検出された位置に立方体を描画 ofBoxPrimitive box; box.setPosition(fingerPos[i].x, fingerPos[i].y, fingerPos[i].z); box.set(20); box.draw(); } cam.end(); }
指先だけ独立して検出できた! 簡単!
ジェスチャーの検知や、Leap Motionから提供されている独自のSDKを呼び出して使用するやり方は、また今度。とりあえず、Leap Motion楽しい! ということで…
07.25: コードを若干修正