这一部分我主要参考了http://blog.youkuaiyun.com/chenxin_130/article/details/6696187和http://blog.youkuaiyun.com/kh1445291129/article/details/39346987,这两篇博客,接下来我简要的总结一下,这两篇博客提到的方法。
进行OPENNI的图像和深度图提取,首先我们要创建上下文对象并进行初始化。
<span style="font-size:18px;color:#000000;">XnStatus eResult = XN_STATUS_OK;
Context mContext;//初始化上下文对象
eResult = mContext.Init();
CheckError(eResult);</span>
以这个为基础,我们才能进一步去进行生产节点的创建。对于OPENNI来说,所有的生产节点均是在上下文对象中创建,不同的上下文对象不可进行数据的传递和共享。
接下来我们进行深度图和彩色图的结点创建。
<span style="font-size:18px;color:#000000;">ImageGenerator mImageGenerator;//创建彩色图像生产节点
eResult = mImageGenerator.Create(mContext); </span>
<span style="font-size:18px;color:#000000;">CheckError(eResult,"Create image generator"); </span>
<span style="font-size:18px;color:#000000;">DepthGenerator mDepthGenerator;//创建深度图像生产节点 </span>
<span style="font-size:18px;color:#000000;">eResult = mDepthGenerator.Create(mContext);
CheckError(eResult,"Create depth generator");</span>
为了能够达到我们需要的图像的大小,我们需要进行图生成器输出模式的设定,即设定输出图像的x,y轴像素数量,及帧速率。设定之后应用到我们的生产节点。
<span style="font-size:18px;color:#000000;">XnMapOutputMode mapMode;//设置图像分辨率
mapMode.nXRes = 320;
mapMode.nYRes = 240;
mapMode.nXRes = 30;
eResult = mImageGenerator.SetMapOutputMode(mapMode);
eResult = mDepthGenerator.SetMapOutputMode(mapMode); </span>
由于RGB图与Depth图生成位置(摄像头的位置)不同,所以,两个图肯定会产生偏差,为了弥补这个偏差,我们使用DepthGenerator.GetAlternativeViewPointCap().SetViewPoint()这个函数进行矫正。
<span style="font-size:18px;color:#000000;"> mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint(mImageGenerator);
</span>
然后产生数据
<span style="font-size:18px;color:#000000;"> eResult = mContext.StartGeneratingAll();//开始产生数据 </span>
<span style="font-size:18px;color:#000000;">while(true)
{
eResult = mContext.WaitAndUpdateAll();
if(eResult == XN_STATUS_OK)
{
mImageGenerator.GetMetaData(imageMD);
Mat cvRGBImage(imageMD.FullYRes(),imageMD.FullXRes(),CV_8UC3,(char*) imageMD.Data());
Mat cvBGRImage;
cvtColor(cvRGBImage,cvBGRImage,CV_RGB2BGR);
//整幅图像颜色转换,因为opencv中采用BGR方式排列
imshow("Color Image",cvBGRImage);
mDepthGenerator.GetMetaData(depthMD);
Mat cvDepthImage16UC1(depthMD.FullYRes(),
depthMD.FullXRes(),
CV_16UC1,(char*) depthMD.Data());
Mat cvDepthImage8UC1;
cvDepthImage16UC1.convertTo(cvDepthImage8UC1,CV_8UC1,255.0/(depthMD.ZRes()));//格式转换
imshow("Depth Image",cvDepthImage8UC1);
Mat cvDepthImage8UC3;
cvtColor(cvDepthImage8UC1,cvDepthImage8UC3,CV_GRAY2BGR);//格式转换
Mat cvFusionImage;
cvFusionImage = 0.5*cvBGRImage + 0.5*cvDepthImage8UC3;//图像融合
imshow("Fusion Image",cvFusionImage);
waitKey(30);
}
} </span>
这一段代码主要包含这么几个函数,首先是Context.WaitAndUpdateAll()这个函数用来进行数据的更新,一共有四种,WaitAnyUpdateAll(),WaitOneUpdateAll(),WaitAndUpdateAll(),WaitNoneAndUpdateAll(),分别为任意节点更新则全部更新,指定节点更新全更新,所有节点有新数据后更新,强制更新这几种。
还有mImageGenerator.GetMetaData(imageMD);和mDepthGenerator.GetMetaData(depthMD);这两个函数,用来获取彩色图和深度图的数据,并存在制定变量中。
这样我们就得到了彩色图和深度图以及融合图的信息,以便进行接下来的处理。