博主从一位台湾大牛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