持续维护地址:http://guoming.me/kinect2-depth-opencv
这次带来Kinect for windows v2深度数据的显示~
总感觉微软的Kinect API越来越复杂了呢,为什么获取深度数据后,不能直接返回一个结构体啊。每次要调这么多函数获取一个一个小参数变量,。
代码在前,运行截图在后:
// DepthBasic-OpenCV.cpp : 定义控制台应用程序的入口点。 /**************************************************** 程序功能:Kinect V2深度数据用OpenCV显示 开发环境:win32控制台应用程序 x86程序 (程序类型) VisualStudio 2012 (开发工具) OpenCV2.4.10 (显示界面库 vc11库, http://guoming.me/opencv) KinectSDK-v2.0-PublicPreview1409-Setup (Kinect SDK驱动版本, http://guoming.me/kinect2) Windows 8.1 (操作系统) 博客文章:http://guoming.me/kinect2-depth-opencv 代码地址:https://github.com/guoming0000/KinectV2/tree/master/DepthBasic-OpenCV 开发人员:小明 开发时间:2014-10-20~ 2014-10-21 联系方式: [email protected] (邮箱,推荐联系方式) http://guoming.me (网站,体感资讯和知识汇总) http://weibo.com/guoming0000 (新浪微博,用于发布体感等科技资讯,请勿私信) ******************************************************/ #include "stdafx.h" #include "opencv2/opencv.hpp" #include <windows.h> #include <Kinect.h>// Kinect Header files using namespace cv; // Safe release for interfaces template<class Interface> inline void SafeRelease(Interface *& pInterfaceToRelease) { if (pInterfaceToRelease != NULL) { pInterfaceToRelease->Release(); pInterfaceToRelease = NULL; } } //定义Kinect方法类 class Kinect { public: static const int cDepthWidth = 512; static const int cDepthHeight = 424; Kinect(); ~Kinect(); HRESULT InitKinect();//初始化Kinect void Update();//更新数据 void ProcessDepth(const UINT16* pBuffer, int nWidth, int nHeight, USHORT nMinDepth, USHORT nMaxDepth);//处理得到的数据 private: IKinectSensor* m_pKinectSensor;// Current Kinect IDepthFrameReader* m_pDepthFrameReader;// Color reader RGBQUAD* m_pDepthRGBX; }; //主函数 int main() { Kinect kinect; kinect.InitKinect(); while(1) { kinect.Update(); if(waitKey(1) >= 0)//按下任意键退出 { break; } } return 0; } Kinect::Kinect() { m_pKinectSensor = NULL; m_pDepthFrameReader = NULL; m_pDepthRGBX = new RGBQUAD[cDepthWidth * cDepthHeight];// create heap storage for color pixel data in RGBX format } Kinect::~Kinect() { if (m_pDepthRGBX) { delete [] m_pDepthRGBX; m_pDepthRGBX = NULL; } SafeRelease(m_pDepthFrameReader);// done with color frame reader if (m_pKinectSensor) { m_pKinectSensor->Close();// close the Kinect Sensor } SafeRelease(m_pKinectSensor); } HRESULT Kinect::InitKinect() { HRESULT hr; hr = GetDefaultKinectSensor(&m_pKinectSensor); if (FAILED(hr)) { return hr; } if (m_pKinectSensor) { // Initialize the Kinect and get the depth reader IDepthFrameSource* pDepthFrameSource = NULL; hr = m_pKinectSensor->Open(); if (SUCCEEDED(hr)) { hr = m_pKinectSensor->get_DepthFrameSource(&pDepthFrameSource); } if (SUCCEEDED(hr)) { hr = pDepthFrameSource->OpenReader(&m_pDepthFrameReader); } SafeRelease(pDepthFrameSource); } if (!m_pKinectSensor || FAILED(hr)) { printf("No ready Kinect found! \n"); return E_FAIL; } return hr; } void Kinect::Update() { if (!m_pDepthFrameReader) { return; } IDepthFrame* pDepthFrame = NULL; HRESULT hr = m_pDepthFrameReader->AcquireLatestFrame(&pDepthFrame); if (SUCCEEDED(hr)) { IFrameDescription* pFrameDescription = NULL; int nWidth = 0; int nHeight = 0; USHORT nDepthMinReliableDistance = 0; USHORT nDepthMaxDistance = 0; UINT nBufferSize = 0; UINT16 *pBuffer = NULL; if (SUCCEEDED(hr)) { hr = pDepthFrame->get_FrameDescription(&pFrameDescription); } if (SUCCEEDED(hr)) { hr = pFrameDescription->get_Width(&nWidth); } if (SUCCEEDED(hr)) { hr = pFrameDescription->get_Height(&nHeight); } if (SUCCEEDED(hr)) { hr = pDepthFrame->get_DepthMinReliableDistance(&nDepthMinReliableDistance); } if (SUCCEEDED(hr)) { // In order to see the full range of depth (including the less reliable far field depth) // we are setting nDepthMaxDistance to the extreme potential depth threshold nDepthMaxDistance = USHRT_MAX; // Note: If you wish to filter by reliable depth distance, uncomment the following line. //// hr = pDepthFrame->get_DepthMaxReliableDistance(&nDepthMaxDistance); } if (SUCCEEDED(hr)) { hr = pDepthFrame->AccessUnderlyingBuffer(&nBufferSize, &pBuffer); } if (SUCCEEDED(hr)) { ProcessDepth( pBuffer, nWidth, nHeight, nDepthMinReliableDistance, nDepthMaxDistance); } SafeRelease(pFrameDescription); } SafeRelease(pDepthFrame); } void Kinect::ProcessDepth(const UINT16* pBuffer, int nWidth, int nHeight, USHORT nMinDepth, USHORT nMaxDepth) { // Make sure we've received valid data if (m_pDepthRGBX && pBuffer && (nWidth == cDepthWidth) && (nHeight == cDepthHeight)) { RGBQUAD* pRGBX = m_pDepthRGBX; // end pixel is start + width*height - 1 const UINT16* pBufferEnd = pBuffer + (nWidth * nHeight); while (pBuffer < pBufferEnd) { USHORT depth = *pBuffer; // To convert to a byte, we're discarding the most-significant // rather than least-significant bits. // We're preserving detail, although the intensity will "wrap." // Values outside the reliable depth range are mapped to 0 (black). // Note: Using conditionals in this loop could degrade performance. // Consider using a lookup table instead when writing production code. BYTE intensity = static_cast<BYTE>((depth >= nMinDepth) && (depth <= nMaxDepth) ? (depth % 256) : 0); pRGBX->rgbRed = intensity; pRGBX->rgbGreen = intensity; pRGBX->rgbBlue = intensity; ++pRGBX; ++pBuffer; } // Draw the data with OpenCV Mat DepthImage(nHeight, nWidth, CV_8UC4, m_pDepthRGBX); Mat show = DepthImage.clone(); imshow("DepthImage", show); } }