Kinect V2 _ 數據源處理及獲得統整_獲取特定骨節點數據
先備知識
Kinect V2 在Windows Form 上的配置教學_秀彩色影像_L1
link : http://coolmandiary.blogspot.tw/2016/04/kinect-v2-windows-form.html
KinectV2_骨節點_分析
再度開啟Kinect_深度影像分析
link : http://coolmandiary.blogspot.tw/2016/06/kinect.html
【程式碼】
//Standard Library
#include <iostream>
#include <stdio.h>
//OpenCV Header
#include <opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\video\background_segm.hpp>
using namespace cv;
using namespace std;
// Kinect for Windows SDK Header
#include <Kinect.h>
const string get_name(int n); //判斷關節的名字
int main( )
{
/*
(1) 取得 Sensor
(2)選擇你所要讀取的資料源(data source) / Select the data source to read from
(3)處理從資料源讀取到的資料 / Handle the data you read from the source
*/
//取得預設傳感器並開啟
IKinectSensor * mySensor = nullptr;
GetDefaultKinectSensor(&mySensor);
mySensor->Open();
//一個關於Kinect V2觀念 : 不同種數據會搭配兩個項目(源、閱讀器) IBody , IDepth , IColor .....etc
//一個xxxFrameSource(源)
//一個xxxFrameReader(閱讀器)
//處理三步驟
/*
從「傳感器」獲得「源」
從「源」打開「閱讀器」
從「閱讀器」獲得「視訊幀(frame)」
*/
int myBodyCount = 0;
IBodyFrameSource * myBodySource = nullptr;//一個IBodyFrameSource(身體數據源)
IBodyFrameReader * myBodyReader = nullptr;//一個IBodyFrameReader(身體閱讀器)
//從「傳感器」獲得「身體數據源」..................................................................................step1_1
mySensor->get_BodyFrameSource(&myBodySource);
//從「身體數據源」打開「身體閱讀器」..............................................................................step1_2
myBodySource->OpenReader(&myBodyReader);
myBodySource->get_BodyCount(&myBodyCount);// 取得預設微軟限定的遍歷6人的bodyCount
IDepthFrameSource * myDepthSource = nullptr;//一個IDepthFrameSource(深度數據源)
IDepthFrameReader * myDepthReader = nullptr;//一個IDepthFrameReader(深度閱讀器)
//從「傳感器」獲得「深度數據源」..................................................................................step2_1
mySensor->get_DepthFrameSource(&myDepthSource);
//從「深度數據源」打開「深度閱讀器」..............................................................................step2_2
myDepthSource->OpenReader(&myDepthReader);
int height = 0, width = 0;
IFrameDescription * myDescription = nullptr;;
myDepthSource->get_FrameDescription(&myDescription);
myDescription->get_Height(&height);
myDescription->get_Width(&width); //以上為準備好深度數據和骨骼數據的Reader
IBodyFrame * myBodyFrame = nullptr;
IDepthFrame * myDepthFrame = nullptr;
Mat img16(height, width, CV_16UC1); //為顯示深度影像做準備
Mat img8(height, width, CV_8UC1);
while (1)
{
//從「身體閱讀器」獲得「身體視訊幀(frame)」//..............................................step1_3
while (myBodyReader->AcquireLatestFrame(&myBodyFrame) != S_OK);
//從「深度閱讀器」獲得「深度視訊幀(frame)」//..............................................step2_3
while (myDepthReader->AcquireLatestFrame(&myDepthFrame) != S_OK);
myDepthFrame->CopyFrameDataToArray(width * height, (UINT16 *)img16.data);
img16.convertTo(img8, CV_8UC1, 255.0 / 4500);
imshow("Depth Img", img8); //深度圖像的轉換及顯示
int myBodyCount = 0;
//寫法一.一行搞定
IBody ** bodyArr = new IBody*[myBodyCount];
//寫法二.兩行寫法
//IBody ** bodyArr = nullptr;
//bodyArr = new IBody *[myBodyCount];
//bodyArr 就是之後讓 K4W SDK v2 紀錄骨架資料的陣列
myBodySource->get_BodyCount(&myBodyCount);//取得攝影機捕捉到的人體總數
for (int i = 0; i < myBodyCount; i++) //bodyArr的初始化
bodyArr[i] = nullptr;
myBodyFrame->GetAndRefreshBodyData(myBodyCount, bodyArr);
for (int i = 0; i < myBodyCount; i++) //遍歷6個人
{
BOOLEAN result = false;
if (bodyArr[i]->get_IsTracked(&result) == S_OK && result) //判断此人是否被偵測到
{
cout << "Body " << i << " tracked!" << endl;
int count = 0;
Joint jointArr[JointType_Count];
//「JointType_Count」,來代表總共的關節數目
bodyArr[i]->GetJoints(JointType_Count, jointArr); //獲取此人的關節數據
for (int j = 0; j < JointType_Count; j++)
{
if (jointArr[j].TrackingState != TrackingState_Tracked) //將確定偵測到的關節顯示出來
continue;
string rt = get_name(jointArr[j].JointType); //獲取關節的名字
if (rt != "NULL") //輸出關節信息
{
count++;
cout << " " << rt << " tracked" << endl;
if (rt == "脖子")
cout << " 脖子座標: " << jointArr[j].Position.X << "," << jointArr[j].Position.Y << "," << jointArr[j].Position.Z << endl;
if (rt == "肩膀中央")
cout << " 肩膀中央座標: " << jointArr[j].Position.X << "," << jointArr[j].Position.Y << "," << jointArr[j].Position.Z << endl;
if (rt == "左肩膀")
cout << " 左肩膀座標: " << jointArr[j].Position.X << "," << jointArr[j].Position.Y << "," << jointArr[j].Position.Z << endl;
if (rt == "右肩膀")
cout << " 右肩膀座標: " << jointArr[j].Position.X << "," << jointArr[j].Position.Y << "," << jointArr[j].Position.Z << endl;
if (rt == "脊椎中央")
cout << " 脊椎中央座標: " << jointArr[j].Position.X << "," << jointArr[j].Position.Y << "," << jointArr[j].Position.Z << endl;
}
}
cout << count << " joints tracked" << endl << endl;
}
}
myDepthFrame->Release();
myBodyFrame->Release();
delete[] bodyArr;
if (waitKey(30) == VK_ESCAPE)
break;
//Sleep(1000); //每秒鐘更新一次, 放慢速度用
}
myBodyReader->Release();
myDepthReader->Release();
myBodySource->Release();
myDepthSource->Release();
mySensor->Close();
mySensor->Release();
return 0;
}
const string get_name(int n)
{
switch (n)
{
case 2:
return "脖子";
break;
case 20:
return "肩膀中央";
break;
case 4:
return "左肩膀";
break;
case 8:
return "右肩膀";
break;
case 1:
return "脊椎中央";
break;
default:return "NULL";
}
}
留言
張貼留言