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












留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題