博主从一位台湾大牛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
// OpenCV Header
#include
#include
#include
// OpenNI Header
#include
// 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