Kinect2.0 挥手动作的识别(C++实现)
2016-04-25 22:26
211 查看
最近刚入手一个Kinect 2.0,但是感觉学起来不容易,网上的资料并不多,搜了很多都是一代的资料,只能对着官方给的例子一个个的看,不懂得地方查函数库。在网上看到了一篇挥手动作识别的例子,觉得蛮有意思,但是,是针对一代的版本,在二代中跑不起来,特地改了一下,全当练练手。由于是新手,有不准确的地方,还请各位多指导。原文链接:点击这里
#include <Windows.h> #include <Kinect.h> #include <iostream> #include<ctime> #include<cassert> #include<process.h> #pragma comment(lib,"kinect20.lib") using namespace std; #define _DDDEBUG static int CTRL = 0; template<class Interface> inline void SafeRelease(Interface *& pInterfaceToRelease) { if (pInterfaceToRelease != NULL){ pInterfaceToRelease->Release(); pInterfaceToRelease = 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 < 1; i++) { wave_datas[i][left_hand].Reset(); wave_datas[i][right_hand].Reset(); } } // 功能:循环接收骨骼数据,如果识别出为挥手动作则输出:success, // 识别失败输出:failed, void Update(IBody * frame) { if (NULL == frame) return; for (int i = 0; i < 1; i++) { JudgeState(frame, wave_datas[i][right_hand],true); } } private: DataState wave_datas[1][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(IBody *n_body, DataState& data,bool isLeft = true) { Joint joints[JointType_Count]; // 定义骨骼信息 n_body->GetJoints(JointType::JointType_Count, joints); // 获取骨骼信息节点 int elbow = JointType_ElbowRight; int hand = JointType_HandRight; if (!IsSkeletonTrackedWell(n_body, isLeft)) // 如果手部的位置在肘部之上 则认为为真 { if (data.State == InProgress) { #ifdef _DDEBUG cout << "not a well skeleton, detection failed!\n"; #endif data.Reset(); return; } } float curpos = joints[hand].Position.X; float center = joints[elbow].Position.X; // 得到人手部和肘部的X坐标的位置 都是右手 if (!IsNeutral(curpos, center)) // 如果手部不是在中立的位置 { if (data.Pos == NonePos) { #ifdef _DDEBUG cout << "found!\n"; #endif data.times++; if ( get_length(curpos, center) == -1 ) { data.Pos = Left; } else if (get_length(curpos, center) == 1) { data.Pos = Right; } 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"; data.State = InProgress; data.timestamp = time(NULL); } else if ( ( (data.Pos == Left) && get_length(curpos, center) == 1) || ( (data.Pos == Right) && get_length(curpos, center) == -1 ) ) // 左摆找右摆 右摆找左摆 { assert(data.State == InProgress); data.times++; data.Pos = (data.Pos == Left) ? Right : Left; #ifdef _DDDEBUG 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 _DDDEBUG cout << "success!\n"; #endif CTRL = 1; data.Reset(); } else if (difftime(time(NULL), data.timestamp) > difftimes) { #ifdef _DDDEBUG cout << "time out, detection failed!\n"; cout << "data.times : " << data.times << endl; #endif data.Reset(); } } } } bool IsLeftSide(float curpos, float center) { int i = 0; i = get_length(curpos,center); if (i == -1) { return true; } else { return false; } } bool IsRightSide(float curpos, float center) { int i = 0; i = get_length(curpos, center); if (i == 1) { return true; } else { return false; } } bool IsNeutral(float curpos, float center) // 参数分别为手部的位置和肘部的位置 判断是否是中立的状态 { int i = 0; i = get_length(curpos, center); if (i == 0) { return true; // 是中立的状态 } else { return false; } } int get_length(float shou,float zhou) // 在这里定义 右边是 1 左边是 -1 中间是 0 { if (shou >= 0 && zhou >= 0) { if ((shou - zhou) > neutral_threshold) { return 1; // 在右边 } else if ((shou - zhou) < neutral_threshold || (zhou - shou) > -neutral_threshold) { return 0; // 中立 } else { return -1; // 左边 } } else if (shou >= 0 && zhou <= 0) { if ((shou + (-zhou)) > neutral_threshold) { return 1; // 右边 } else { return 0; // 中立 } } else if (shou <= 0 && zhou >= 0) { if ( ((-shou) + zhou) > neutral_threshold ) { return -1; // 左边 } else { return 0; // 中立 } } else { if ((-shou) >= (-zhou)) { if (((-shou) + zhou) > neutral_threshold) { return -1; // 左边 } else if (((-shou) + zhou) < neutral_threshold) { return 0; // 中立 } else { return 1; // 右边 } } else { if (((-zhou) + shou) > neutral_threshold ) { return 1; // 右边 } else { return 0; // 中立 } } } } // 判断骨骼追踪情况:包括骨骼追踪完好且手部位置在肘上面 bool IsSkeletonTrackedWell(IBody * n_body, bool isLeft = true) { Joint joints[JointType_Count]; n_body->GetJoints(JointType::JointType_Count, joints); int elbow = JointType_ElbowRight; int hand = JointType_HandRight; if (joints[hand].Position.Y > joints[elbow].Position.Y) { return true; } else { return false; } } }; int main() { IKinectSensor *kinect = NULL; HRESULT hr = S_OK; hr = GetDefaultKinectSensor(&kinect); // 得到默认的设备 if (FAILED(hr) || kinect == NULL) { cout << "创建 sensor 失败\n"; return -1; } if (kinect->Open() != S_OK) // 是否打开成功 { cout << "Kinect sensor 没准备好\n"; return -1; } IBodyFrameSource *bady = nullptr; // 获取源 hr = kinect->get_BodyFrameSource(&bady); IBodyFrameReader *pBodyReader; hr = bady->OpenReader(&pBodyReader); // 打开获取骨骼信息的 Reader if (FAILED(hr)){ std::cerr << "Error : IBodyFrameSource::OpenReader()" << std::endl; return -1; } cout << "开始检测\n"; GestureDetection gesture_detection(0.05, 5, 5); while (1) { IBodyFrame* pBodyFrame = nullptr; hr = pBodyReader->AcquireLatestFrame(&pBodyFrame); if (SUCCEEDED(hr)){ IBody* pBody[BODY_COUNT] = { 0 }; // 默认的是 6 个骨骼 ,初始化所有的骨骼信息 //更新骨骼数据 hr = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, pBody); // 刷新骨骼信息(6个) if (SUCCEEDED(hr)) { BOOLEAN bTracked = false; for (int i = 0; i < 6; i++) { hr = pBody[i]->get_IsTracked(&bTracked); // 检查是否被追踪 if (SUCCEEDED(hr) && bTracked) { gesture_detection.Update(pBody[i]); } } } for (int count = 0; count < BODY_COUNT; count++){ SafeRelease(pBody[count]); } } if (CTRL == 1) { break; // 识别成功以后 跳出识别程序 } SafeRelease(pBodyFrame); // 别忘了释放 } kinect->Close(); // 关闭设备 system("pause"); return 0; }
相关文章推荐
- c++作业4
- 我的第四次C++作业
- C语言里static的应用
- C语言之结构体内存对齐
- C++调用windows API
- OC语言,逻辑性的模拟通讯录,大家可以作参考
- C++ 类的保护继承与构造函数
- c++语言const关键字
- 实际问题与C语言会擦出什么的火花
- C++DLL导出类(快排,堆排,插入排序,选择排序,冒泡排序)
- c++作业4
- 在Dev C++中制作和使用静态链接库
- 编译原理:C语言词法分析器
- C++的几个输入函数
- 第5周 经典小程序2题 C语言实现的猜拳游戏(剪子锤子布)
- c++ bitset类用法
- C和C++混合编程FAQ
- C语言变量存储类型
- C语言简单键盘扫描,可用于简单小游戏
- c++第四次作业