kinect 2.0开发笔记之一

        网上有很多kinect的开发教程,写得不错,但是很多都不是基于C++的,其实我也觉得看它的example就可以了,但是它的example都是基于win32,所以我写的开发笔记全部针对与MFC结合,其实也没啥技术含量,但是看了之后可能相对来说比较简单一点吧。

       第一个就是最简单的彩色视频流的显示,在这个demo里面,显示其实是其次,关键你要采集到图像数据,存进OpenCV的Mat结构里面才是最重要的,下面给出关键的代码:

// ColorBasicDemoDlg.h : 头文件
//

#pragma once

#include "ImageRenderer.h"
// CColorBasicDemoDlg 对话框
class CColorBasicDemoDlg : public CDialogEx
{
	static const int        cColorWidth = 1920;
	static const int        cColorHeight = 1080;
// 构造
public:
	CColorBasicDemoDlg(CWnd* pParent = NULL);	// 标准构造函数
	~CColorBasicDemoDlg();

// 对话框数据
	enum { IDD = IDD_COLORBASICDEMO_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()

private:
	BOOL m_bSaveScreenshot;
	// Current Kinect
	IKinectSensor*          m_pKinectSensor;

	// Color reader
	IColorFrameReader*      m_pColorFrameReader;

	// Direct2D
	ImageRenderer*          m_pDrawColor;
	ID2D1Factory*           m_pD2DFactory;
	RGBQUAD*                m_pColorRGBX;

	HRESULT                 InitD2D();
	HRESULT                 InitializeDefaultSensor();
	void                    Update();
	HRESULT                 SaveBitmapToFile(BYTE* pBitmapBits, LONG lWidth, LONG lHeight, WORD wBitsPerPixel, LPCWSTR lpszFilePath);
public:
	afx_msg void OnTimer(UINT_PTR nIDEvent);
	afx_msg void OnBnClickedButton1();
};

        很多都是一些Kinect初始化的函数以及绘图初始化的函数

// ColorBasicDemoDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Resource.h "
#include "ColorBasicDemo.h"
#include "ColorBasicDemoDlg.h"
#include "afxdialogex.h"
#include <iostream>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#include"opencv/cv.hpp"
using namespace cv;
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CColorBasicDemoDlg 对话框



CColorBasicDemoDlg::CColorBasicDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CColorBasicDemoDlg::IDD, pParent),
	m_pKinectSensor(NULL),
	m_pColorFrameReader(NULL),
	m_pD2DFactory(NULL),
	m_pDrawColor(NULL),
	m_pColorRGBX(NULL),
	m_bSaveScreenshot(FALSE)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight];
}

CColorBasicDemoDlg::~CColorBasicDemoDlg()
{
	if (m_pDrawColor)
	{
		delete m_pDrawColor;
		m_pDrawColor = NULL;
	}

	if (m_pColorRGBX)
	{
		delete[] m_pColorRGBX;
		m_pColorRGBX = NULL;
	}

	SafeRelease(m_pD2DFactory);
	SafeRelease(m_pColorFrameReader);
	if (m_pKinectSensor)
	{
		m_pKinectSensor->Close();
	}
	SafeRelease(m_pKinectSensor);
}

void CColorBasicDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CColorBasicDemoDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON1, &CColorBasicDemoDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


BOOL CColorBasicDemoDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码
	InitD2D();
	InitializeDefaultSensor();
	SetTimer(1, 50, NULL);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CColorBasicDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

void CColorBasicDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}

}
HCURSOR CColorBasicDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CColorBasicDemoDlg::Update()
{
		if (!m_pColorFrameReader)
		{
			return ;
		}

		IColorFrame* pColorFrame = NULL;

		HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame);

		if (SUCCEEDED(hr))
		{
			IFrameDescription* pFrameDescription = NULL;
			int nWidth = 0;
			int nHeight = 0;
			ColorImageFormat imageFormat = ColorImageFormat_None;
			UINT nBufferSize = 0;
			RGBQUAD *pBuffer = NULL;

			if (SUCCEEDED(hr))
			{
				hr = pColorFrame->get_FrameDescription(&pFrameDescription);
			}

			if (SUCCEEDED(hr))
			{
				hr = pFrameDescription->get_Width(&nWidth);
			}

			if (SUCCEEDED(hr))
			{
				hr = pFrameDescription->get_Height(&nHeight);
			}

			if (SUCCEEDED(hr))
			{
				hr = pColorFrame->get_RawColorImageFormat(&imageFormat);
			}

			if (SUCCEEDED(hr))
			{
				if (imageFormat == ColorImageFormat_Bgra)
				{
					hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast<BYTE**>(&pBuffer));
				}
				else if (m_pColorRGBX)
				{
					pBuffer = m_pColorRGBX;
					nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD);
					hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast<BYTE*>(pBuffer), ColorImageFormat_Bgra);

					Mat ColorImage(nHeight, nWidth, CV_8UC4);
					pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast<BYTE*>(ColorImage.data), ColorImageFormat_Bgra);//把采集回来的图像数据给Mat数据结构
					Mat showImage;
					resize(ColorImage, showImage, Size(nWidth / 2, nHeight / 2));
					imshow("ColorImage", showImage);////imshow("ColorImage", ColorImage);
				}
				else
				{
					hr = E_FAIL;
				}
			}

			if (SUCCEEDED(hr))
			{
				// Make sure we've received valid data
				if (pBuffer && (nWidth == cColorWidth) && (nHeight == cColorHeight))
				{
					// Draw the data with Direct2D
					m_pDrawColor->Draw(reinterpret_cast<BYTE*>(pBuffer), cColorWidth * cColorHeight * sizeof(RGBQUAD));

					//Mat ColorImage(nHeight, nWidth, CV_8UC4, pBuffer);
					//Mat showImage;
					//resize(ColorImage, showImage, Size(nWidth / 2, nHeight / 2));
					//imshow("ColorImage", showImage);////imshow("ColorImage", ColorImage);
				}

				if (m_bSaveScreenshot)
				{
					HRESULT hr = SaveBitmapToFile(reinterpret_cast<BYTE*>(pBuffer), nWidth, nHeight, sizeof(RGBQUAD) * 8, L"D:/1.bmp");
					m_bSaveScreenshot = FALSE;
				}
			}

			SafeRelease(pFrameDescription);
		}

		SafeRelease(pColorFrame);

}

