Kinect For Windows V2開發日志五:使用OpenCV顯示彩色圖像及紅外圖像


# 彩色圖像 ```CPP #include #include #include

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位,因此這樣的推論應該是正確的。





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM