以下代码是根据这里改编成C++版的,实现思路上相同,但是细节有差异,不影响理解
#include<iostream>
#include<Windows.h>
#include<NuiApi.h>
#include<ctime>
#include<cassert>
#include<process.h>
#pragma comment(lib,"kinect10.lib")
using namespace std;
HANDLE DetectionEvent = CreateEvent( NULL, false, false, NULL );
// 记录手势当前位置
enum GesturePos{
NonePos = 0,
Left,
Right,
Neutral
};
// 判断识别状态
enum DetectionState{
NoneState = 0,
Success,
Failed,
InProgress
};
// 判断手势需要的数据
struct DataState{
GesturePos Pos; // 每个人的左右手
DetectionState State;
int times;
time_t timestamp;
void Reset()
{
Pos = GesturePos::NonePos;
State = DetectionState::NoneState;
times = 0;
timestamp = 0;
}
};
// 完成手势判断逻辑功能
class GestureDetection{
public:
GestureDetection( float neutral_threshold, int times, double difftimes )
: neutral_threshold( neutral_threshold )
, times(times)
, difftimes(difftimes)
, left_hand(0)
, right_hand(1)
{
for( int i = 0; i < NUI_SKELETON_COUNT; i++ )
{
wave_datas[i][left_hand].Reset();
wave_datas[i][right_hand].Reset();
}
}
// 功能:循环接收骨骼数据,如果识别出为挥手动作则输出:success,
// 识别失败输出:failed,
void Update( const NUI_SKELETON_FRAME* frame )
{
if( NULL == frame )
return ;
for( int i = 0; i < NUI_SKELETON_COUNT; i++ )
{
JudgeState( frame->SkeletonData[i], wave_datas[i][left_hand], true );
JudgeState( frame->SkeletonData[i], wave_datas[i][right_hand], false );
}
}
private:
DataState wave_datas[NUI_SKELETON_COUNT][2]; // 记录每个人,每只手的状态
const int left_hand; // 左手 ID
const int right_hand; // 右手 ID
// 中间位置阀值:在该范围内的都认为手在中间位置(相对于肘部的 x 坐标)
const float neutral_threshold;
// 挥手次数阀值,达到该次数认为是挥手
const int times;
// 时间限制,如果超过该时间差依然识别不出挥手动作则认为识别失败
const double difftimes;
// 判断当前的状态成功输出:success,并生成事件:DetectionEvent
// 失败输出 failed,供 UpDate 函数调用
void JudgeState( const NUI_SKELETON_DATA& skeletonData, DataState& data, bool isLeft = true )
{
int elbow = (isLeft)? NUI_SKELETON_POSITION_ELBOW_LEFT:
NUI_SKELETON_POSITION_ELBOW_RIGHT;
int hand = (isLeft)? NUI_SKELETON_POSITION_HAND_LEFT:
NUI_SKELETON_POSITION_HAND_RIGHT;
if( !IsSkeletonTrackedWell( skeletonData, isLeft ) )
{
if( data.State == InProgress )
{
#ifdef _DEBUG
cout << "not a well skeleton, detection failed!\n";
#endif
data.Reset();
return ;
}
}
float curpos = skeletonData.SkeletonPositions[hand].x ;
float center = skeletonData.SkeletonPositions[elbow].x;
if( !IsNeutral( curpos, center ) )
{
if( data.Pos == NonePos )
{
#ifdef _DEBUG
cout << "found!\n";
#endif
data.times++;
data.Pos = IsLeftSide(curpos,center)?Left:Right;
data.State = InProgress;
data.timestamp = time(NULL);
}
else if( ( (data.Pos == Left ) && IsRightSide( curpos, center ))
|| ( (data.Pos == Right) && IsLeftSide( curpos, center ) )
)
{
assert( data.State == InProgress );
data.times++;
data.Pos = (data.Pos == Left)?Right:Left;
#ifdef _DEBUG
cout << "times:" << data.times<< endl;
if( data.Pos == Left )
{
cout << "left !\n";
}
else if( data.Pos == Right )
{
cout << "right!\n";
}
else
cout << "you can't see me!\n";
#endif
if( data.times >= times )
{
#ifdef _DEBUG
cout << "success!\n";
#endif
SetEvent( DetectionEvent );
data.Reset();
}
else if( difftime( time(NULL), data.timestamp ) > difftimes )
{
#ifdef _DEBUG
cout << "time out, detection failed!\n";
cout << "data.times : " << data.times << endl;
#endif
data.Reset();
}
}
}
}
bool IsLeftSide( float curpos, float center )
{
return curpos < (center - neutral_threshold) ;
}
bool IsRightSide( float curpos, float center )
{
return curpos > (center + neutral_threshold) ;
}
bool IsNeutral( float curpos, float center )
{
return !IsLeftSide(curpos,center)&&!IsRightSide(curpos,center);
}
// 判断骨骼追踪情况:包括骨骼追踪完好且手部位置在肘上面
bool IsSkeletonTrackedWell( const NUI_SKELETON_DATA& skeletonData,
bool isLeft = true )
{
int elbow = (isLeft)? NUI_SKELETON_POSITION_ELBOW_LEFT:
NUI_SKELETON_POSITION_ELBOW_RIGHT;
int hand = (isLeft)? NUI_SKELETON_POSITION_HAND_LEFT:
NUI_SKELETON_POSITION_HAND_RIGHT;
if( skeletonData.eTrackingState != NUI_SKELETON_NOT_TRACKED )
{
if( (skeletonData.eSkeletonPositionTrackingState[hand]
!= NUI_SKELETON_POSITION_NOT_TRACKED )
&& (skeletonData.eSkeletonPositionTrackingState[elbow]
!= NUI_SKELETON_POSITION_NOT_TRACKED) )
{
if( skeletonData.SkeletonPositions[hand].y > skeletonData.SkeletonPositions[elbow].y )
return true;
}
}
return false;
}
};
#define CHECK_FAILED( hr, msg ) if(FAILED(hr)) { cout << msg << endl; return -1; }
unsigned int __stdcall doWave( void* p )
{
while( WaitForSingleObject( DetectionEvent,INFINITE ) == WAIT_OBJECT_0 )
{
cout << "do something when detecting wave hand\n";
cout << "hello what can i do for you?\n";
}
return 0;
}
int main()
{
int count;
INuiSensor *kinect = NULL;
HRESULT hr;
NuiGetSensorCount(&count);
if( count < 1 )
{
cout << "检测不到 Kinect\n";
return -1;
}
hr = NuiCreateSensorByIndex(0, &kinect );
if( FAILED(hr) || kinect == NULL)
{
cout << "创建 sensor 失败\n";
return -1;
}
if( kinect->NuiStatus() != S_OK )
{
cout << "Kinect sensor 没准备好\n";
return -1;
}
hr = kinect->NuiInitialize( NUI_INITIALIZE_FLAG_USES_SKELETON );
CHECK_FAILED( hr, "初始化失败" );
HANDLE next_frame_event = CreateEvent( NULL, true, false, NULL );
hr = kinect->NuiSkeletonTrackingEnable( next_frame_event, NUI_SKELETON_TRACKING_FLAG_ENABLE_IN_NEAR_RANGE );
CHECK_FAILED( hr, "打开骨骼追踪失败" );
uintptr_t thread = _beginthreadex( NULL, 0, doWave, NULL, 0, NULL );
if( thread <= 0 )
{
cout << "thread create failed!\n";
return -1;
}
NUI_SKELETON_FRAME skeleton_frame;
GestureDetection gesture_detection( 0.05, 3, 4 );
cout << "开始检测\n";
while(true)
{
if( WaitForSingleObject( next_frame_event, INFINITE ) == WAIT_OBJECT_0 )
{
kinect->NuiSkeletonGetNextFrame( 0, &skeleton_frame );
NuiTransformSmooth( &skeleton_frame, NULL );
gesture_detection.Update( &skeleton_frame );
}
}
kinect->NuiShutdown();
system("pause");
return 0;
}原文地址:http://blog.csdn.net/feitianhu213/article/details/38780101