Kinect中使用OpenNI2实现深度图和彩色图对齐

          博主从一位台湾大牛heresy那里学到很多东西,其中就有关于Kinect中使用OpenNI2实现深度图和彩色图对齐的相关知识。他的Blog是http://viml.nchc.org.tw/home/,大家可以去他的Blog学到很多知识。

          关于这篇文章,其中heresy自己写了一个Kinect.dll文件,可以实现 mDevice.setImageRegistrationMode(IMAGE_REGISTRATION_DEPTH_TO_COLOR );这个函数。有了它,对齐自然就水到渠成了。OpenNI1中不支持这个函数,需要修改相关源代码,实验室一个师兄做过这个。微软SDK也出过一个函数,叫做MapColorFrameToDepthFrame()这个函数,博主搞了好几天,没用好这个函数,故选择了OPENNI2。如果有同学对微软SDK熟悉,并搞定了这个问题的化,欢迎分享交流。

         下面博主贴出自己的代码,很简单。希望可以帮助大家。

         

#include <iostream>
  
// OpenCV Header
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
  
// OpenNI Header
#include <OpenNI.h>
  
// namespace
using namespace std;
using namespace openni;
  
int main( int argc, char **argv )
{
  // 1. Initial OpenNI
  if( OpenNI::initialize() != STATUS_OK )
  {
    cerr << "OpenNI Initial Error: " 
         << OpenNI::getExtendedError() << endl;
    return -1;
  }
  
  // 2. Open Device
  Device mDevice;
  if( mDevice.open( ANY_DEVICE ) != STATUS_OK )
  {
    cerr << "Can't Open Device: " 
         << OpenNI::getExtendedError() << endl;
    return -1;
  }
  openni::Status status;


  // 3. Create depth stream
  VideoStream mDepthStream;
  if( mDevice.hasSensor( SENSOR_DEPTH ) )
  {
    if( mDepthStream.create( mDevice, SENSOR_DEPTH ) == STATUS_OK )
    {
      // 3a. set video mode
      VideoMode mMode;
      mMode.setResolution( 640, 480 );
      mMode.setFps( 30 );
      mMode.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );
  
      if( mDepthStream.setVideoMode( mMode) != STATUS_OK )
      {
        cout << "Can't apply VideoMode: "
             << OpenNI::getExtendedError() << endl;
      }
    }
    else
    {
      cerr << "Can't create depth stream on device: "
           << OpenNI::getExtendedError() << endl;
      return -1;
    }
  }
  else
  {
    cerr << "ERROR: This device does not have depth sensor" << endl;
    return -1;
  }
  
  // 4. Create color stream
  VideoStream mColorStream;
  if( mDevice.hasSensor( SENSOR_COLOR ) )
  {
    if( mColorStream.create( mDevice, SENSOR_COLOR ) == STATUS_OK )
    {
      // 4a. set video mode
      VideoMode mMode;
      mMode.setResolution( 640, 480 );
      mMode.setFps( 30 );
      mMode.setPixelFormat( PIXEL_FORMAT_RGB888 );
  
      if( mColorStream.setVideoMode( mMode) != STATUS_OK )
      {
        cout << "Can't apply VideoMode: " 
             << OpenNI::getExtendedError() << endl;
      }
  
      // 4b. image registration
      if( mDevice.isImageRegistrationModeSupported(
              IMAGE_REGISTRATION_DEPTH_TO_COLOR ) )
      {
        mDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
      }
    }
    else
    {
      cerr << "Can't create color stream on device: "
           << OpenNI::getExtendedError() << endl;
      return -1;
    }
  }
  
   if( mDevice.isImageRegistrationModeSupported( IMAGE_REGISTRATION_DEPTH_TO_COLOR ) )
{
	 status=mDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
}
  // 5. create OpenCV Window
  cv::namedWindow( "Depth Image",  CV_WINDOW_AUTOSIZE );
  cv::namedWindow( "Color Image",  CV_WINDOW_AUTOSIZE );
  
  // 6. start
  VideoFrameRef  mColorFrame;
  VideoFrameRef  mDepthFrame;
  mDepthStream.start();
  mColorStream.start();
  int iMaxDepth = mDepthStream.getMaxPixelValue();
  int ImgNum=0;
  char ImagesName[50];
  cv::Mat cImageBGR;
  cv::Mat mScaledDepth;
  while( true )
  {
    // 7. check is color stream is available
    if( mColorStream.isValid() )
    {
      // 7a. get color frame
      if( mColorStream.readFrame( &mColorFrame ) == STATUS_OK )
      {
        // 7b. convert data to OpenCV format
        const cv::Mat mImageRGB(
                mColorFrame.getHeight(), mColorFrame.getWidth(),
                CV_8UC3, (void*)mColorFrame.getData() );
        // 7c. convert form RGB to BGR
		
        cv::cvtColor( mImageRGB, cImageBGR, CV_RGB2BGR );
        // 7d. show image
        cv::imshow( "Color Image", cImageBGR );
      }
    }
  
    // 8a. get depth frame
    if( mDepthStream.readFrame( &mDepthFrame ) == STATUS_OK )
    {
      // 8b. convert data to OpenCV format
      const cv::Mat mImageDepth(
                mDepthFrame.getHeight(), mDepthFrame.getWidth(),
                CV_16UC1, (void*)mDepthFrame.getData() );
      // 8c. re-map depth data [0,Max] to [0,255]
     
      mImageDepth.convertTo( mScaledDepth, CV_8U, 255.0 / iMaxDepth );
      // 8d. show image
      cv::imshow( "Depth Image", mScaledDepth );
    }
  
    // 6a. check keyboard
    if( cv::waitKey( 1 ) == 'q' )
      break;
	if(cv::waitKey( 1 )=='s')
			//char filename[100];
		{
				sprintf(ImagesName, "cImage%.3d.bmp", ImgNum);
                imwrite(ImagesName,cImageBGR );
				sprintf(ImagesName, "dImage%.3d.bmp", ImgNum);
				imwrite(ImagesName,mScaledDepth);
				ImgNum++;
		     
		}
  }
  
  // 9. stop
  mDepthStream.destroy();
  mColorStream.destroy();
  mDevice.close();
  OpenNI::shutdown();
  system("pause");
  return 0;
}

这个代码实现了同时显示深度图和彩色图。并进行了对齐。大家可以获取彩色图和深度图进行叠加,观察效果。

该代码成功的运行条件是替换OpenNI2安装路径下的Kinect.dll和项目文件下的Kinect.dll

具体路径为C:\Program Files (x86)\OpenNI2\Redist\OpenNI2\Drivers


由于Heresy发布的Kinect.dll文件的地址被GFW呵呵了,所以我上传了一份到CSDN论坛里面,大家可以下载,博主最近没啥积分,故设了2个积分下载权限,大家没有积分的也可以留下邮箱,我看到了后会发给你们。

下载地址是 http://download.csdn.net/detail/janestar/7817293




         

你可能感兴趣的:(Kinect中使用OpenNI2实现深度图和彩色图对齐)