kinect 2.0 SDK學習筆記(一)--獲得原始數據

工程配置

包含目錄加上:
$(KINECTSDK20_DIR)\inc;
庫目錄加上:
$(KINECTSDK20_DIR)\lib\x64;(注意選擇x64/x86)

其中KINECTSDK20_DIR是安裝kinect SDK時的安裝目錄,比如我的是
C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\

六種數據源

Kinect Data Sources – 6種數據源
1. ColorFrameSource
彩色圖
2. InfraredFrameSource
紅外圖(16-bit)
3. DepthFrameSource
深度圖(16-bit,單位:mm)
kinect採的深度數據是short型,即每個像素深度佔2個字節,但是16位中只有12位是有用的,2^12 = 4096,單位是毫米,所以範圍是4m
4. BodyIndexFrameSource
人物索引圖(用一個字節代表人體,最多支持6個人體)
5. BodyFrameSource
人體關節圖
6. AudioSource
聲音

流程

Kinect v2中獲取並處理數據源接口步驟如下:
Sensor -> Source -> Reader -> Frame -> Data
- 單數據源的獲取:
1. 獲取kinect

IKinectSensor* m_pKinectSensor;  
HRESULT hr;
hr = GetDefaultKinectSensor(&m_pKinectSensor);
hr = m_pKinectSensor->Open();
  1. 顯示數據源的源數據併爲閱讀器(readers)提供途徑、爲傳感器每個數據提供一種數據源。
hr = m_pKinectSensor->get_ColorFrameSource(&pColorFrameSource);
  1. 提供獲取幀的途徑(事件機制、輪詢機制)。
hr = pColorFrameSource->OpenReader(&m_pColorFrameReader);
  1. 發送幀事件參數,獲取最近一幀的數據。
hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame);
  • 多數據源獲取:
    1. 與上面的1.相同
    2. 獲取多數據源到讀取器
IMultiSourceFrameReader* m_pMultiFrameReader;
hr = m_pKinectSensor->OpenMultiSourceFrameReader(
    FrameSourceTypes::FrameSourceTypes_Color |
    FrameSourceTypes::FrameSourceTypes_Infrared |
    FrameSourceTypes::FrameSourceTypes_Depth, 
    &m_pMultiFrameReader);
  1. 獲取多源數據幀
hr = m_pMultiFrameReader->AcquireLatestFrame(&m_pMultiFrame);
  1. 從多源數據幀中分離出各個數據源
hr = m_pMultiFrame->get_ColorFrameReference(&m_pColorFrameReference);
hr = m_pColorFrameReference->AcquireFrame(&m_pColorFrame);

兩種方式最後都能獲得你想要的數據幀,並對其進行操作

例子

  • opencv顯示原始的彩色,深度,紅外數據
#include "kinect.h"
#include <iostream>
#include <opencv2/core/core.hpp>  
#include <opencv2\opencv.hpp>
#include <opencv2/highgui/highgui.hpp>  
using namespace cv;
using namespace std;

// 安全釋放指針
template<class Interface>
inline void SafeRelease(Interface *& pInterfaceToRelease)
{
    if (pInterfaceToRelease != NULL)
    {
        pInterfaceToRelease->Release();
        pInterfaceToRelease = NULL;
    }
}

