zoukankan      html  css  js  c++  java
  • Kinect for Windows V2和V1对照开发___深度数据获取并用OpenCV2.4.10显示

    V1深度分辨率:320x240

    V2深度分辨率:512x424


    1。  打开深度图像帧的方式

    对于V1:

    hr = m_PNuiSensor->NuiImageStreamOpen(
                                       NUI_IMAGE_TYPE_DEPTH,NUI_IMAGE_RESOLUTION_320x240,0, 2,
                                       m_hNextDepthFrameEvent, &m_hDepthStreamHandle);
                              if( FAILED( hr ) )
                              {
                                       cout<<"Could notopen image stream video"<<endl;
                                       return hr;
                        }
    这样的方式能够设置分辨率

    对于V2:     

    // Initialize the Kinect and get the depth reader
            IDepthFrameSource* pDepthFrameSource =NULL;
    首先使用        hr = m_pKinectSensor->Open();//打开Kinect 
            if (SUCCEEDED(hr))
            {
              hr =m_pKinectSensor->get_DepthFrameSource(&pDepthFrameSource);
            }
    方法get_DepthFrameSource打开深度帧的源。

    然后使用 if (SUCCEEDED(hr)) { hr =pDepthFrameSource->OpenReader(&m_pDepthFrameReader); } SafeRelease(pDepthFrameSource); 方法OpenReader打开深度帧读取器。

     

    2,   更新深度帧的方式

    对于V1:使用NuiImageStreamGetNextFrame方法

    NuiImageStreamGetNextFrame(m_hDepthStreamHandle,0, &pImageFrame);;//得到该帧数据</span>

    对于V2:使用AcquireLatestFrame方法

       

     if (!m_pDepthFrameReader)
        {
            return;
        }
     
        IDepthFrame* pDepthFrame = NULL;
     
        HRESULT hr =m_pDepthFrameReader->AcquireLatestFrame(&pDepthFrame);

    3,  数据的处理方式

    对于V1:这样的数据获取方式比較明朗看到数据内部结构,

    INuiFrameTexture *pTexture =pImageFrame->pFrameTexture;
                              NUI_LOCKED_RECT LockedRect;
                              pTexture->LockRect(0, &LockedRect,NULL, 0);
     
                              RGBQUAD q;
     
                              if( LockedRect.Pitch != 0 )
                              {
                                      
                                                //BYTE * pBuffer = (BYTE*)(LockedRect.pBits);
                                                //INT size =  LockedRect.size;
                                                //memcpy_s(m_pDepthBuffer,size, pBuffer, size);
                                                //USHORT* pBufferRun =reinterpret_cast<USHORT*>(m_pDepthBuffer);
                                       for (int i=0; i<image.rows; i++)
                                       {
                                       //USHORT* ptr = (USHORT*)depthIndexImage->height;
                                                //USHORT* pDepthRow =(USHORT*)(i);
                                                //BYTE * pBuffer = (BYTE*)(LockedRect.pBits);
                                                uchar *ptr =image.ptr<uchar>(i);  //第i行的指针
                                                uchar * pBuffer =(uchar*)(LockedRect.pBits)+i*LockedRect.Pitch;
                                                USHORT* pBufferRun =(USHORT*) pBuffer;//注意这里须要转换,由于每一个数据是2个字节,存储的同上面的颜色信息不一样,这里是2个字节一个信息,不能再用BYTE,转化为USHORT
     
                                                for (int j=0; j<image.cols; j++)
                                                {                                                  
                                                         //ptr[j] = 255 -(BYTE)(256*pBufferRun[j]/0x0fff);//直接将数据归一化处理
                                                         //ptr[j]  = pBufferRun[i * 640 + j];
                                                         // ptr[j] = 255 -(uchar)(256 * pBufferRun[j]/0x0fff);  //直接将数据归一化处理
                                       int player =pBufferRun[j]&7;  
                    int data =(pBufferRun[j]&0xfff8) >> 3;  
                      
                    uchar imageData = 255-(uchar)(256*data/0x0fff);  
                    q.rgbBlue = q.rgbGreen =q.rgbRed = 0;  
      
                    switch(player)  
                    {  
                        case 0:    
                            q.rgbRed = imageData /2;    
                            q.rgbBlue = imageData / 2;    
                            q.rgbGreen = imageData/ 2;    
                            break;    
                        case 1:     
                            q.rgbRed =imageData;    
                            break;    
                        case 2:    
                            q.rgbGreen =imageData;    
                            break;    
                        case 3:    
                            q.rgbRed = imageData /4;    
                            q.rgbGreen = q.rgbRed*4;  //这里利用乘的方法,而不用原来的方法能够避免不整除的情况  
                            q.rgbBlue =q.rgbRed*4;  //能够在后面的getTheContour()中配合使用,避免遗漏一些情况  
                            break;    
                        case 4:    
                            q.rgbBlue = imageData /4;   
                            q.rgbRed = q.rgbBlue*4;    
                            q.rgbGreen =q.rgbBlue*4;    
                            break;    
                        case 5:    
                            q.rgbGreen = imageData/ 4;   
                            q.rgbRed =q.rgbGreen*4;    
                            q.rgbBlue =q.rgbGreen*4;    
                            break;    
                        case 6:    
                            q.rgbRed = imageData /2;    
                            q.rgbGreen = imageData/ 2;     
                            q.rgbBlue =q.rgbGreen*2;    
                            break;    
                        case 7:    
                            q.rgbRed = 255 - (imageData / 2 );    
                            q.rgbGreen = 255 - (imageData / 2 );    
                            q.rgbBlue = 255 - (imageData / 2 );  
                    }     
                    ptr[3*j] = q.rgbBlue;  
                    ptr[3*j+1] = q.rgbGreen;  
                    ptr[3*j+2] = q.rgbRed;
                                                }
                                       }
                                      
                                       imshow("depthImage",image); //显示图像
    得到的终于形式能够用OpenCV显示。

    对于V2:


    RGBQUAD*  m_pDepthRGBX;;//深度数据存储位置
    m_pDepthRGBX(NULL)//构造函数初始化
        // create heap storage for color pixel data in RGBXformat
      m_pDepthRGBX = new RGBQUAD[cDepthWidth *cDepthHeight];
     
    //下边就是AcquireLatestFrame之后处理数据
            INT64 nTime = 0;
            IFrameDescription* pFrameDescription =NULL;
            int nWidth = 0;
            int nHeight = 0;
            USHORTnDepthMinReliableDistance = 0;
            USHORT nDepthMaxDistance =0;
            UINT nBufferSize = 0;
            UINT16 *pBuffer = NULL;
     
                   if (SUCCEEDED(hr))
            {
                hr =pDepthFrame->AccessUnderlyingBuffer(&nBufferSize, &pBuffer);           
            }
     
            if (SUCCEEDED(hr))
            {
                ProcessDepth(nTime, pBuffer,nWidth, nHeight, nDepthMinReliableDistance, nDepthMaxDistance);
            }

    4,OpenCV显示


    	int width = 0;
    	int height = 0;
    	pDescription->get_Width( &width ); // 512
    	pDescription->get_Height( &height ); // 424
    	unsigned int bufferSize = width * height * sizeof( unsigned short );
    
    	// Range
    	unsigned short min = 0;
    	unsigned short max = 0;
    	pDepthSource->get_DepthMinReliableDistance( &min ); // 500
    	pDepthSource->get_DepthMaxReliableDistance( &max ); // 4500
    	cout << "Range : " << min << " - " << max << std::endl;
    	
    	//创建尺寸为height x width 的1通道8位图像
    	Mat bufferMat( height, width, CV_16UC1 );
    	Mat depthMat( height, width, CV_8UC1 );
    
    	while( 1 ){
    		// 更新深度帧
    		IDepthFrame* pDepthFrame = nullptr;
    		hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );
    		if( SUCCEEDED( hResult ) ){
    			hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );
    			if( SUCCEEDED( hResult ) ){
    				bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f, 255.0f );
    			}
    		}
    		SafeRelease( pDepthFrame );
    
    		imshow( "Depth", depthMat );



    5。V2+VS2012+OpenCV代码


    #include <Windows.h>
    #include <Kinect.h>
    #include <opencv2/opencv.hpp>
    #include <cstdlib>
    
    using namespace std;
    using namespace cv;
    
    
    //释放接口须要自定义
    template<class Interface>
    inline void SafeRelease( Interface *& pInterfaceToRelease )
    {
    	if( pInterfaceToRelease != NULL ){
    		pInterfaceToRelease->Release();
    		pInterfaceToRelease = NULL;
    	}
    }
    
    int main( int argc, char **argv[] )
    {
    	//OpenCV中开启CPU的硬件指令优化功能函数
    	setUseOptimized( true );
    
    	// 打开kinect
    	IKinectSensor* pSensor;
    	HRESULT hResult = S_OK;
    	hResult = GetDefaultKinectSensor( &pSensor );
    	if( FAILED( hResult ) ){
    		cerr << "Error : GetDefaultKinectSensor" << std::endl;
    		return -1;
    	}
    
    	hResult = pSensor->Open();
    	if( FAILED( hResult ) ){
    		cerr << "Error : IKinectSensor::Open()" << std::endl;
    		return -1;
    	}
    
    	// 深度帧源
    	IDepthFrameSource* pDepthSource;
    	hResult = pSensor->get_DepthFrameSource( &pDepthSource );
    	if( FAILED( hResult ) ){
    		cerr << "Error : IKinectSensor::get_DepthFrameSource()" << std::endl;
    		return -1;
    	}
    
    	// 深度帧读取
    	IDepthFrameReader* pDepthReader;
    	hResult = pDepthSource->OpenReader( &pDepthReader );
    	if( FAILED( hResult ) ){
    		cerr << "Error : IDepthFrameSource::OpenReader()" << std::endl;
    		return -1;
    	}
    
    	// Description
    	IFrameDescription* pDescription;
    	hResult = pDepthSource->get_FrameDescription( &pDescription );
    	if( FAILED( hResult ) ){
    		cerr << "Error : IDepthFrameSource::get_FrameDescription()" << std::endl;
    		return -1;
    	}
    
    	int width = 0;
    	int height = 0;
    	pDescription->get_Width( &width ); // 512
    	pDescription->get_Height( &height ); // 424
    	unsigned int bufferSize = width * height * sizeof( unsigned short );
    
    	// Range
    	unsigned short min = 0;
    	unsigned short max = 0;
    	pDepthSource->get_DepthMinReliableDistance( &min ); // 500
    	pDepthSource->get_DepthMaxReliableDistance( &max ); // 4500
    	cout << "Range : " << min << " - " << max << std::endl;
    	
    	//创建尺寸为height x width 的1通道8位图像
    	Mat bufferMat( height, width, CV_16UC1 );
    	Mat depthMat( height, width, CV_8UC1 );
    
    	while( 1 ){
    		// 更新深度帧
    		IDepthFrame* pDepthFrame = nullptr;
    		hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );
    		if( SUCCEEDED( hResult ) ){
    			hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );
    			if( SUCCEEDED( hResult ) ){
    				bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f, 255.0f );
    			}
    		}
    		SafeRelease( pDepthFrame );
    
    		imshow( "Depth", depthMat );
    
    		if( cv::waitKey( 30 ) == VK_ESCAPE ){
    			break;
    		}
    	}
    
    	SafeRelease( pDepthSource );
    	SafeRelease( pDepthReader );
    	SafeRelease( pDescription );
    	if( pSensor ){
    		pSensor->Close();
    	}
    	SafeRelease( pSensor );
    
    	return 0;
    }
    


  • 相关阅读:
    python 获取浏览器窗口句柄
    实现远程连接 Win10的Ubuntu子系统下的MySQL数据库
    Postman 测试微信小程序后台接口
    使用Postman获取小程序码时如何解决47001报错
    富文本编辑框比较
    PIL 生成随机验证码图片
    哪里买书合算
    在文件中读取列表功能
    python函数01
    修改文件内容
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5243133.html
Copyright © 2011-2022 走看看