转载至:https://www.parful.com/blog/article/110
在开始学习这篇教程前,你首先需要了解如何利用VGB工具制作一个后缀名为 .gba 或 .gbd 的姿势数据库文件。如果没有此基础,请按顺序阅读:
- Kinect for windows v2 姿势识别工具之 Kinect Studio 的使用
- Kinect for windows v2 姿势识别工具之 Visual Gesture Builder的使用
- Kinect for windows v2 姿势识别工具之 连续性动作检测
开发你自己的第一个 Kinect Gestrue 匹配程序
你需要在你的vs项目中设置好 包含目录 及 库目录,包含目录为 Kinect 安装目录下的 inc 目录,库目录在 Kinect 安装目录下的 Lib 文件夹中(包含 x64 x86,请选择你需要的版本)。
#include "Kinect.h"
#include "Kinect.VisualGestureBuilder.h"
#pragma comment(lib,"Kinect20.lib")
#pragma comment(lib,"Kinect20.VisualGestureBuilder.lib")
IKinectSensor* pSensor = nullptr;
if (GetDefaultKinectSensor(&pSensor) != S_OK)
{
return 1;
}
pSensor->Open();
读取 gesture 数据库
wstring gestureDatabasePath = L"Seat.gbd";
IVisualGestureBuilderDatabase* pGestureDatabase = nullptr;
if (CreateVisualGestureBuilderDatabaseInstanceFromFile(gestureDatabasePath.c_str(), &pGestureDatabase)!=S_OK)
{
wcout << "Can not read the database, Please check if it exit!" << endl;
return 1;
}
获取 gesture 数据库中 gesture 数量 及 gesture 信息
UINT numGesture = 0;
//Get how many gestures in database
pGestureDatabase->get_AvailableGesturesCount(&numGesture);
wcout << "Total gesture count:" << numGesture << endl;
//Get the list of gestures
IGesture** gestureList = new IGesture*[numGesture];
pGestureDatabase->get_AvailableGestures(numGesture, gestureList);
//GestureType enum
GestureType gestureType;
wchar_t gestureName[300];
for (int index = 0; index < numGesture; ++index)
{
if (gestureList[index]->get_GestureType(&gestureType) == S_OK)
{
if (gestureType == GestureType::GestureType_Discrete)
{
//Get discrete gesture name
gestureList[index]->get_Name(300, gestureName);
wcout << "discrete_gesture_" << index << "_name:" << gestureName << endl;
}
else if (gestureType == GestureType::GestureType_Continuous)
{
//Get continuous gesture name
gestureList[index]->get_Name(300, gestureName);
wcout << "continuous_gesture_" << index << "_name" << gestureName << endl;
}
}
}
一个数据流对应一个流的读取器,体感最大可以同时检测到6个body数据(numBody=6).为了实现同时检测多人的姿势,所以此处创建6个gesture流与6个gesture流的读取器
IVisualGestureBuilderFrameSource** gestureSources = new IVisualGestureBuilderFrameSource*[numBody];
IVisualGestureBuilderFrameReader** gestureReaders = new IVisualGestureBuilderFrameReader*[numBody];
for (int bodyIndex = 0; bodyIndex < numBody; ++bodyIndex)
{
CreateVisualGestureBuilderFrameSource(pSensor, bodyIndex, &gestureSources[bodyIndex]);
gestureSources[bodyIndex]->AddGestures(numGesture, gestureList);
gestureSources[bodyIndex]->OpenReader(&gestureReaders[bodyIndex]);
}
IBodyFrame* pFrame = nullptr;
//Gets the latest frame.
if (pFrameReader->AcquireLatestFrame(&pFrame) == S_OK)
{
//for each frame, update the body data
if (pFrame->GetAndRefreshBodyData(numBody, bodies) == S_OK)
{
for (int bodyIndex = 0; bodyIndex < numBody; ++bodyIndex)
{
BOOLEAN tracked = false;
IBody* pBody = bodies[bodyIndex];
//has tracked body
if (pBody->get_IsTracked(&tracked) == S_OK&&tracked)
{
//Process body
}
}
}
pFrame->Release();
}
UINT64 trackingId = 0;
if (pBody->get_TrackingId(&trackingId) == S_OK)
{
UINT64 gestureId = 0;
if (gestureSources[bodyIndex]->get_TrackingId(&gestureId) == S_OK)
{
if (gestureId != trackingId)
{
//Bind tracking ID
gestureSources[bodyIndex]->put_TrackingId(trackingId);
wcout << "Gesture Source " << bodyIndex << " start to track user " << trackingId << endl;
}
}
}
最后获取到的结果有两种可能,IDiscreteGestureResult(离散型姿势结果) 与 IContinuousGestureResult(连续型姿势结果)。
- IDicreteGestureResult可获取的结果为一个 BOOLEAN 变量,当离散型姿势匹配成功时,伴有一个值为 float 的 confidence(值为 0-1)。
- IContinuousGestureResult可获取的结果是一个 float 变量,值为 0-1 代表该连续动作的进度值,这个值是一直存在的。
IVisualGestureBuilderFrame* pGestureFrame = nullptr;
//Get latest frame
if (gestureReaders[bodyIndex]->CalculateAndAcquireLatestFrame(&pGestureFrame) == S_OK)
{
BOOLEAN bGestureTracked = false;
if (pGestureFrame->get_IsTrackingIdValid(&bGestureTracked) == S_OK&&bGestureTracked)
{
for (UINT gestureIndex = 0; gestureIndex < numGesture; ++gestureIndex)
{
GestureType gestureType;
gestureList[gestureIndex]->get_GestureType(&gestureType);
wchar_t gestureName[260];
gestureList[gestureIndex]->get_Name(260, gestureName);
//Discrete gesture
if (gestureType == GestureType::GestureType_Discrete)
{
IDiscreteGestureResult* pGestureResult = nullptr;
if (pGestureFrame->get_DiscreteGestureResult(gestureList[gestureIndex], &pGestureResult) == S_OK)
{
BOOLEAN detected = false;
if (pGestureResult->get_Detected(&detected) == S_OK&&detected)
{
float confidence = 0.0f;
pGestureResult->get_Confidence(&confidence);
wcout <<gestureName<<"-Confidence:" << confidence<<endl;
pGestureResult->Release();
}
}
} //Continuous gesture
else if (gestureType == GestureType::GestureType_Continuous)
{
IContinuousGestureResult* pGestureResult = nullptr;
if (pGestureFrame->get_ContinuousGestureResult(gestureList[gestureIndex], &pGestureResult) == S_OK)
{
float progress = 0.0f;
if (pGestureResult->get_Progress(&progress) == S_OK)
{
wcout << gestureName << "-progress:" << progress << endl;
}
pGestureResult->Release();
}
}
}
}
pGestureFrame->Release();
}
-
完整代码下载请移步原文处:https://www.parful.com/blog/article/110