全バージョンから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() で検出状態かどうかを取得できます。
今回は、検出したジェスチャー名を表示するようにしています。