ブログ@kaorun55

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

Kinect for Windows SDK v1.7 の Interactionを使ってみる(C++)

C++でKinectInteractionのライブラリを使ってみます。

基本的には Kinect for Windows SDK v1.7 の Interactionを使ってみる(C#) と同じになります。

すべてコードはこちらを参照いただくとして、要所を書いていきます。

一応取得できるのですが、途中で認識できなくなる場合もあるので、もしかしたら何か足りないかもしれません。

InteractionStreamの初期化

NuiCreateInteractionStream を使って INuiInteractionStream を初期化します。C#と同様にKinectインスタンスおよびINuiInteractionClient の派生クラスを渡します。インスタンスが生成できたら、Streamを有効にします。

// インタラクションライブラリの初期化

ERROR_CHECK( ::NuiCreateInteractionStream( kinect, &adapter, &stream ) );

stream->Enable( 0 );

INuiInteractionClient

INuiInteractionClient::GetInteractionInfoAtLocation() を実装します。C++では引数として渡されるので、それに設定します。なお、QueryInterface、AddRef、Releaseも実装する必要があります。

class KinectAdapter : public INuiInteractionClient

{

public:

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv)

{

return S_OK;

}

ULONG STDMETHODCALLTYPE AddRef()

{

return 1;

}

ULONG STDMETHODCALLTYPE Release()

{

return 0;

}

HRESULT STDMETHODCALLTYPE GetInteractionInfoAtLocation(DWORD skeletonTrackingId,

NUI_HAND_TYPE handType, FLOAT x, FLOAT y, _Out_ NUI_INTERACTION_INFO *pInteractionInfo)

{

pInteractionInfo->IsGripTarget = TRUE;

return S_OK;

}

};

Depthデータの設定

Depthデータを渡します。拡張された距離データを渡します。

void processDepth()

{

// 距離カメラのフレームデータを取得する

NUI_IMAGE_FRAME depthFrame = { 0 };

ERROR_CHECK( kinect->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ) );

// フレームデータを元に、拡張距離データを取得する

BOOL nearMode = FALSE;

INuiFrameTexture *frameTexture = 0;

kinect->NuiImageFrameGetDepthImagePixelFrameTexture( depthStreamHandle, &depthFrame,

&nearMode, &frameTexture );

// 距離データを取得する

NUI_LOCKED_RECT depthData = { 0 };

frameTexture->LockRect( 0, &depthData, 0, 0 );

if ( depthData.Pitch == 0 ) {

std::cout << "zero" << std::endl;

}

// Depthデータを設定する

ERROR_CHECK( stream->ProcessDepth( depthData.size, depthData.pBits, depthFrame.liTimeStamp ));

// フレームデータを解放する

ERROR_CHECK( kinect->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ) );

}

Skeletonデータの設定

Skeletonデータをわたします。

void processSkeleton()

{

// スケルトンのフレームを取得する

NUI_SKELETON_FRAME skeletonFrame = { 0 };

kinect->NuiSkeletonGetNextFrame( 0, &skeletonFrame );

// スケルトンデータを設定する

Vector4 reading = { 0 };

kinect->NuiAccelerometerGetCurrentReading( &reading );

ERROR_CHECK( stream->ProcessSkeleton( NUI_SKELETON_COUNT, skeletonFrame.SkeletonData,

&reading, skeletonFrame.liTimeStamp ) );

}

インタラクションフレームの処理

すれーむを処理します。こちらもすべてのプレイヤーの左右の手の情報が来るので、必要なものを使います。

void processInteraction()

{

// インタラクションフレームを取得する

NUI_INTERACTION_FRAME interactionFrame = { 0 } ;

auto ret = stream->GetNextFrame( 0, &interactionFrame );

if ( ret != S_OK ) {

return;

}

for ( auto user : interactionFrame.UserInfos ) {

if ( user.SkeletonTrackingId != 0 ) {

for ( auto hand : user.HandPointerInfos ) {

std::cout << EventTypeToString( hand.HandEventType ) << " " << std::endl;

}

}

}

}