using namespace std;
using namespace cv;
int main(void)
{
IKinectSensor * mySensor = nullptr; //第1步打開Sensor
GetDefaultKinectSensor(&mySensor);
mySensor->Open();
IColorFrameSource * mySource = nullptr; //第2步獲取Source
mySensor->get_ColorFrameSource(&mySource);
int height = 0, width = 0; //取得寬和高等下用
IFrameDescription * myDescription = nullptr;
mySource->get_FrameDescription(&myDescription);
myDescription->get_Height(&height);
myDescription->get_Width(&width);
IColorFrameReader * myReader = nullptr; //第3步打開Reader
mySource->OpenReader(&myReader);
Mat img(height,width,CV_8UC4);
IColorFrame * myFrame = nullptr;
while (1)
{
if (myReader->AcquireLatestFrame(&myFrame) == S_OK) //第4步獲取Frame
{
UINT size = 0;
myFrame->CopyConvertedFrameDataToArray(width * height * 4,(BYTE *)img.data,ColorImageFormat_Bgra);
imshow("TEST",img);
myFrame->Release();
}
if (waitKey(30) == VK_ESCAPE)
break;
}
myReader->Release(); //記得要釋放
myDescription->Release();
mySource->Release();
mySensor->Close();
mySensor->Release();
return 0;
}
- - -
## 詳細解釋:
讀取彩色圖像的步驟和讀取深度圖像的是一樣的,區別在於數據輸出的處理上。Kinect V2使用的圖像格式是YUY2,不太好處理,好在彩色幀自帶了一個轉換函數`CopyConvertedFrameDataToArray()`,它的:
- 第一個參數是所需的大小
- 第二個參數是目標數組
- 第三個參數是要轉換的格式,其中第三個參數的類型可以在[這里](https://msdn.microsoft.com/en-us/library/microsoft.kinect.kinect.colorimageformat.aspx)找到。
第一個參數的大小為圖像的長乘上寬再乘上4個通道。
因為我們要轉成RGB,但是枚舉量里帶RGB的都還有一個A,這個A代表的是透明度,成了`RGBA`,所以開Mat時要開成四通道的(另外選8位而不選16位的原因我個人理解是,那個轉換函數第二個參數要求類型是`BYTE`,而一個`BYTE`是8位的)。
令我費解的是,`Rgba`和`Bgra`只是通道的順序不同,混合出來的效果應該是一樣的,但是如果選用`Rgba`,顯示出來的顏色就不正確。懂了以后更新。<font color=red>(更新:原來OpenCV在使用數據時,不是簡單的把輸入的三種顏色疊加,而是把輸入的值當成對應的顏色的值,然后疊加這些值,OpenCV用的顏色模式是BGR,所以RGB中R的量就成了B的量,B的量就成了R的量,因此顯示出的圖像色彩就不對了)。</font>
- - -
# 紅外圖像
```CPP
#include <iostream>
#include <Kinect.h>
#include <opencv2\highgui.hpp>
using namespace std;
using namespace cv;
int main(void)
{
IKinectSensor * mySensor = nullptr; //第1步打開Sensor
GetDefaultKinectSensor(&mySensor);
mySensor->Open();
IInfraredFrameSource * mySource = nullptr; //第2步獲取Source
mySensor->get_InfraredFrameSource(&mySource);
int height = 0, width = 0; //取得寬和高等下用
IFrameDescription * myDescription = nullptr;
mySource->get_FrameDescription(&myDescription);
myDescription->get_Height(&height);
myDescription->get_Width(&width);
IInfraredFrameReader * myReader = nullptr; //第3步打開Reader
mySource->OpenReader(&myReader);
Mat img(height,width,CV_16UC1);
IInfraredFrame * myFrame = nullptr;
while (1)
{
if (myReader->AcquireLatestFrame(&myFrame) == S_OK) //第4步獲取Frame
{
myFrame->CopyFrameDataToArray(height * width,(UINT16 *)img.data);
imshow("TEST",img);
myFrame->Release();
}
if (waitKey(30) == VK_ESCAPE)
break;
}
myReader->Release(); //記得要釋放
myDescription->Release();
mySource->Release();
mySensor->Close();
mySensor->Release();
return 0;
}
詳細解釋
可見此段代碼於上一段幾乎一樣,只是輸出數據時換個函數就行了,Mat開16位是因為CopyFrameDataToArray()
中第2個參數指定16位,因此這樣的推論應該是正確的。