方法contextOpenNI: 深度图显示方法

文章结束给大家来个程序员笑话:[M]

    OpenNI的深度图表现有重要有两种方法:

    1.深度值直接赋值方法(同上一篇):

    缺点:深度图层次不显著,重要由于位移操作导致

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

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

using namespace std;
using namespace cv;


void CheckOpenNIError( XnStatus result, string status )
{ 
	if( result != XN_STATUS_OK ) 
		cerr << status << " Error: " << xnGetStatusString( result ) << endl;
}

int main( int argc, char** argv )
{
	XnStatus result = XN_STATUS_OK;  
	xn::DepthMetaData depthMD;
	xn::ImageMetaData 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",1);
	cvNamedWindow("image",1);
	char key=0;

	//【2】
	// context 
	xn::Context context; 
	result = context.Init(); 
	CheckOpenNIError( result, "initialize context" );  

	// creategenerator  
	xn::DepthGenerator depthGenerator;  
	result = depthGenerator.Create( context ); 
	CheckOpenNIError( result, "Create depth generator" );  
	xn::ImageGenerator imageGenerator;
	result = imageGenerator.Create( context ); 
	CheckOpenNIError( result, "Create image generator" );

	//【3】
	//map mode  
	XnMapOutputMode mapMode; 
	mapMode.nXRes = 640;  
	mapMode.nYRes = 480; 
	mapMode.nFPS = 30; 
	result = depthGenerator.SetMapOutputMode( mapMode );  
	result = imageGenerator.SetMapOutputMode( mapMode );  

	//【4】
	// correct view port  
	depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator ); 

	//【5】
	//read data
	result = context.StartGeneratingAll();  
	//【6】
	result = context.WaitNoneUpdateAll();  


	while((key!=27) && !(result = context.WaitNoneUpdateAll()) )
	{
		//get meta data
		depthGenerator.GetMetaData(depthMD); 
		imageGenerator.GetMetaData(imageMD);
//----------------------------------------------------------------------
//---------------转换为Mat操作,3种方法----------------------------
//------------------------------------------------------------------------
		if(depthMD.Data()!=NULL)
		{
			//方法【1】通过Mat定义
			//convert ImageMetaData to Mat
			uchar *q = (uchar *) imageMD.Data();
			Mat rgbMat1(480,640,CV_8UC3,q);
			Mat rgbMatShow1;
			cvtColor(rgbMat1,rgbMatShow1,CV_RGB2BGR);
			imshow("testColorMat",rgbMatShow1);

			//convert DepthMetaData to Mat
			unsigned short* p = (unsigned short*)  depthMD.Data();
			Mat depthMat1(480,640,CV_16SC1,p);
			Mat depthMatShow1(480,640,CV_8UC1);
			convertScaleAbs(depthMat1,depthMatShow1,255/4096.0);//这一步很重要;
			normalize(depthMatShow1,depthMatShow1,255,0,CV_MINMAX);
			imshow("testDepthMat",depthMatShow1);

			//方法【2】通过坐标(x,y),ImageMetaData貌似不太支持;
			Mat depthMat2(480,640,CV_16SC1);
			Mat depthMatShow2(480,640,CV_8UC1);
			UINT16* depth_p;
			for (int y=0; y<480; y++)
			{
				depth_p = depthMat2.ptr<UINT16>(y);
				for (int x=0; x<640; x++)
				{
					depth_p[x]=(UINT16)depthMD(x,y);//核心赋值
				}
			}
			convertScaleAbs(depthMat2,depthMatShow2,255/4096.0);//这一步很重要;
			normalize(depthMatShow2,depthMatShow2,255,0,CV_MINMAX);
			imshow("testDepthMat2",depthMatShow2);

			//方法【3】通过指针操作;
			//RGB
			Mat rgbMat3(480,640,CV_8UC3);
			Mat rgbMatShow3;
			uchar *rgb_p;
			UINT8 *src_p;
			src_p = (UINT8*) imageMD.Data();
			for (int y=0; y<480; y++)
			{
				rgb_p = rgbMat3.ptr<uchar>(y);
				for (int x=0; x<640; x++)
				{
					*rgb_p++ =(uchar) *src_p++;
					*rgb_p++ =(uchar) *src_p++;
					*rgb_p++ =(uchar) *src_p++;
				}
			}
			cvtColor(rgbMat3,rgbMatShow3,CV_RGB2BGR);
			imshow("testColorMat3",rgbMatShow3);

			Mat depthMat3(480,640,CV_16SC1);
			Mat depthMatShow3(480,640,CV_8UC1);
			UINT16* depthSrc_p;
			uchar* depth3_p;
			depthSrc_p = (UINT16*)depthMD.Data();
			for (int y=0; y<480; y++)
			{
				depth3_p = depthMatShow3.ptr<uchar>(y);
				for (int x=0; x<640; x++)
				{
					depth3_p[x]= (uchar)((*depthSrc_p)*255/4096);//
					depthSrc_p++;
				}
			}
			//convertScaleAbs(depthMat3,depthMatShow3,255/4096.0);//这一步很重要;
			normalize(depthMatShow3,depthMatShow3,255,0,CV_MINMAX);
			imshow("testDepthMat3",depthMatShow3);


		}

		//OpenCV output
// ----------------------------------------------------------------------
// ---------------转换为IplImage操作----------------------------
// ------------------------------------------------------------------------
		memcpy(imgDepth16u->imageData,depthMD.Data(),640*480*2);
		cvConvertScale(imgDepth16u,depthShow,255/4096.0,0);
		memcpy(imgRGB8u->imageData,imageMD.Data(),640*480*3);
		cvCvtColor(imgRGB8u,imageShow,CV_RGB2BGR);
		cvShowImage("depth", depthShow);
		cvShowImage("image",imageShow);
  		key=cvWaitKey(20);
		
	}

}
    每日一道理
