kinect 2.0 SDK學習筆記(一)--獲得原始資料
阿新 • • 發佈:2019-02-13
工程配置
包含目錄加上:
$(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();
- 顯示資料來源的源資料併為閱讀器(readers)提供途徑、為感測器每個資料提供一種資料來源。
hr = m_pKinectSensor->get_ColorFrameSource(&pColorFrameSource);
- 提供獲取幀的途徑(事件機制、輪詢機制)。
hr = pColorFrameSource->OpenReader(&m_pColorFrameReader);
- 傳送幀事件引數,獲取最近一幀的資料。
hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame);
- 多資料來源獲取:
- 與上面的1.相同
- 獲取多資料來源到讀取器
IMultiSourceFrameReader* m_pMultiFrameReader;
hr = m_pKinectSensor->OpenMultiSourceFrameReader(
FrameSourceTypes::FrameSourceTypes_Color |
FrameSourceTypes::FrameSourceTypes_Infrared |
FrameSourceTypes::FrameSourceTypes_Depth,
&m_pMultiFrameReader);
- 獲取多源資料幀
hr = m_pMultiFrameReader->AcquireLatestFrame(&m_pMultiFrame);
- 從多源資料幀中分離出各個資料來源
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;
}
效果如下: