KINECT for Windows V2 をopenFrameworksで動かす

KINECT V2をopenFrameworksで動かせるようになったので、その備忘録


KINECT V2をopenFrameworksで動かすためのアドオンとしては、

https://github.com/sadmb/ofxKinect2

など一部、使えるものも上がっているのだが、bodyFrameをとれるものがない…
C++初心者でアドオン頼みだった私には酷な現実です。でもなんとかしないといけないので、頑張りました。

ソフト、OS等
OS:Windows 8.1
開発環境:Microsoft Visual Studio Express 2012
その他
・openFrameworks v0.8.4
・Microsoft Kinect for Windows v2 Software Development Kit (SDK)


まずは、OFのアドオンに頼らずC++でKINECTを使えるようにセットアップ。


1.KINECT V2 用のSDKをダウンロード

https://www.microsoft.com/en-us/kinectforwindows/develop/

SDKとは開発者用キットのこと。モーションキャプチャとか基本のアプリケーションとかコードもある。最初はこのC++コードを解読して使おうとしたけど、断念。とりあえずダウンロード。



SDK Browser いろいろあって楽しい。Installからコードも取得できる。


2.OFの新しいプロジェクトを作成
プロジェクトジェネレータとか、サンプルのコピペとかでもいいので新しいプロジェクトを作成する。
OFの基本操作については省略します。


3.インクルードディレクトリ等の追加

新規作成したプロジェクトを立ち上げ、プロジェクト->プロパティを選択。

構成プロパティ -> VC++ディレクトリを選択。
・インクルードディレクトリを編集し、以下を追加する。
  SDKのインストールディレクトリ\Kinect\v2.0_1409\inc
・ライブラリディレクトリには以下を追加する。(32bitか64bitかは適当に)
  SDKのインストールディレクトリ\Kinect\v2.0_1409\\Lib\x86



さらに、
C/C++ -> 全般を選択し、「追加のインクルードディレクトリ」に同様に追加。
リンカ― -> 全般を選択し、「追加のライブラリディレクトリ」にも同様。
リンカ― -> 入力を選択し、「追加の依存ファイル」には「Kinect20.lib」を追加する。



以上で、セッティング完了。
あとはSDKに合わせてコードを書く。前述の通り、OFのアドオンは使わない…


以下、超簡単プログラム例
(左手の位置が画面上にトラッキングされて、ぐーちょきぱーを色分けされるだけ)
以下のURLのC++コードを参考に、OFに合うように一部変更。

参考URL:http://www.buildinsider.net/small/kinectv2cpp/05


ヘッダーファイル
#pragma once

#include "ofMain.h"
#include "Kinect.h"

class ofApp : 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);

float leftHandx, leftHandy;
float colorR, colorG, colorB;
int w,h;

private:
IKinectSensor* kinect;
IColorFrameReader* colorFrameReader;
IBodyFrameReader* bodyFrameReader;
IBody* bodies[BODY_COUNT];
};

___________________________

プログラムファイル
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
w = 1980;
h = 1080;
ofSetFrameRate(30);
ofBackground(0,0,0);

//デフォルトのKinectを取得する
HRESULT hr = GetDefaultKinectSensor(&kinect);

if(kinect)

{
IBodyFrameSource* bodyFrameSource = NULL;
//IColorFrameSource* colorFrameSource = NULL;
hr = kinect->Open();
if(SUCCEEDED(hr))
{
hr = kinect->get_BodyFrameSource(&bodyFrameSource);
//hr = kinect->get_ColorFrameSource(&colorFrameSource);
}
if(SUCCEEDED(hr))
{
hr = bodyFrameSource->OpenReader(&bodyFrameReader);
//hr = colorFrameSource->OpenReader(&colorFrameReader);
}
bodyFrameSource->Release();
}

if(!kinect || FAILED(hr) )
{
std::cout << "no kinect sensor found!" << std::endl;
}
}


//--------------------------------------------------------------

void ofApp::update(){
if(!bodyFrameReader)
{
cout << "True" << endl;
return;
}

// カメラ座標系をDepth座標系に変換する

ICoordinateMapper* mapper;
HRESULT hr = kinect->get_CoordinateMapper( &mapper );

IBodyFrame* bodyFrame = nullptr;

auto ret = bodyFrameReader->AcquireLatestFrame(&bodyFrame);

if(ret == S_OK)

{
IBody* bodies[BODY_COUNT] = { 0 };
hr = bodyFrame->GetAndRefreshBodyData(6, bodies[0]);
//cout << "running" << endl;

if(SUCCEEDED(hr)){

for(int count = 0; count < BODY_COUNT; count++){
BOOLEAN isTracked = false;
hr = bodies[count]->get_IsTracked(&isTracked);
cout << "1" << endl;

if(SUCCEEDED(hr) && isTracked){

Joint joint[JointType::JointType_Count];
hr = bodies[count]->GetJoints(JointType::JointType_Count, joint);

cout << "2" << endl;


if(SUCCEEDED(hr)){

HandState leftHandState = HandState::HandState_Unknown;
hr = bodies[count]->get_HandLeftState(&leftHandState);

cout << "3" << endl;


if( SUCCEEDED(hr) ){

ColorSpacePoint colorSpacePoint = { 0 };
hr = mapper->MapCameraPointToColorSpace( joint[JointType::JointType_HandLeft].Position, &colorSpacePoint );

cout << "4" << endl;


if( SUCCEEDED(hr) ){


cout << "5" << endl;
cout << "number " << count << endl;

leftHandx = static_cast<int>( colorSpacePoint.X );

leftHandy = static_cast<int>( colorSpacePoint.Y );
if( ( leftHandx >= 0 ) && ( leftHandx < w ) && ( leftHandy >= 0 ) && ( leftHandy < h ) ){

cout << "6" << endl;


if( leftHandState == HandState::HandState_Open ){

colorR = 255; colorG = 0; colorB = 255;
cout << "open" << endl;
}
else if( leftHandState == HandState::HandState_Closed ){
colorR = 0; colorG = 255; colorB = 255;
cout << "close" << endl;
}
else if( leftHandState == HandState::HandState_Lasso ){
colorR = 255; colorG = 255; colorB = 0;
}
}
}
}
}
}
}
bodyFrame->Release();
}
}
//cout << "false" << endl;
}

//--------------------------------------------------------------
void ofApp::draw(){

ofSetColor(colorR,colorG,colorB);
ofCircle(leftHandx,leftHandy,10);
}

以下省略

とりあえず、これで動きました…
ここまで出来れば、ほかの身体部位については書き加えればOK
私は、両手の位置とStateをとってくるのが目的だったので、ほぼ目標達成です。

コメント

このブログの人気の投稿

入力インピーダンスってなに?

脳の3DグラフィックをOpenFrameworksで作成

デトロイト美術館展 上野の森美術館