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;
}

时间: 2024-08-13 14:27:14

Kinect 手势识别之挥手(C++实现)的相关文章

手势识别(一)--手势基本概念和ChaLearn Gesture Challenge

以下转自: http://blog.csdn.net/qq1175421841/article/details/50312565 像点击(clicks)是GUI平台的核心,轻点(taps)是触摸平台的核心那样,手势(gestures)是Kinect应用程序的核心.和图形用户界面中的数字交互不同,手势是现实生活中存在的动作.如果没有电脑我们就不需要鼠标,但是没了Kinect,手势依然存在.从另一方面讲,手势是日常生活中人与人之间相互交流的一部分.手势能够增强演讲的说服力,能够用来强调和传递情感.像

图像处理实用资源

图像处理实用资源 本文转自:http://www.cnblogs.com/tornadomeet/archive/2012/05/24/2515980.html 跟OpenCV相关的: http://opencv.org/ 2012年7月4日随着opencv2.4.2版本的发布,opencv更改了其最新的官方网站地址. http://www.opencvchina.com/ 好像12年才有这个论坛的,比较新.里面有针对<learning opencv>这本书的视频讲解,不过视频教学还没出完,正

[转]机器学习、深度学习、数据挖掘各种资源整理

Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的theano库,主要是rbm系列,搞python的可以参考,很不错. deeplearning.net主页,里面包含的信息量非常多,有software, reading list, research lab, dataset, demo等,

DIP常用资源整理

Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的theano库,主要是rbm系列,搞python的可以参考,很不错. deeplearning.net主页,里面包含的信息量非常多,有software, reading list, research lab, dataset, demo等,

计算机视觉整理库

本文章有转载自其它博文,也有自己发现的新库添加进来的,如果发现有新的库,可以推荐我加进来 转自:http://www.cnblogs.com/tornadomeet/archive/2012/05/24/2515980.html Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的thean

【转】本人常用资源整理(ing...)

Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的theano库,主要是rbm系列,搞python的可以参考,很不错. deeplearning.net主页,里面包含的信息量非常多,有software, reading list, research lab, dataset, demo等,

机器学习的资源

Deep Learning(深度学习) ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的theano库,主要是rbm系列,搞python的可以参考,很不错. deeplearning.net主页,里面包含的信息量非常多,有software, reading list, research lab, dataset, demo等,强

cv/dl/cl领域的实验室官网/牛人主页/技术论坛/比赛数据库/好玩的东西

一(自己整理的) #技术论坛 1/mit的关于关于机器人的技术review https://www.technologyreview.com/c/robotics/ 2/valse视觉与学习青年学者讨论会 http://valser.org/ 3/人工智能资讯平台/机器人/机器视觉 http://www.ailab.cn/robot/Machine_vision/ #比赛 1/pascal voc 含各种代码和数据库 http://www.eecs.berkeley.edu/Research/P

常用学习资源汇总

Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):二 Bengio团队的deep learning教程,用的theano库,主要是rbm系列,搞python的可以参考,很不错. deeplearning.net主页,里面包含的信息量非常多,有software, reading list, research lab, dataset, demo等,