跳至主要內容

windows10环境下使用Kinect2.0获取RGB-D图片

yczha大约 3 分钟windows操作系统windowskinect

摘要:这篇文章介绍如何在Windows10环境下使用C++程序驱动Kinect2.0获取RGB-D图片

  • STEP 1 :安装Kinect2.0 SDK

    Kinect2.0设备需要使用usb3.0接口,所以,首先要保证你接入的接口一定是USB3.0!

    接下来,在官网上下载Kinect2.0的SDK :

    https://www.microsoft.com/en-hk/download/confirmation.aspx?id=44561

    下载之后安装,安装完成后会有一个Kinect2.0 SDK和一个Kinect2.0 Studio

    将Kinect2.0设备连接到电脑上,然后打开Kinect2.0 Studio,这时可看到Kinect2.0摄像头的实时镜头照片,表示Kinect2.0安装完成。

  • STEP 2 :获取RGB-D图像

    Kinect2.0 Studio能看到实时的图像,但是没法保存下来,要保存Kinect2.0的照片需要我们调用其SDK来编程获得。

    我们这里使用VS2013+Kinect2.0 SDK 环境来编写代码。

    • 配置Kinect2.0 SDK的开发环境

      安装好Kinect2.0 SDK之后要在VS2013工程环境中使用还需要配置。

      • 新建一个x86的VS2013的工程,注意,楼主这里使用x64 工程时Kinect2.0 SDK出错,因而建议使用x86工程
      • 配置工程:
        • 包含目录下添加:***\Microsoft SDKs\Kinect\v2.0_1409\inc ,这里***代表你的实际安装地址
        • 库目录下添加***\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86
        • 附加依赖项 里添加kinect20.lib
    • 编写代码获取Kinect2.0设备的图像

      #include <kinect.h>
      #include <iostream>
      #include <opencv2\opencv.hpp>
      #include <opencv2/core/core.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 GetPicture()
      {
      	// 获取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_ir(424, 512, CV_16UC1);
      
      	UINT16 *depthData = new UINT16[424 * 512];
      	IMultiSourceFrame* m_pMultiFrame = nullptr;
      	int sample_id = 1;
      	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_depth.data));
      		}
      
      		// infrared拷贝到图片中
      		if (SUCCEEDED(hr))
      		{
      			hr = m_pInfraredFrame->CopyFrameDataToArray(424 * 512, reinterpret_cast<UINT16*>(i_ir.data));
      		}
      
      		// 显示
      		imshow("rgb", i_rgb);
      		if (waitKey(1) == VK_ESCAPE)
      			break;
      		imshow("depth", i_depth);
      		if (waitKey(1) == VK_ESCAPE)
      			break;
      		imshow("ir", i_ir);
      		if (waitKey(1) == VK_ESCAPE)
      			break;
      		//waitKey(0);
      		/*string s1 = "C:\\Users\\mataiyuan\\Desktop\\yooongchun\\dataset\\sample-";
      		string s2 = "-rgb.png";
      		string s3 = "-depth.png";
      		string s4 = "-infrared.png";
      		cvSaveImage((s1 + to_string(sample_id) + s2).c_str(), &IplImage(i_rgb));
      		cvSaveImage((s1 + to_string(sample_id) + s3).c_str(), &IplImage(i_depth));
      		cvSaveImage((s1 + to_string(sample_id) + s4).c_str(), &IplImage(i_ir));
      		sample_id += 1;*/
      
      		// 释放资源
      		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();
      }
      int main()
      {
      	GetPicture();
      	std::system("pause");
      	return 0;
      }
      

完成!