首页 > 代码库 > Kinect 手势识别之挥手(C++实现)
Kinect 手势识别之挥手(C++实现)
以下代码是根据这里改编成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; }
Kinect 手势识别之挥手(C++实现)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。