我拽着春姑娘的衣裙,春姑娘把我带到了绿色的世界里。

    2.通过NiSample的直方图赋值方法:

    长处:生成的深度图层次比较显著。

    代码附带深度阈值分割

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

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

using namespace std;
using namespace cv;


void CheckOpenNIError( XnStatus result, string status )
{ 
	if( result != XN_STATUS_OK ) 
		cerr << status << " Error: " << xnGetStatusString( result ) << endl;
}

int main( int argc, char** argv )
{
	XnStatus result = XN_STATUS_OK;  
	xn::DepthMetaData depthMD;
	xn::ImageMetaData imageMD;

	//【2】
	// context 
	xn::Context context; 
	result = context.Init(); 
	CheckOpenNIError( result, "initialize context" );  
	// creategenerator  
	xn::DepthGenerator depthGenerator;  
	result = depthGenerator.Create( context ); 
	CheckOpenNIError( result, "Create depth generator" );  
	xn::ImageGenerator imageGenerator;
	result = imageGenerator.Create( context ); 
	CheckOpenNIError( result, "Create image generator" );

	//【3】
	//map mode  
	XnMapOutputMode mapMode; 
	mapMode.nXRes = 640;  
	mapMode.nYRes = 480; 
	mapMode.nFPS = 30; 
	result = depthGenerator.SetMapOutputMode( mapMode );  
	result = imageGenerator.SetMapOutputMode( mapMode );  

	//【4】
	// correct view port
	// 若使用imageGenerator则深度图有一圈黑
	depthGenerator.GetAlternativeViewPointCap().SetViewPoint( depthGenerator ); 

	//【5】
	//read data
	result = context.StartGeneratingAll();  
	
	//【6】
	result = context.WaitNoneUpdateAll();  

	Mat depthMat1u(480,640,CV_8UC1);
	Mat depthMat3u(480,640,CV_8UC3);
	

	char key=0;
	while((key!=27) && !(result = context.WaitNoneUpdateAll()) )
	{

		//get meta data
		depthGenerator.GetMetaData(depthMD); 
		imageGenerator.GetMetaData(imageMD);

		//直接Mat赋值操作
		uchar *q = (uchar *) imageMD.Data();
		Mat rgbMat1(480,640,CV_8UC3,q);
		Mat rgbMatShow1;
		cvtColor(rgbMat1,rgbMatShow1,CV_RGB2BGR);
		imshow("testColorMat",rgbMatShow1);

		//通过OpenNI Sample 中 NUISampleViewer 的 pDepthHist[*pDepth]操作.
		XnDepthPixel nZRes = depthMD.ZRes();
		float* pDepthHist = (float*)malloc(nZRes * sizeof(float));

		const XnDepthPixel* pDepth = depthMD.Data();
		xnOSMemSet(pDepthHist, 0, nZRes*sizeof(float));

		unsigned int nNumberOfPoints = 0;
		for (XnUInt y = 0; y < depthMD.YRes(); ++y)
		{
			for (XnUInt x = 0; x < depthMD.XRes(); ++x, ++pDepth)
			{
				if (*pDepth != 0)
				{
					pDepthHist[*pDepth]++;
					nNumberOfPoints++;
				}
			}
		}

		for (int nIndex=1; nIndex<nZRes; nIndex++)
		{
			pDepthHist[nIndex] += pDepthHist[nIndex-1];
		}
		
		if (nNumberOfPoints)
		{
			for (int nIndex=1; nIndex<nZRes; nIndex++)
			{
				pDepthHist[nIndex] = (unsigned int)(256 * (1.0f - (pDepthHist[nIndex] / nNumberOfPoints)));
			}
		}

		const XnDepthPixel* pDepthRow = depthMD.Data();
		for (XnUInt y = 0; y < depthMD.YRes(); ++y)
		{
			const XnDepthPixel* pDepth = pDepthRow;
			uchar* depthMat1u_p = depthMat1u.ptr<uchar>(y);
			for (XnUInt x = 0; x < depthMD.XRes(); ++x, ++pDepth)
			{
				if (1/**pDepth != 0*/)
				{
					uchar nHistValue =(uchar) pDepthHist[*pDepth];
					depthMat1u_p[x] = nHistValue;//NiSample是将B、G两个通道都赋值生成黄色深度图
				}
			}
			pDepthRow += depthMD.XRes();
		}


		//normalize(depthMat1u,depthMat1u,255,0,CV_MINMAX);
		Point maxLoc;
		double maxV;
		minMaxLoc(depthMat1u,0,&maxV,0,&maxLoc);
		Mat mask(480,640,CV_8UC1);
		
		threshold(depthMat1u,mask,0.9*maxV,255,THRESH_BINARY);
		imshow("mask",mask);

		
		cvtColor(depthMat1u,depthMat3u,CV_GRAY2BGR);
		circle(depthMat3u,maxLoc,5,Scalar(0,255,0),-1);
		imshow("depthMaxloc",depthMat3u);
		key=waitKey(20);
	}

	
}

文章结束给大家分享下程序员的一些笑话语录: 这个世界上只有10种人:懂得二进制的和不懂得二进制的。

--------------------------------- 原创文章 By
方法和context
---------------------------------

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3113100.html