HRESULT CColorBasicDemoDlg::InitD2D()
{
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
	m_pDrawColor = new ImageRenderer();
	HRESULT hr = m_pDrawColor->Initialize(::GetDlgItem(m_hWnd, IDC_PIC), m_pD2DFactory, cColorWidth, cColorHeight, cColorWidth * sizeof(RGBQUAD));
	if (FAILED(hr))
	{
		wcout << _T("Failed to initialize the Direct2D draw device.") << endl;
	}

	return hr;
}

HRESULT CColorBasicDemoDlg::InitializeDefaultSensor()
{
	HRESULT hr;

	hr = GetDefaultKinectSensor(&m_pKinectSensor);
	if (FAILED(hr))
	{
		return hr;
	}

	if (m_pKinectSensor)
	{
		// Initialize the Kinect and get the color reader
		IColorFrameSource* pColorFrameSource = NULL;

		hr = m_pKinectSensor->Open();

		if (SUCCEEDED(hr))
		{
			hr = m_pKinectSensor->get_ColorFrameSource(&pColorFrameSource);
		}

		if (SUCCEEDED(hr))
		{
			hr = pColorFrameSource->OpenReader(&m_pColorFrameReader);
		}

		SafeRelease(pColorFrameSource);
	}

	if (!m_pKinectSensor || FAILED(hr))
	{
	   wcout << _T("No ready Kinect found!") << endl;
	   return E_FAIL;
	}

	return hr;
}


HRESULT CColorBasicDemoDlg::SaveBitmapToFile(BYTE* pBitmapBits, LONG lWidth, LONG lHeight, WORD wBitsPerPixel, LPCWSTR lpszFilePath)
{
	DWORD dwByteCount = lWidth * lHeight * (wBitsPerPixel / 8);

	BITMAPINFOHEADER bmpInfoHeader = { 0 };

	bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);  // Size of the header
	bmpInfoHeader.biBitCount = wBitsPerPixel;             // Bit count
	bmpInfoHeader.biCompression = BI_RGB;                    // Standard RGB, no compression
	bmpInfoHeader.biWidth = lWidth;                    // Width in pixels
	bmpInfoHeader.biHeight = -lHeight;                  // Height in pixels, negative indicates it's stored right-side-up
	bmpInfoHeader.biPlanes = 1;                         // Default
	bmpInfoHeader.biSizeImage = dwByteCount;               // Image size in bytes

	BITMAPFILEHEADER bfh = { 0 };

	bfh.bfType = 0x4D42;                                           // 'M''B', indicates bitmap
	bfh.bfOffBits = bmpInfoHeader.biSize + sizeof(BITMAPFILEHEADER);  // Offset to the start of pixel data
	bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage;        // Size of image + headers

	// Create the file on disk to write to
	HANDLE hFile = CreateFileW(lpszFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	// Return if error opening file
	if (NULL == hFile)
	{
		return E_ACCESSDENIED;
	}

	DWORD dwBytesWritten = 0;

	// Write the bitmap file header
	if (!WriteFile(hFile, &bfh, sizeof(bfh), &dwBytesWritten, NULL))
	{
		CloseHandle(hFile);
		return E_FAIL;
	}

	// Write the bitmap info header
	if (!WriteFile(hFile, &bmpInfoHeader, sizeof(bmpInfoHeader), &dwBytesWritten, NULL))
	{
		CloseHandle(hFile);
		return E_FAIL;
	}

	// Write the RGB Data
	if (!WriteFile(hFile, pBitmapBits, bmpInfoHeader.biSizeImage, &dwBytesWritten, NULL))
	{
		CloseHandle(hFile);
		return E_FAIL;
	}

	// Close the file
	CloseHandle(hFile);
	return S_OK;
}

void CColorBasicDemoDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	Update();
	CDialogEx::OnTimer(nIDEvent);
}


void CColorBasicDemoDlg::OnBnClickedButton1()
{
	// TODO:  在此添加控件通知处理程序代码
	m_bSaveScreenshot = TRUE;
}

       其实代码非常简单,显示视频流其实就是设置一个定时器去定时刷新屏幕而已。


你可能感兴趣的:(kinect 2.0开发笔记之一)