Kinect for Windows SDK——FreeImage显示彩色数据

在众多图像库中,FreeImage具有以下优势:开源;比OpenCV稳定;比CxImage调用简单(一个.h文件、一个dll文件、一个lib文件);相比于CxImage,还提供参考文档,学习起来更加方便(另外一个原因则是运用CxImage在Picture Control中显示Kinect的彩色数据搞了半天没成功闭嘴)。所以最后选择FreeImage作为图像库进行Kinect的开发。

1、创建基于对话框的应用程序,添加一个picture control,ID为IDC_COLOR_PICBOX;

2、配置好Kinect SDK和FreeImage的包含目录、库目录、附加依赖项,添加#include"FreeImage.h";

3、定义结构体,便于在多线程中传递参数;

struct ColorDisplayPara
{
	CStatic *picBox;
	INuiSensor* pNuiSensor;
	HANDLE hColorStreamHandle;
	HANDLE hNextColorFrameEvent;
};

4、按照Toolkit提供的demo编写创建Kinect联接的函数

HRESULT CKinectMultiThreadDisplayColorFrameDlg::CreateFirstConnected(void)
{
	INuiSensor * pNuiSensor;
	HRESULT hr;

	int iSensorCount = 0;
	hr = NuiGetSensorCount(&iSensorCount);
	if (FAILED(hr))
	{
		return hr;
	}

	// Look at each Kinect sensor
	for (int i = 0; i < iSensorCount; ++i)
	{
		// Create the sensor so we can check status, if we can't create it, move on to the next
		hr = NuiCreateSensorByIndex(i, &pNuiSensor);
		if (FAILED(hr))
		{
			continue;
		}

		// Get the status of the sensor, and if connected, then we can initialize it
		hr = pNuiSensor->NuiStatus();
		if (S_OK == hr)
		{
			m_ColorDisPlayPara.pNuiSensor = pNuiSensor;
			break;
		}

		// This sensor wasn't OK, so release it since we're not using it
		pNuiSensor->Release();
	}

	if (NULL != m_ColorDisPlayPara.pNuiSensor)
	{
		// Initialize the Kinect and specify that we'll be using color
		hr = m_ColorDisPlayPara.pNuiSensor->NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR); 
		if (SUCCEEDED(hr))
		{
			// Create an event that will be signaled when color data is available
			m_ColorDisPlayPara.hNextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

			// Open a color image stream to receive color frames
			hr = m_ColorDisPlayPara.pNuiSensor->NuiImageStreamOpen(
				NUI_IMAGE_TYPE_COLOR,
				NUI_IMAGE_RESOLUTION_640x480,
				0,
				2,
				m_ColorDisPlayPara.hNextColorFrameEvent,
				&m_ColorDisPlayPara.hColorStreamHandle);
		}
	}

	if (NULL == m_ColorDisPlayPara.pNuiSensor || FAILED(hr))
	{
		//SetStatusMessage(L"No ready Kinect found!");
		return E_FAIL;
	}
	m_ColorDisPlayPara.picBox=(CStatic*)GetDlgItem(IDC_COLOR_PICBOX);

	return hr;
}
主要是把对话框上添加的picturecontrol赋给结构体的picBox变量;

5、在OnInitialDialog函数中加入下面两行代码,第二行的函数代码创建一个新的线程显示彩色数据

	CreateFirstConnected();
	HANDLE hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)processColor,&m_ColorDisPlayPara,0,NULL);
6、第五步对应的线程函数为:

DWORD processColor(ColorDisplayPara* param)
{
	ColorDisplayPara* myPara=(ColorDisplayPara*)param;
	while(1)
	{
		if (0 == WaitForSingleObject(myPara->hNextColorFrameEvent, INFINITE) )
		{
			HRESULT hr;
			NUI_IMAGE_FRAME imageFrame;

			// Attempt to get the color frame
			hr = myPara->pNuiSensor->NuiImageStreamGetNextFrame(myPara->hColorStreamHandle, 0, &imageFrame);
			if (FAILED(hr))
			{
				//return;
			}

			INuiFrameTexture * pTexture = imageFrame.pFrameTexture;
			NUI_LOCKED_RECT LockedRect;

			// Lock the frame data so the Kinect knows not to modify it while we're reading it
			pTexture->LockRect(0, &LockedRect, NULL, 0);

			// Make sure we've received valid data
			if (LockedRect.Pitch != 0)
			{
				FIBITMAP *freeImage=FreeImage_Allocate(640,480,24);
				BYTE* pData=FreeImage_GetBits(freeImage);
				for (int i=0;i<FreeImage_GetHeight(freeImage);i++)
				{
					uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch; 
					for (int j=0;j<FreeImage_GetWidth(freeImage);j++)
					{
						pData[(FreeImage_GetHeight(freeImage)-i)*FreeImage_GetPitch(freeImage)+3*j] = pBuffer[4*j];  //内部数据是4个字节,0-1-2是BGR,第4个现在未使用   
						pData[(FreeImage_GetHeight(freeImage)-i)*FreeImage_GetPitch(freeImage)+3*j+1] = pBuffer[4*j+1];   
						pData[(FreeImage_GetHeight(freeImage)-i)*FreeImage_GetPitch(freeImage)+3*j+2] = pBuffer[4*j+2];
					}
				}
				int w=FreeImage_GetWidth(freeImage);
				int h=FreeImage_GetHeight(freeImage);
				BITMAPINFO info;
				memset(&info,0,sizeof(BITMAPINFO));
				info.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
				info.bmiHeader.biBitCount=24;
				info.bmiHeader.biPlanes=1;
				info.bmiHeader.biWidth=w;
				info.bmiHeader.biHeight=h;
				HDC Hdc=myPara->picBox->GetDC()->GetSafeHdc();
				RECT rect;
				GetClientRect(myPara->picBox->GetSafeHwnd(),&rect);
				int desW=rect.right-rect.left;
				int desH=rect.bottom-rect.top;
				SetStretchBltMode(Hdc,COLORONCOLOR);
				if (desH==h&&desW==w)
				{
					StretchDIBits(Hdc,0,0,w,h,0,0,w,h,pData,&info,DIB_RGB_COLORS,SRCCOPY);
				}
				else
				{
					float fScale=(float)(w*desH)/(float)(h*desW);
					if (fScale>1.0f)
					{
						desH=(int)(desH/fScale);
					}
					else
					{
						desW=(int)(desW*fScale);
					}
					StretchDIBits(Hdc,0,0,desW,desH,0,0,w,h,pData,&info,DIB_RGB_COLORS,SRCCOPY);
				}
				
				if (freeImage)
				{
					FreeImage_Unload(freeImage);
					freeImage=NULL;
				}

				
			}

			// We're done with the texture so unlock it
			pTexture->UnlockRect(0);

			// Release the frame
			myPara->pNuiSensor->NuiImageStreamReleaseFrame(myPara->hColorStreamHandle, &imageFrame);
		}
	}
	
}
注意bmp格式像素的位置,需要上下颠倒位图数据(红色部分)才能正常的显示,否则显示的图像是倒立的。

运行结果如下,对话框可以随意移动。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值