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 <opencv2highgui.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位,因此这样的推论应该是正确的。