ブログ@kaorun55

HoloLensやKinectなどのDepthセンサーを中心に書いています。

NiTE2(Beta) 入門(4) :ジェスチャーを検出する

全バージョンからNiTEの特長であったジェスチャーの検出をやってみます。ジェスチャーの検出はnite::HandTrackerが行います。検出できるジェスチャーはnite::GestureTypeに定義されており、現在のところGESTURE_WAVE、GESTURE_CLICK、GESTURE_HAND_RAISEの3つです。Waveは手を左右に振る動作、Clickは手を前後に振る動作、Hand Riseは手を挙げる動作です。

今回は、WaveとClickを検出させてみます。

#include <iostream>

#include<opencv2\opencv.hpp>

#include <NiTE.h>

cv::Mat convertDepthToColor( openni::VideoFrameRef& depthFrame )

{

cv::Mat depthImage = cv::Mat( depthFrame.getVideoMode().getResolutionY(),

depthFrame.getVideoMode().getResolutionX(),

CV_8UC4 );

openni::DepthPixel* depth = (openni::DepthPixel*)depthFrame.getData();

for ( int i = 0; i < (depthFrame.getDataSize()/sizeof(openni::DepthPixel)); ++i ) {

// 画像インデックスを生成

int index = i * 4;

// 距離データを画像化する

UCHAR* data = &depthImage.data[index];

// 0-255のグレーデータを作成する

// distance : 10000 = gray : 255

int gray = ~((depth[i] * 255) / 10000);

data[0] = gray;

data[1] = gray;

data[2] = gray;

}

return depthImage;

}

void main()

{

try {

nite::Status niteRet = nite::NiTE::initialize();

nite::HandTracker handTracker;

niteRet = handTracker.create();

if (niteRet != nite::STATUS_OK) {

throw std::runtime_error( "handTracker.create" );

}

// 認識させるジェスチャーを登録する

handTracker.startGestureDetection( nite::GestureType::GESTURE_WAVE );

handTracker.startGestureDetection( nite::GestureType::GESTURE_CLICK );

cv::Mat depthImage;

std::string detectGesture;

while ( 1 ) {

// 手の追跡フレームを取得する

nite::HandTrackerFrameRef handTrackerFrame;

handTracker.readFrame( &handTrackerFrame );

depthImage = convertDepthToColor( handTrackerFrame.getDepthFrame() );

// 認識したジェスチャー名を表示する

const nite::Array<nite::GestureData>& gestures =

handTrackerFrame.getGestures();

for ( int i = 0; i < gestures.getSize(); ++i ) {

if ( gestures[i].isComplete() ) {

if ( gestures[i].getType() == nite::GestureType::GESTURE_WAVE ) {

detectGesture = "wave";

}

else if (gestures[i].getType() == nite::GestureType::GESTURE_CLICK){

detectGesture = "click";

}

}

}

cv::putText( depthImage, detectGesture.c_str(),

cv::Point( 0, 50 ), cv::FONT_HERSHEY_SIMPLEX,

1.0, cv::Scalar( 255, 0, 0 ), 3 );

cv::imshow( "Gesture", depthImage );

int key = cv::waitKey( 10 );

if ( key == 'q' ) {

break;

}

}

}

catch ( std::exception& ) {

std::cout << openni::OpenNI::getExtendedError() << std::endl;

}

}

前述の通り、ジェスチャーの検出にはnite::HandTrackerを使います。初期化処理としてnite::HandTracker::create()を呼び出し、検出したいジェスチャーをnite::HandTracker::startGestureDetection() で登録します。

フレームの更新はnite::HandTracker::readFrame()を呼び出すことでnite::HandTrackerFrameRefにフレームデータが入ります。nite::UserTrakcer同様DepthFrameが取得できるので、グレー画像化します。

ジェスチャーは nite::HandTrackerFrameRef::getGestures() でnite::GestureDataの配列として取得できます。ジェスチャーの検出状態はnite::GestureData::isInProgress()で検出中かどうか(未検出状態)、nite::GestureData::isComplete() で検出状態かどうかを取得できます。

今回は、検出したジェスチャー名を表示するようにしています。