V1深度分辨率:320x240
V2深度分辨率:512x424
1, 打开深度图像帧的方式
对于V1:
hr = m_PNuiSensor->NuiImageStreamOpen(
NUI_IMAGE_TYPE_DEPTH,NUI_IMAGE_RESOLUTION_320x240,0, 2,
m_hNextDepthFrameEvent, &m_hDepthStreamHandle);
if( FAILED( hr ) )
{
cout<<"Could notopen image stream video"<<endl;
return hr;
}
这种方式可以设置分辨率
对于V2:
// Initialize the Kinect and get the depth reader
IDepthFrameSource* pDepthFrameSource =NULL;
首先使用 hr = m_pKinectSensor->Open();//打开Kinect
if (SUCCEEDED(hr))
{
hr =m_pKinectSensor->get_DepthFrameSource(&pDepthFrameSource);
}
方法get_DepthFrameSource打开深度帧的源。
然后使用 if (SUCCEEDED(hr))
{
hr =pDepthFrameSource->OpenReader(&m_pDepthFrameReader);
}
SafeRelease(pDepthFrameSource);
方法OpenReader打开深度帧读取器。
2, 更新深度帧的方式
对于V1:使用NuiImageStreamGetNextFrame方法
NuiImageStreamGetNextFrame(m_hDepthStreamHandle,0, &pImageFrame);;//得到该帧数据</span>
对于V2:使用AcquireLatestFrame方法
if (!m_pDepthFrameReader)
{
return;
}
IDepthFrame* pDepthFrame = NULL;
HRESULT hr =m_pDepthFrameReader->AcquireLatestFrame(&pDepthFrame);
3, 数据的处理方式
对于V1:这种数据获取方式比较明朗看到数据内部结构,
INuiFrameTexture *pTexture =pImageFrame->pFrameTexture;
NUI_LOCKED_RECT LockedRect;
pTexture->LockRect(0, &LockedRect,NULL, 0);
RGBQUAD q;
if( LockedRect.Pitch != 0 )
{
//BYTE * pBuffer = (BYTE*)(LockedRect.pBits);
//INT size = LockedRect.size;
//memcpy_s(m_pDepthBuffer,size, pBuffer, size);
//USHORT* pBufferRun =reinterpret_cast<USHORT*>(m_pDepthBuffer);
for (int i=0; i<image.rows; i++)
{
//USHORT* ptr = (USHORT*)depthIndexImage->height;
//USHORT* pDepthRow =(USHORT*)(i);
//BYTE * pBuffer = (BYTE*)(LockedRect.pBits);
uchar *ptr =image.ptr<uchar>(i); //第i行的指针
uchar * pBuffer =(uchar*)(LockedRect.pBits)+i*LockedRect.Pitch;
USHORT* pBufferRun =(USHORT*) pBuffer;//注意这里需要转换,因为每个数据是2个字节,存储的同上面的颜色信息不一样,这里是2个字节一个信息,不能再用BYTE,转化为USHORT
for (int j=0; j<image.cols; j++)
{
//ptr[j] = 255 -(BYTE)(256*pBufferRun[j]/0x0fff);//直接将数据归一化处理
//ptr[j] = pBufferRun[i * 640 + j];
// ptr[j] = 255 -(uchar)(256 * pBufferRun[j]/0x0fff); //直接将数据归一化处理
int player =pBufferRun[j]&7;
int data =(pBufferRun[j]&0xfff8) >> 3;
uchar imageData = 255-(uchar)(256*data/0x0fff);
q.rgbBlue = q.rgbGreen =q.rgbRed = 0;
switch(player)
{
case 0:
q.rgbRed = imageData /2;
q.rgbBlue = imageData / 2;
q.rgbGreen = imageData/ 2;
break;
case 1:
q.rgbRed =imageData;
break;
case 2:
q.rgbGreen =imageData;
break;
case 3:
q.rgbRed = imageData /4;
q.rgbGreen = q.rgbRed*4; //这里利用乘的方法,而不用原来的方法可以避免不整除的情况
q.rgbBlue =q.rgbRed*4; //可以在后面的getTheContour()中配合使用,避免遗漏一些情况
break;
case 4:
q.rgbBlue = imageData /4;
q.rgbRed = q.rgbBlue*4;
q.rgbGreen =q.rgbBlue*4;
break;
case 5:
q.rgbGreen = imageData/ 4;
q.rgbRed =q.rgbGreen*4;
q.rgbBlue =q.rgbGreen*4;
break;
case 6:
q.rgbRed = imageData /2;
q.rgbGreen = imageData/ 2;
q.rgbBlue =q.rgbGreen*2;
break;
case 7:
q.rgbRed = 255 - (imageData / 2 );
q.rgbGreen = 255 - (imageData / 2 );
q.rgbBlue = 255 - (imageData / 2 );
}
ptr[3*j] = q.rgbBlue;
ptr[3*j+1] = q.rgbGreen;
ptr[3*j+2] = q.rgbRed;
}
}
imshow("depthImage",image); //显示图像
得到的最终形式可以用OpenCV显示。
对于V2:
RGBQUAD* m_pDepthRGBX;;//深度数据存储位置
m_pDepthRGBX(NULL)//构造函数初始化
// create heap storage for color pixel data in RGBXformat
m_pDepthRGBX = new RGBQUAD[cDepthWidth *cDepthHeight];
//下边就是AcquireLatestFrame之后处理数据
INT64 nTime = 0;
IFrameDescription* pFrameDescription =NULL;
int nWidth = 0;
int nHeight = 0;
USHORTnDepthMinReliableDistance = 0;
USHORT nDepthMaxDistance =0;
UINT nBufferSize = 0;
UINT16 *pBuffer = NULL;
if (SUCCEEDED(hr))
{
hr =pDepthFrame->AccessUnderlyingBuffer(&nBufferSize, &pBuffer);
}
if (SUCCEEDED(hr))
{
ProcessDepth(nTime, pBuffer,nWidth, nHeight, nDepthMinReliableDistance, nDepthMaxDistance);
}
4,OpenCV显示
int width = 0;
int height = 0;
pDescription->get_Width( &width ); // 512
pDescription->get_Height( &height ); // 424
unsigned int bufferSize = width * height * sizeof( unsigned short );
// Range
unsigned short min = 0;
unsigned short max = 0;
pDepthSource->get_DepthMinReliableDistance( &min ); // 500
pDepthSource->get_DepthMaxReliableDistance( &max ); // 4500
cout << "Range : " << min << " - " << max << std::endl;
//创建尺寸为height x width 的1通道8位图像
Mat bufferMat( height, width, CV_16UC1 );
Mat depthMat( height, width, CV_8UC1 );
while( 1 ){
// 更新深度帧
IDepthFrame* pDepthFrame = nullptr;
hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );
if( SUCCEEDED( hResult ) ){
hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );
if( SUCCEEDED( hResult ) ){
bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f, 255.0f );
}
}
SafeRelease( pDepthFrame );
imshow( "Depth", depthMat );
5,V2+VS2012+OpenCV代码
#include <Windows.h>
#include <Kinect.h>
#include <opencv2/opencv.hpp>
#include <cstdlib>
using namespace std;
using namespace cv;
//释放接口需要自己定义
template<class Interface>
inline void SafeRelease( Interface *& pInterfaceToRelease )
{
if( pInterfaceToRelease != NULL ){
pInterfaceToRelease->Release();
pInterfaceToRelease = NULL;
}
}
int main( int argc, char **argv[] )
{
//OpenCV中开启CPU的硬件指令优化功能函数
setUseOptimized( true );
// 打开kinect
IKinectSensor* pSensor;
HRESULT hResult = S_OK;
hResult = GetDefaultKinectSensor( &pSensor );
if( FAILED( hResult ) ){
cerr << "Error : GetDefaultKinectSensor" << std::endl;
return -1;
}
hResult = pSensor->Open();
if( FAILED( hResult ) ){
cerr << "Error : IKinectSensor::Open()" << std::endl;
return -1;
}
// 深度帧源
IDepthFrameSource* pDepthSource;
hResult = pSensor->get_DepthFrameSource( &pDepthSource );
if( FAILED( hResult ) ){
cerr << "Error : IKinectSensor::get_DepthFrameSource()" << std::endl;
return -1;
}
// 深度帧读取
IDepthFrameReader* pDepthReader;
hResult = pDepthSource->OpenReader( &pDepthReader );
if( FAILED( hResult ) ){
cerr << "Error : IDepthFrameSource::OpenReader()" << std::endl;
return -1;
}
// Description
IFrameDescription* pDescription;
hResult = pDepthSource->get_FrameDescription( &pDescription );
if( FAILED( hResult ) ){
cerr << "Error : IDepthFrameSource::get_FrameDescription()" << std::endl;
return -1;
}
int width = 0;
int height = 0;
pDescription->get_Width( &width ); // 512
pDescription->get_Height( &height ); // 424
unsigned int bufferSize = width * height * sizeof( unsigned short );
// Range
unsigned short min = 0;
unsigned short max = 0;
pDepthSource->get_DepthMinReliableDistance( &min ); // 500
pDepthSource->get_DepthMaxReliableDistance( &max ); // 4500
cout << "Range : " << min << " - " << max << std::endl;
//创建尺寸为height x width 的1通道8位图像
Mat bufferMat( height, width, CV_16UC1 );
Mat depthMat( height, width, CV_8UC1 );
while( 1 ){
// 更新深度帧
IDepthFrame* pDepthFrame = nullptr;
hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );
if( SUCCEEDED( hResult ) ){
hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );
if( SUCCEEDED( hResult ) ){
bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f, 255.0f );
}
}
SafeRelease( pDepthFrame );
imshow( "Depth", depthMat );
if( cv::waitKey( 30 ) == VK_ESCAPE ){
break;
}
}
SafeRelease( pDepthSource );
SafeRelease( pDepthReader );
SafeRelease( pDescription );
if( pSensor ){
pSensor->Close();
}
SafeRelease( pSensor );
return 0;
}