代码示例:
#include#include #include using namespace std;using namespace cv;int main(void){ IKinectSensor * mySensor = nullptr; GetDefaultKinectSensor(&mySensor); //获取感应器 mySensor->Open(); //打开感应器 IDepthFrameSource * mySource = nullptr; //取得深度数据 mySensor->get_DepthFrameSource(&mySource); int height = 0, width = 0; IFrameDescription * myDescription = nullptr; //取得深度数据的分辨率 mySource->get_FrameDescription(&myDescription); myDescription->get_Height(&height); myDescription->get_Width(&width); myDescription->Release(); IDepthFrameReader * myReader = nullptr; mySource->OpenReader(&myReader); //打开深度数据的Reader IDepthFrame * myFrame = nullptr; Mat temp(height,width,CV_16UC1); //建立图像矩阵 Mat img(height,width,CV_8UC1); while (1) { if (myReader->AcquireLatestFrame(&myFrame) == S_OK) //通过Reader尝试获取最新的一帧深度数据,放入深度帧中,并判断是否成功获取 { myFrame->CopyFrameDataToArray(height * width, (UINT16 *)temp.data); //先把数据存入16位的图像矩阵中 temp.convertTo(img,CV_8UC1,255.0 / 4500); //再把16位转换为8位 imshow("TEST", img); myFrame->Release(); } if (waitKey(30) == VK_ESCAPE) break; } myReader->Release(); //释放不用的变量并且关闭感应器 mySource->Release(); mySensor->Close(); mySensor->Release(); return 0;}
详细解释
为了简便起见,此段代码同样略掉了大部分错误检测。不难看出此段代码于非常相似,主要区别在循环里。
首先,声明了两个矩阵,一个为16位单通道,一个为8位单通道,之所以开16位的,是因为在这篇里可以看到,深度数据是16位的。开8位的原因等下说。然后同样的,利用AcquireLatestFrame()
来获取最新的一帧,不同的是下面一句,不再用AccessUnderlyingBuffer()
,而是用CopyFrameDataToArray
来把数据复制到openCV的图像矩阵Mat里,注意第三个参数的类型是UINT16*
,所以需要强制转换一下。接下来要把16位的Mat转换成8位来输出显示,为什么不直接用16位?其实也可以用,但是直接用16位的话显示的图像很接接近于全黑,不方便观察,于是转换为8位。convertTo()
这个函数的第一个参数是输出矩阵,第二个是转换的类型,第三个是缩放因子,其中4500是深度数据的最大距离。
最后,输出的图像应该像这样: