Kinect开发教程二:OpenNI读取深度图像与彩色图像并显示

来源:互联网 发布:金牛教育网络视频 编辑:程序博客网 时间:2024/04/24 18:32

细心的朋友肯定已经发现Kinect上长了三只眼睛,其中一个是彩色摄像头,另外两个深度摄像头,一个负责发射红外光,一个负责接收,这样,我们便能通过Kinect得到一幅彩色图像和一幅深度图像。如果大家对Kniect眼睛的技术细节感兴趣,请点击这里。

       小斤的第一个范例,便是通过OpenNI得到彩色和深度图像咯,代码不长,其中一部分参考了Heresky童鞋的文章《透過 OpneNI 合併 Kinect 深度以及彩色影像資料》,此外,小斤补充了OpenCV的显示部分,使范例更为直观。

[cpp] view plaincopy
  1. #include <stdlib.h>  
  2. #include <iostream>  
  3. #include <string>  
  4. //【1】  
  5. #include <XnCppWrapper.h>  
  6. #include "opencv/cv.h"  
  7. #include "opencv/highgui.h"  
  8.   
  9. using namespace std;  
  10. using namespace cv;  
  11.   
  12. void CheckOpenNIError( XnStatus result, string status )  
  13. {   
  14.     if( result != XN_STATUS_OK )   
  15.         cerr << status << " Error: " << xnGetStatusString( result ) << endl;  
  16. }  
  17.   
  18. int main( int argc, char** argv )  
  19. {  
  20.     XnStatus result = XN_STATUS_OK;    
  21.     xn::DepthMetaData depthMD;  
  22.     xn::ImageMetaData imageMD;  
  23.   
  24.     //OpenCV  
  25.     IplImage*  imgDepth16u=cvCreateImage(cvSize(640,480),IPL_DEPTH_16U,1);  
  26.     IplImage* imgRGB8u=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);  
  27.     IplImage*  depthShow=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  28.     IplImage* imageShow=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);  
  29.     cvNamedWindow("depth",1);  
  30.     cvNamedWindow("image",1);  
  31.     char key=0;  
  32.   
  33.     //【2】  
  34.     // context   
  35.     xn::Context context;   
  36.     result = context.Init();   
  37.     CheckOpenNIError( result, "initialize context" );    
  38.   
  39.     // creategenerator    
  40.     xn::DepthGenerator depthGenerator;    
  41.     result = depthGenerator.Create( context );   
  42.     CheckOpenNIError( result, "Create depth generator" );    
  43.     xn::ImageGenerator imageGenerator;  
  44.     result = imageGenerator.Create( context );   
  45.     CheckOpenNIError( result, "Create image generator" );  
  46.   
  47.     //【3】  
  48.     //map mode    
  49.     XnMapOutputMode mapMode;   
  50.     mapMode.nXRes = 640;    
  51.     mapMode.nYRes = 480;   
  52.     mapMode.nFPS = 30;   
  53.     result = depthGenerator.SetMapOutputMode( mapMode );    
  54.     result = imageGenerator.SetMapOutputMode( mapMode );    
  55.   
  56.     //【4】  
  57.     // correct view port    
  58.     depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator );   
  59.   
  60.     //【5】  
  61.     //read data  
  62.     result = context.StartGeneratingAll();    
  63.     //【6】  
  64.     result = context.WaitNoneUpdateAll();    
  65.   
  66.     while( (key!=27) && !(result = context.WaitNoneUpdateAll( ))  )   
  67.     {    
  68.         //get meta data  
  69.         depthGenerator.GetMetaData(depthMD);   
  70.         imageGenerator.GetMetaData(imageMD);  
  71.   
  72.         //【7】  
  73.         //OpenCV output  
  74.         memcpy(imgDepth16u->imageData,depthMD.Data(),640*480*2);  
  75.         cvConvertScale(imgDepth16u,depthShow,255/4096.0,0);  
  76.         memcpy(imgRGB8u->imageData,imageMD.Data(),640*480*3);  
  77.         cvCvtColor(imgRGB8u,imageShow,CV_RGB2BGR);  
  78.         cvShowImage("depth", depthShow);  
  79.         cvShowImage("image",imageShow);  
  80.         key=cvWaitKey(20);  
  81.     }  
  82.   
  83.     //destroy  
  84.     cvDestroyWindow("depth");  
  85.     cvDestroyWindow("image");  
  86.     cvReleaseImage(&imgDepth16u);  
  87.     cvReleaseImage(&imgRGB8u);  
  88.     cvReleaseImage(&depthShow);  
  89.     cvReleaseImage(&imageShow);  
  90.     context.StopGeneratingAll();  
  91.     context.Shutdown();  
  92.     return 0;  
  93. }  

     

 这边小斤由上到下解释一把:

【1】<XnCppWrapper.h>便是OpenNI的文件头了,使用OpenNI的话,目前只要include这个就行。

【2】DepthGenerator和ImageGenerator,小斤称之为图像生成器,前者负责深度图像,后者负责彩色图像。创建一个生成器非常简单,首先我们要初始化一个Context上下文,然后把Context作为Create函数的参数,便可以创建生成器了。

【3】XnMapOutputMode是用来设定生成器的参数的,这边小斤设定了分辨率为640*480(标准),30fps采样。

【4】depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator)这句话也许会让大家疑惑,它是用来调整视角的。为什么要调整呢?因为Kinect的三只眼长在不同的地方,所以画幅一致的深度摄像头和彩色摄像头,它们看出来的景物是有偏差的,这里OpenNI提供了函数进行对齐。这里,小斤把深度生成器的视角,设定为彩色生成器的视角。

【5】调用StartGeneratingAll()后,生成器们便开始上班了,如果要结束,就StopGeneratingAll()函数。

【6】尽管生成器们在工作了,但他们一直忙着各读各的,没有人协调,自己不会乖乖把最新的资料给我们。我们调用getMetaData()方法前,需要使用WaitAnyUpdateAll()、WaitOneUpdateAll()、WaitNoneUpdateAll()和WiatAndUpdateAll()中的一种。功能如其名,这边小斤使用的是WaitNoneUpdateAll()函数,它比较暴力,不管生成器有没有读到新数据,我这边先更新了再说。大家可以试试其它三个,看看效果。

【7】这边使用OpenNI获得图像MetaData数据后,小斤通过一系列函数,转换为OpenCV的IplImage图像类型,然后输出。主要参考了这篇文章。

       对于深度MetaData,这边使用cvConvertScale转换尺度,成为灰度值[0,255]的灰度图。对于彩色MetaData,使用cvCvtColor转换色彩空间即可。按ESC键可以退出循环,结束程序。

        最终效果如下:


      在灰度图中灰度值0显示为黑色,255为白色,所以,离Kinect近的地方(桌面)显示为黑色,中间为不同程度的灰色,远处(天花板)显示为白色。

0 0
原创粉丝点击