Kinect SDK获取深度图与彩色图并保存

#include <stdlib.h>
#include <iostream>
#include <string>
#include "OpenNI.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "Windows.h"
#include <Shlobj.h>
#include "NuiApi.h"
#include <sstream>
 
 
#include <opencv2/opencv.hpp>  
 
using namespace std;  
using namespace cv;  
using namespace openni;
 
 
int frameNo = 1;
 
int main(int argc, char *argv[])
{
	Mat colorImage;
	Mat depthImage;
	colorImage.create(480, 640, CV_8UC3);
	depthImage.create(480,640,CV_8UC1);
 
	//1、初始化NUI 
	HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH); 
	if (FAILED(hr)) 
	{ 
		cout<<"NuiInitialize failed"<<endl; 
		return hr; 
	} 
 
	//2、定义事件句柄 
	//创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据
	HANDLE nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	HANDLE colorStreamHandle = NULL; //保存彩色图像数据流的句柄,用以提取数据
 
	HANDLE nextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	HANDLE depthStreamHandle = NULL;//保存深度图像数据流的句柄,用以提取数据
 
	//3、打开KINECT设备的彩色图信息通道,并用colorStreamHandle保存该流的句柄,以便于以后读取
	hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 
		0, 2, nextColorFrameEvent, &colorStreamHandle); 
	if( FAILED( hr ) )//判断是否提取正确 
	{ 
		cout<<"Could not open color image stream video"<<endl; 
		NuiShutdown(); 
		return hr; 
	}
	namedWindow("colorImage", CV_WINDOW_AUTOSIZE);
 
	hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480,
		0, 2, nextDepthFrameEvent, &depthStreamHandle);
	if( FAILED( hr ) )//判断是否提取正确
	{
		cout<<"Could not open depth image stream video"<<endl;
		NuiShutdown();
		return hr;
	}
	namedWindow("depthImage", CV_WINDOW_AUTOSIZE);
 
	//4、开始读取彩色图数据 
	while(1) 
	{ 
		const NUI_IMAGE_FRAME * pColorImageFrame = NULL; 
		const NUI_IMAGE_FRAME * pDepthImageFrame = NULL;
 
		string colorPathPrefix = "colorImage";
		string depthPathPrefix = "depthImage";
		string commonPathSuffix = ".jpg";
 
		//4.1、无限等待新的彩色图像数据,等到后返回
		if (WaitForSingleObject(nextColorFrameEvent, INFINITE)==0) 
		{
			
			stringstream ss;
			ss<<colorPathPrefix;
			ss<<frameNo;
			ss<<commonPathSuffix;
			string colorImagePath = ss.str();
 
			//4.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pColorImageFrame
			hr = NuiImageStreamGetNextFrame(colorStreamHandle, 0, &pColorImageFrame); 
			if (FAILED(hr))
			{
				cout<<"Could not get color image"<<endl; 
				NuiShutdown();
				return -1;
			}
 
			INuiFrameTexture * pTexture = pColorImageFrame->pFrameTexture;
			NUI_LOCKED_RECT LockedRect;
 
			//4.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址
			//并锁定数据,这样当我们读数据的时候,kinect就不会去修改它
			pTexture->LockRect(0, &LockedRect, NULL, 0); 
			//4.4、确认获得的数据是否有效
			if( LockedRect.Pitch != 0 ) 
			{ 
				//4.5、将数据转换为OpenCV的Mat格式
				for (int i=0; i<colorImage.rows; i++) 
				{
					uchar *ptr = colorImage.ptr<uchar>(i);  //第i行的指针
 
					//每个字节代表一个颜色信息,直接使用uchar
					uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
					for (int j=0; j<colorImage.cols; j++) 
					{ 
						ptr[3*j] = pBuffer[4*j];  //内部数据是4个字节,0-1-2是BGR,第4个现在未使用 
						ptr[3*j+1] = pBuffer[4*j+1]; 
						ptr[3*j+2] = pBuffer[4*j+2]; 
					} 
				} 
				imwrite(colorImagePath,colorImage);
				imshow("colorImage", colorImage); //显示图像 
			} 
			else 
			{ 
				cout<<"Buffer length of received texture is bogus\r\n"<<endl; 
			}
 
			//5、这帧已经处理完了,所以将其解锁
			pTexture->UnlockRect(0);
			//6、释放本帧数据,准备迎接下一帧 
			NuiImageStreamReleaseFrame(colorStreamHandle, pColorImageFrame ); 
		}
 
		//7.1、无限等待新的深度数据,等到后返回
		if (WaitForSingleObject(nextDepthFrameEvent, INFINITE)==0)
		{
			stringstream ss;
			ss<<depthPathPrefix;
			ss<<frameNo;
			ss<<commonPathSuffix;
			string depthImagePath = ss.str();
			frameNo++;
			//7.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame
			hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pDepthImageFrame);
			if (FAILED(hr))
			{
				cout<<"Could not get color image"<<endl;
				NuiShutdown();
				return -1;
			}
			INuiFrameTexture * pTexture = pDepthImageFrame->pFrameTexture;
			NUI_LOCKED_RECT LockedRect;
			//7.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址
			//并锁定数据,这样当我们读数据的时候,kinect就不会去修改它
			pTexture->LockRect(0, &LockedRect, NULL, 0);
			//7.4、确认获得的数据是否有效
			if( LockedRect.Pitch != 0 )
			{
 
				//7.5、将数据转换为OpenCV的Mat格式
				for (int i=0; i<depthImage.rows; i++)
				{
					uchar *ptr = depthImage.ptr(i);  //第i行的指针
					//每个字节代表一个颜色信息,直接使用uchar
					uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
					USHORT *pBufferRun = (USHORT *)pBuffer;//这里需要转换,因为每个深度数据是2个字节,应将BYTE转成USHORT
					 for (int j=0; j<depthImage.cols; j++)  
					{
						ptr[j] = 255-(BYTE)(256*pBufferRun[j]/0x1fff); //将数据归一化处理*
					}
				}
				imwrite(depthImagePath,depthImage);
				imshow("depthImage", depthImage); //显示图像
				
			}
			else
			{
				cout<<"Buffer length of received texture is bogus\r\n"<<endl;
			}
			//8、这帧已经处理完了,所以将其解锁
			pTexture->UnlockRect(0);
			//9、释放本帧数据,准备迎接下一帧
			NuiImageStreamReleaseFrame(depthStreamHandle, pDepthImageFrame );
			if(frameNo == 10)
				break;
		}
 
		if (cvWaitKey(20) == 27) 
			break; 
	} 
	//7、关闭NUI链接 
	NuiShutdown(); 
	return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值