我是靠谱客的博主 能干毛豆,最近开发中收集的这篇文章主要介绍微软Kinect 1.7 附带ColorBasics-D2D示例程序基本解析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

先安装Kinect SDK;

如上图;需要安装2个安装文件;sdk,toolkit;然后可以获得示例代码;

运行程序需要安装Kinect传感器;

 

主文件代码;

//------------------------------------------------------------------------------
// <copyright file="ColorBasics.cpp" company="Microsoft">
//
Copyright (c) Microsoft Corporation.
All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
#include "stdafx.h"
#include <strsafe.h>
#include "ColorBasics.h"
#include "resource.h"
/// <summary>
/// Entry point for the application
/// </summary>
/// <param name="hInstance">handle to the application instance</param>
/// <param name="hPrevInstance">always 0</param>
/// <param name="lpCmdLine">command line arguments</param>
/// <param name="nCmdShow">whether to display minimized, maximized, or normally</param>
/// <returns>status</returns>
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
CColorBasics application;
application.Run(hInstance, nCmdShow);
}
/// <summary>
/// Constructor
/// </summary>
CColorBasics::CColorBasics() :
m_pD2DFactory(NULL),
m_pDrawColor(NULL),
m_hNextColorFrameEvent(INVALID_HANDLE_VALUE),
m_pColorStreamHandle(INVALID_HANDLE_VALUE),
m_bSaveScreenshot(false),
m_pNuiSensor(NULL)
{
}
/// <summary>
/// Destructor
/// </summary>
CColorBasics::~CColorBasics()
{
if (m_pNuiSensor)
{
m_pNuiSensor->NuiShutdown();
}
if (m_hNextColorFrameEvent != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hNextColorFrameEvent);
}
// clean up Direct2D renderer
delete m_pDrawColor;
m_pDrawColor = NULL;
// clean up Direct2D
SafeRelease(m_pD2DFactory);
SafeRelease(m_pNuiSensor);
}
/// <summary>
/// Creates the main window and begins processing
/// </summary>
/// <param name="hInstance">handle to the application instance</param>
/// <param name="nCmdShow">whether to display minimized, maximized, or normally</param>
int CColorBasics::Run(HINSTANCE hInstance, int nCmdShow)
{
MSG
msg = {0};
WNDCLASS
wc;
// Dialog custom window class
ZeroMemory(&wc, sizeof(wc));
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.cbWndExtra
= DLGWINDOWEXTRA;
wc.hInstance
= hInstance;
wc.hCursor
= LoadCursorW(NULL, IDC_ARROW);
wc.hIcon
= LoadIconW(hInstance, MAKEINTRESOURCE(IDI_APP));
wc.lpfnWndProc
= DefDlgProcW;
wc.lpszClassName = L"ColorBasicsAppDlgWndClass";
if (!RegisterClassW(&wc))
{
return 0;
}
// Create main application window
HWND hWndApp = CreateDialogParamW(
hInstance,
MAKEINTRESOURCE(IDD_APP),
NULL,
(DLGPROC)CColorBasics::MessageRouter,
reinterpret_cast<LPARAM>(this));
// Show window
ShowWindow(hWndApp, nCmdShow);
const int eventCount = 1;
HANDLE hEvents[eventCount];
// Main message loop
while (WM_QUIT != msg.message)
{
hEvents[0] = m_hNextColorFrameEvent;
// Check to see if we have either a message (by passing in QS_ALLINPUT)
// Or a Kinect event (hEvents)
// Update() will check for Kinect events individually, in case more than one are signalled
DWORD dwEvent = MsgWaitForMultipleObjects(eventCount, hEvents, FALSE, INFINITE, QS_ALLINPUT);
// Check if this is an event we're waiting on and not a timeout or message
if (WAIT_OBJECT_0 == dwEvent)
{
Update();
}
if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
// If a dialog message will be taken care of by the dialog proc
if ((hWndApp != NULL) && IsDialogMessageW(hWndApp, &msg))
{
continue;
}
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
return static_cast<int>(msg.wParam);
}
/// <summary>
/// Main processing function
/// </summary>
void CColorBasics::Update()
{
if (NULL == m_pNuiSensor)
{
return;
}
if ( WAIT_OBJECT_0 == WaitForSingleObject(m_hNextColorFrameEvent, 0) )
{
ProcessColor();
}
}
/// <summary>
/// Handles window messages, passes most to the class instance to handle
/// </summary>
/// <param name="hWnd">window message is for</param>
/// <param name="uMsg">message</param>
/// <param name="wParam">message data</param>
/// <param name="lParam">additional message data</param>
/// <returns>result of message processing</returns>
LRESULT CALLBACK CColorBasics::MessageRouter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CColorBasics* pThis = NULL;
if (WM_INITDIALOG == uMsg)
{
pThis = reinterpret_cast<CColorBasics*>(lParam);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
}
else
{
pThis = reinterpret_cast<CColorBasics*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
}
if (pThis)
{
return pThis->DlgProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
/// <summary>
/// Handle windows messages for the class instance
/// </summary>
/// <param name="hWnd">window message is for</param>
/// <param name="uMsg">message</param>
/// <param name="wParam">message data</param>
/// <param name="lParam">additional message data</param>
/// <returns>result of message processing</returns>
LRESULT CALLBACK CColorBasics::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Bind application window handle
m_hWnd = hWnd;
// Init Direct2D
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
// Create and initialize a new Direct2D image renderer (take a look at ImageRenderer.h)
// We'll use this to draw the data we receive from the Kinect to the screen
m_pDrawColor = new ImageRenderer();
HRESULT hr = m_pDrawColor->Initialize(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), m_pD2DFactory, cColorWidth, cColorHeight, cColorWidth * sizeof(long));
if (FAILED(hr))
{
SetStatusMessage(L"Failed to initialize the Direct2D draw device.");
}
// Look for a connected Kinect, and create it if found
CreateFirstConnected();
}
break;
// If the titlebar X is clicked, destroy app
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
// Quit the main message pump
PostQuitMessage(0);
break;
// Handle button press
case WM_COMMAND:
// If it was for the screenshot control and a button clicked event, save a screenshot next frame
if (IDC_BUTTON_SCREENSHOT == LOWORD(wParam) && BN_CLICKED == HIWORD(wParam))
{
m_bSaveScreenshot = true;
}
break;
}
return FALSE;
}
/// <summary>
/// Create the first connected Kinect found
/// </summary>
/// <returns>indicates success or failure</returns>
HRESULT CColorBasics::CreateFirstConnected()
{
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_pNuiSensor = pNuiSensor;
break;
}
// This sensor wasn't OK, so release it since we're not using it
pNuiSensor->Release();
}
if (NULL != m_pNuiSensor)
{
// Initialize the Kinect and specify that we'll be using color
hr = m_pNuiSensor->NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR);
if (SUCCEEDED(hr))
{
// Create an event that will be signaled when color data is available
m_hNextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// Open a color image stream to receive color frames
hr = m_pNuiSensor->NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_640x480,
0,
2,
m_hNextColorFrameEvent,
&m_pColorStreamHandle);
}
}
if (NULL == m_pNuiSensor || FAILED(hr))
{
SetStatusMessage(L"No ready Kinect found!");
return E_FAIL;
}
return hr;
}
/// <summary>
/// Get the name of the file where screenshot will be stored.
/// </summary>
/// <param name="screenshotName">
/// [out] String buffer that will receive screenshot file name.
/// </param>
/// <param name="screenshotNameSize">
/// [in] Number of characters in screenshotName string buffer.
/// </param>
/// <returns>
/// S_OK on success, otherwise failure code.
/// </returns>
HRESULT GetScreenshotFileName(wchar_t *screenshotName, UINT screenshotNameSize)
{
wchar_t *knownPath = NULL;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, 0, NULL, &knownPath);
if (SUCCEEDED(hr))
{
// Get the time
wchar_t timeString[MAX_PATH];
GetTimeFormatEx(NULL, 0, NULL, L"hh'-'mm'-'ss", timeString, _countof(timeString));
// File name will be KinectSnapshot-HH-MM-SS.wav
StringCchPrintfW(screenshotName, screenshotNameSize, L"%s\KinectSnapshot-%s.bmp", knownPath, timeString);
}
CoTaskMemFree(knownPath);
return hr;
}
/// <summary>
/// Handle new color data
/// </summary>
/// <returns>indicates success or failure</returns>
void CColorBasics::ProcessColor()
{
HRESULT hr;
NUI_IMAGE_FRAME imageFrame;
// Attempt to get the color frame
hr = m_pNuiSensor->NuiImageStreamGetNextFrame(m_pColorStreamHandle, 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)
{
// Draw the data with Direct2D
m_pDrawColor->Draw(static_cast<BYTE *>(LockedRect.pBits), LockedRect.size);
// If the user pressed the screenshot button, save a screenshot
if (m_bSaveScreenshot)
{
WCHAR statusMessage[cStatusMessageMaxLen];
// Retrieve the path to My Photos
WCHAR screenshotPath[MAX_PATH];
GetScreenshotFileName(screenshotPath, _countof(screenshotPath));
// Write out the bitmap to disk
hr = SaveBitmapToFile(static_cast<BYTE *>(LockedRect.pBits), cColorWidth, cColorHeight, 32, screenshotPath);
if (SUCCEEDED(hr))
{
// Set the status bar to show where the screenshot was saved
StringCchPrintf( statusMessage, cStatusMessageMaxLen, L"Screenshot saved to %s", screenshotPath);
}
else
{
StringCchPrintf( statusMessage, cStatusMessageMaxLen, L"Failed to write screenshot to %s", screenshotPath);
}
SetStatusMessage(statusMessage);
// toggle off so we don't save a screenshot again next frame
m_bSaveScreenshot = false;
}
}
// We're done with the texture so unlock it
pTexture->UnlockRect(0);
// Release the frame
m_pNuiSensor->NuiImageStreamReleaseFrame(m_pColorStreamHandle, &imageFrame);
}
/// <summary>
/// Set the status bar message
/// </summary>
/// <param name="szMessage">message to display</param>
void CColorBasics::SetStatusMessage(WCHAR * szMessage)
{
SendDlgItemMessageW(m_hWnd, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szMessage);
}
/// <summary>
/// Save passed in image data to disk as a bitmap
/// </summary>
/// <param name="pBitmapBits">image data to save</param>
/// <param name="lWidth">width (in pixels) of input image data</param>
/// <param name="lHeight">height (in pixels) of input image data</param>
/// <param name="wBitsPerPixel">bits per pixel of image data</param>
/// <param name="lpszFilePath">full file path to output bitmap to</param>
/// <returns>indicates success or failure</returns>
HRESULT CColorBasics::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;
}