int main()
{
    // 獲取Kinect設備
    IKinectSensor* m_pKinectSensor;
    HRESULT hr;
    hr = GetDefaultKinectSensor(&m_pKinectSensor);
    if (FAILED(hr))
    {
        return hr;
    }

    IMultiSourceFrameReader* m_pMultiFrameReader;
    if (m_pKinectSensor)
    {
        hr = m_pKinectSensor->Open();
        if (SUCCEEDED(hr))
        {
            // 獲取多數據源到讀取器  
            hr = m_pKinectSensor->OpenMultiSourceFrameReader(
                FrameSourceTypes::FrameSourceTypes_Color |
                FrameSourceTypes::FrameSourceTypes_Infrared |
                FrameSourceTypes::FrameSourceTypes_Depth,
                &m_pMultiFrameReader);
        }
    }

    if (!m_pKinectSensor || FAILED(hr))
    {
        return E_FAIL;
    }
    // 三個數據幀及引用
    IDepthFrameReference* m_pDepthFrameReference;
    IColorFrameReference* m_pColorFrameReference;
    IInfraredFrameReference* m_pInfraredFrameReference;
    IInfraredFrame* m_pInfraredFrame;
    IDepthFrame* m_pDepthFrame;
    IColorFrame* m_pColorFrame;
    // 三個圖片格式
    Mat i_rgb(1080, 1920, CV_8UC4);      //注意:這裏必須爲4通道的圖,Kinect的數據只能以Bgra格式傳出
    Mat i_depth(424, 512, CV_8UC1);
    Mat i_src_depth(424, 512, CV_16UC1);
    Mat i_ir(424, 512, CV_16UC1);

    UINT16 *depthData = new UINT16[424 * 512];
    IMultiSourceFrame* m_pMultiFrame = nullptr;
    while (true)
    {
        // 獲取新的一個多源數據幀
        hr = m_pMultiFrameReader->AcquireLatestFrame(&m_pMultiFrame);
        if (FAILED(hr) || !m_pMultiFrame)
        {
            //cout << "!!!" << endl;
            continue;
        }

        // 從多源數據幀中分離出彩色數據,深度數據和紅外數據
        if (SUCCEEDED(hr))
            hr = m_pMultiFrame->get_ColorFrameReference(&m_pColorFrameReference);
        if (SUCCEEDED(hr))
            hr = m_pColorFrameReference->AcquireFrame(&m_pColorFrame);
        if (SUCCEEDED(hr))
            hr = m_pMultiFrame->get_DepthFrameReference(&m_pDepthFrameReference);
        if (SUCCEEDED(hr))
            hr = m_pDepthFrameReference->AcquireFrame(&m_pDepthFrame);
        if (SUCCEEDED(hr))
            hr = m_pMultiFrame->get_InfraredFrameReference(&m_pInfraredFrameReference);
        if (SUCCEEDED(hr))
            hr = m_pInfraredFrameReference->AcquireFrame(&m_pInfraredFrame);

        // color拷貝到圖片中
        UINT nColorBufferSize = 1920 * 1080 * 4;
        if (SUCCEEDED(hr))
            hr = m_pColorFrame->CopyConvertedFrameDataToArray(nColorBufferSize, reinterpret_cast<BYTE*>(i_rgb.data), ColorImageFormat::ColorImageFormat_Bgra);

        // depth拷貝到圖片中
        if (SUCCEEDED(hr))
        {
            hr = m_pDepthFrame->CopyFrameDataToArray(424 * 512, depthData);
            //for (int i = 0; i < 512 * 424; i++)
            //{
            //  // 0-255深度圖,爲了顯示明顯,只取深度數據的低8位
            //  BYTE intensity = static_cast<BYTE>(depthData[i] % 256);
            //  reinterpret_cast<BYTE*>(i_depth.data)[i] = intensity;
            //}

            // 實際是16位unsigned int數據
            hr = m_pDepthFrame->CopyFrameDataToArray(424 * 512, reinterpret_cast<UINT16*>(i_src_depth.data));
        }

        // infrared拷貝到圖片中
        if (SUCCEEDED(hr))
        {
            hr = m_pInfraredFrame->CopyFrameDataToArray(424 * 512, reinterpret_cast<UINT16*>(i_ir.data));
        }

        Mat i_rgb_resize = i_rgb.clone();       // 縮小方便看
        cv::resize(i_rgb_resize, i_rgb_resize,Size(512, 424));
        // 顯示
        imshow("rgb", i_rgb_resize);
        if (waitKey(1) == VK_ESCAPE)
            break;
        imshow("i_src_depth", i_src_depth);
        if (waitKey(1) == VK_ESCAPE)
            break;
        imshow("ir", i_ir);
        if (waitKey(1) == VK_ESCAPE)
            break;

        // 釋放資源
        SafeRelease(m_pColorFrame);
        SafeRelease(m_pDepthFrame);
        SafeRelease(m_pInfraredFrame);
        SafeRelease(m_pColorFrameReference);
        SafeRelease(m_pDepthFrameReference);
        SafeRelease(m_pInfraredFrameReference);
        SafeRelease(m_pMultiFrame);
    }
    // 關閉窗口,設備
    cv::destroyAllWindows();
    m_pKinectSensor->Close();
    std::system("pause");
    return 0;
}

效果如下:

發佈了19 篇原創文章 · 獲贊 57 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章