Kinect的第一个实验OPenNI+OpenCV2

昨天验证了Kinect是可以用的,今天做了第一个实验。参考的是小斤同学的文章

OpenNI读取深度图像与彩色图像并显示    

http://blog.csdn.net/chenxin_130/article/details/6696187

OpenNI:开启Kinect & 格式转换Mat         

http://blog.csdn.net/yangtrees/article/details/8989650


本实验使用C++编写,小斤同学使用了opencv1.0的函数库,这个实验一个困难的地方就是将OpenNI中的深度数据和彩色图像数据保存到OpenCV的数据中。

这一部分我参照了 开启Kinect & 格式转换Mat   这篇文章,终于找到了解决方法,这里列举下其中的两种方法。

首先看Mat的构造函数

C++: Mat::Mat()
C++: Mat::Mat(int rows, int cols, int type)
C++: Mat::Mat(Size size, int type)
C++: Mat::Mat(int rows, int cols, int type, const Scalar& s)
C++: Mat::Mat(Size size, int type, const Scalar& s)
C++: Mat::Mat(const Mat& m)
C++: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all() )
C++: Mat::Mat(const Mat& m, const Rect& roi)
C++: Mat::Mat(const CvMat* m, bool copyData=false)
C++: Mat::Mat(const IplImage* img, bool copyData=false)
C++: template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)
C++: template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)
C++: template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)
C++: Mat::Mat(int ndims, const int* sizes, int type)
C++: Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s)
C++: Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
C++: Mat::Mat(const Mat& m, const Range* ranges)


第一种方法

使用

Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
方法新声明一个图像矩阵并用利用指针传递深度信息和图像信息。

                depthGenerator.GetMetaData(depthMD);
		imageGenerator.GetMetaData(imageMD);

		if(depthMD.Data() != NULL)
		{
			//convert ImageMetaDate to Mat
			uchar *imageMDPointer = (uchar *)imageMD.Data();
			Mat imageRGB(480, 640, CV_8UC3, imageMDPointer);//Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
			cvtColor(imageRGB, imageShow, CV_RGB2BGR);			

			//convert DepthMetaData to Mat 
			unsigned short *depthMDPointer = (unsigned short *)depthMD.Data();
			Mat imgDepth(480, 640, CV_16UC1, depthMDPointer);
			convertScaleAbs(imgDepth, depthShow, 255/4096.0); //将16深度位数据转换为8位数据,以便用灰度图像显示。
			normalize(depthShow, depthShow, 255, 0, NORM_MINMAX );//归一化 0~255

			//output
			imshow("Image", imageShow);
			imshow("Depth", depthShow);
			
		}

第二种方法

通过指针将深度数据和图像数据一个一个赋值到指定的Mat中去。

                        Mat rgbMat3(480,640,CV_8UC3);
			Mat rgbMatShow3;
			uchar *rgb_p;
			uchar *src_p;
			src_p = (uchar*) 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);


本实验的源码如下


#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "XnCppWrapper.h"  

using namespace cv;
using namespace std;

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


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

	//Mat imgDepth16u(480, 640, CV_16UC1);
	//Mat imgBGR8u(480, 640, CV_8UC3);//Mat(nrows, ncols, type) 
	Mat depthShow(480, 640, CV_8UC1);
	Mat imageShow(480, 640, CV_8UC3);
	
	char key = 0;

	namedWindow("Depth", WINDOW_AUTOSIZE);
	namedWindow("Image", WINDOW_AUTOSIZE);


	xn::Context context;
	result = context.Init();
	checkOpenNIError(result, "initialize context");

	xn::DepthGenerator depthGenerator;
	result = depthGenerator.Create(context);
	checkOpenNIError(result, "Create depth generator");

	xn::ImageGenerator imageGenerator;
	result = imageGenerator.Create(context);
	checkOpenNIError(result, "Create image generator");

	XnMapOutputMode mapMode;
	mapMode.nXRes = 640;
	mapMode.nYRes = 480;
	mapMode.nFPS = 30;
	result = depthGenerator.SetMapOutputMode(mapMode);
	result = imageGenerator.SetMapOutputMode(mapMode);

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

	//read data
	result = context.StartGeneratingAll();
	result = context.WaitNoneUpdateAll();

	while ( (key != 27) && !(result = context.WaitNoneUpdateAll()) )
	{
		//get meta data
		depthGenerator.GetMetaData(depthMD);
		imageGenerator.GetMetaData(imageMD);

		if(depthMD.Data() != NULL)
		{
			//convert ImageMetaDate to Mat
			uchar *imageMDPointer = (uchar *)imageMD.Data();
			Mat imageRGB(480, 640, CV_8UC3, imageMDPointer);//Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
			cvtColor(imageRGB, imageShow, CV_RGB2BGR);			

			//convert DepthMetaData to Mat 
			unsigned short *depthMDPointer = (unsigned short *)depthMD.Data();
			Mat imgDepth(480, 640, CV_16UC1, depthMDPointer);
			convertScaleAbs(imgDepth, depthShow, 255/4096.0);
			normalize(depthShow, depthShow, 255, 0, NORM_MINMAX );

			//output
			imshow("Image", imageShow);
			imshow("Depth", depthShow);
			
		}			
		key=cvWaitKey(20);
	}
	context.StopGeneratingAll();
	context.Release();	
	return 0;
}




   






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值