首先看一下,包含stdafx.h,Resource.h;这是一个VC++项目;但不是MFC项目;
程序是以wWinMain入口;

Run函数里面主要是注册窗口类;创建窗口,消息循环;
CreateDialogParam函数,根据对话框模板资源创建一个无模式的对话框。在显示对话框之前,函数把一个应用程序定义的值作为WM_INITDIALOG消息IParam参数传到对话框过程应用程序可用此值来初始化对话框控制。

在stdafx.h里,有
#include <d2d1.h>
#pragma comment ( lib, "d2d1.lib" )
也就是此程序将使用微软DirectX 2D;

在初始化对话框(WM_INITDIALOG)的时候,执行
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
创建D2D工厂;

在CreateFirstConnected函数里主要是获取连接了几个kinect传感器(NuiGetSensorCount);
然后调用NuiCreateSensorByIndex创建传感器对象;

主要的功能是在ProcessColor函数里;
NUI_IMAGE_FRAME imageFrame是一个图像帧;
获取了图像帧以后调用D2D的功能来在窗口上进行绘制;
然后保存屏幕截图到文件;

这是kinect的基本C++示例;

最后

以上就是能干毛豆为你收集整理的微软Kinect 1.7 附带ColorBasics-D2D示例程序基本解析的全部内容,希望文章能够帮你解决微软Kinect 1.7 附带ColorBasics-D2D示例程序基本解析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部