关于Kinect深度图和彩色图像提取

     初学使用OpenNi开发Kinect,首先拿过来还是玩一下怎么提取图像数据。Kinect上有一个红外发射器,当驱动Kinect时发射红外扫描视场范围,红外接收器接收到物体反射回来的红外光,经过内部芯片处理后输出深度图像数据,而RGB图像传感器就直接采集到彩色图像数据。
 
// 3DRebuild.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <stdlib.h>
#include <iostream>
#include <string>

#include <XnCppWrapper.h>
#include <opencv/cv.h>   
#include <opencv/highgui.h>

/***************************************
Macros
****************************************/
#define XN_VGA_XRES 640
#define XN_VGA_YRES 480


using namespace std;
using namespace xn;
using namespace cv;


/***************************************
Grobals
****************************************/




/***************************************
Functions
****************************************/
void CheckOpenNIError( XnStatus eResult, string sStatus )
{
  if( eResult != XN_STATUS_OK )
    cerr << sStatus << " Error: " << xnGetStatusString( eResult ) << endl;
}



int main(int argc, _TCHAR* argv[])
{
	XnStatus nRetVal ;
	Context g_context;
	DepthGenerator g_depthGenerator;
	ImageGenerator g_imageGenerator;
	DepthMetaData g_depthMD;
	ImageMetaData g_imageMD;

	 //用于OpenCV显示的图像
    IplImage* imgDepth16u = cvCreateImage(cvSize(640,480),IPL_DEPTH_16U,1);  
    IplImage* imgRGB8u = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);  
    IplImage* depthShow = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
    IplImage* imageShow = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
	cvNamedWindow("depth",CV_WINDOW_AUTOSIZE);
	cvNamedWindow("image",CV_WINDOW_AUTOSIZE);

	nRetVal = g_context.Init();
	CheckOpenNIError(nRetVal,"Context initialization");

	//深度节点和RGB图像节点的创建
	nRetVal = g_depthGenerator.Create(g_context);
	CheckOpenNIError(nRetVal,"Depth generator create");
	nRetVal = g_imageGenerator.Create(g_context);
	if(nRetVal == XN_STATUS_OK)
	CheckOpenNIError(nRetVal,"Image generator create");

	 //图像输出模式配置     
    XnMapOutputMode mapMode;   
    mapMode.nXRes = XN_VGA_XRES;    
    mapMode.nYRes = XN_VGA_YRES;   
    mapMode.nFPS = 30;   
    nRetVal = g_depthGenerator.SetMapOutputMode(mapMode);
	CheckOpenNIError(nRetVal,"Setting the depth map output mode");
    nRetVal = g_imageGenerator.SetMapOutputMode(mapMode);
	CheckOpenNIError(nRetVal,"Setting the image map output mode");

	 //修改视角,将深度图像和彩色图像进行融合    
    g_depthGenerator.GetAlternativeViewPointCap().SetViewPoint( g_imageGenerator );

	//开始启动上下文中所有节点
	nRetVal = g_context.StartGeneratingAll();
	CheckOpenNIError(nRetVal,"Start generating all");

	int key = 0;
	while((key!=27) && !(nRetVal = g_context.WaitNoneUpdateAll()))
	{
		nRetVal = g_context.WaitAndUpdateAll();
		CheckOpenNIError(nRetVal,"Wait and update all");

		//get meta data   
		g_depthGenerator.GetMetaData(g_depthMD);   
        g_imageGenerator.GetMetaData(g_imageMD);  

		//OpenCV output   
       memcpy(imgDepth16u->imageData,g_depthMD.Data(),640*480*2);  
       cvConvertScale(imgDepth16u,depthShow,1.0,0); 
       memcpy(imgRGB8u->imageData,g_imageMD.Data(),640*480*3);  
       cvCvtColor(imgRGB8u,imageShow,CV_RGB2BGR);  
       cvShowImage("depth", depthShow);  
       cvShowImage("image",imageShow);  
	   key = cvWaitKey(20);
	   //printf("Please press any key continue!");
	    
	}
	//destroy   
    cvDestroyAllWindows(); 
    cvReleaseImage(&imgDepth16u);  
    cvReleaseImage(&imgRGB8u);  
	cvReleaseImage(&depthShow);  ; 
	cvReleaseImage(&imageShow);
    g_context.StopGeneratingAll();  
    g_context.Shutdown();  

	return 0;
}


1、<XnCppWrapper.h>是OpenNI的文件头,使用OpenNI的话,目前只要include这个就行了。
 
  2、 DepthGenerator为深度图像生成器,ImageGenerator为彩色图像生成器。创建一个生成器非常简单,首先我们要初始化一个Context上下文,然后把Context作为Create函数的参数,便可以创建生成器了。

3、depthGenerator.GetAlternativeViewPointCap().SetViewPoint(g_ imageGenerator)是用来调整视角的。为什么要调整呢?因为Kinect的三只眼长在不同的地方,所以画幅一致的深度摄像头和彩色摄像头,它们看出来的景物是有偏差的,这里OpenNI提供了函数进行对齐。我把深度生成器的视角,设定为彩色生成器的视角,让它们的视角保持一致,这个到时在深度图像和彩色图像的合成时还会用到,不用这句话的话到时合成的图像是错位的。

4、我们使用StartGeneratingAll()使包含在g_context中的所有节点还是产生数据,但是在调用GetMetaData()方法前,需要使用WaitAnyUpdateAll()、WaitOneUpdateAll()、WaitNoneUpdateAll()和WiatAndUpdateAll()中的一种,不然会可能出现获取的数据不是最新数据。这里使用的是WaitNoneUpdateAll()函数,它比较暴力,不管生成器有没有读到新数据,我这边先更新了再说。大家可以试试其它三个,看看效果。获取图像数据的方法还GetDepthMap()和GetImageMap(),其实使用GetMetaData()方法有一个好处是当在提取数据时配置发生改变了,我们得到的数据将是配置改变了的数据,使用GetDepthMap()和GetImageMap()方法得到的数据就是配置未改变的。

 

效果图:

 
转载请附上链接

你可能感兴趣的:(image,include,generator,output,initialization,macros)