Kinect for Windows V2和V1对照开发___深度数据获取并用OpenCV2.4.10显示
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;
}
Kinect for Windows V2和V1对照开发___深度数据获取并用OpenCV2.4.10显示的更多相关文章
- Kinect for Windows V2和V1对照开发___彩色数据获取并用OpenCV2.4.10显示
V1彩色分辨率:640x480 V2彩色分辨率:1920x1080 1,打开彩色图像帧的方式 对于V1: 使用NuiImageStreamOpen方法打开 hr = m_PNuiSensor-> ...
- Kinect for Windows V2开发教程
教程 https://blog.csdn.net/openbug/article/details/80921437 Windows版Kinect SDK https://docs.microsoft. ...
- Kinect for Windows V2.0 新功能
系统要求: win8 or win8.1 硬件要求: 64位(x64)处理器 i7 2.5-GHz或更快的处理器 内置USB 3.0总线 4 GB RAM DX11图形适配器 外观: 第二代Kin ...
- Kinect For Windows V2开发日志一:开发环境的配置
算是正式进军Kinect了,前段时间学的东西现在就忘了,于是从此开始记录一下. 目前为止大部分的学习资料来自于Heresy的博客,写的非常优秀,清晰明了,十分感谢.开发语言为C++,应该会一直使用,但 ...
- Kinect For Windows V2开发日志八:侦测、追踪人体骨架
简介 Kinect一个很强大的功能就是它可以侦测到人体的骨骼信息并追踪,在Kinect V2的SDK 2.0中,它最多可以同时获取到6个人.每个人25个关节点的信息,并且通过深度摄像头,可以同时获取到 ...
- Kinect For Windows V2开发日志六:人体的轮廓的表示
Kinect中带了一种数据源,叫做BodyIndex,简单来说就是它利用深度摄像头识别出最多6个人体,并且用数据将属于人体的部分标记,将人体和背景区别开来.利用这一特性,就可以在环境中显示出人体的轮廓 ...
- Kinect For Windows V2开发日志五:使用OpenCV显示彩色图像及红外图像
彩色图像 #include <iostream> #include <Kinect.h> #include <opencv2\highgui.hpp> using ...
- Kinect For Windows V2开发日志九:侦测并绘制人体骨架
简介 在上一篇<侦测.追踪人体骨架>里,介绍了关节点的使用办法,这一篇记录将关节点与OpenCV结合的绘图方法. 代码 #include <iostream> #include ...
- Kinect For Windows V2开发日志七:照片合成与背景消除
上一篇里讲到了Kinect可以从环境中区分出人体来.因此可以利用这个功能,来把摄像头前的人合成进照片里,和利用Photoshop不同的是,这样合成进去的人是动态且实时的. 简单的思路 BodyInde ...
随机推荐
- [jobdu]树中两个结点的最低公共祖先
http://ac.jobdu.com/problem.php?pid=1509 此题最直观的方法是两次DFS,分别找到这两个节点的path,然后遍历path1和path2做比较,找到最后一个共同的元 ...
- 内存不足时Android 系统如何Kill进程
[转]内存不足时Android 系统如何Kill进程 大家其实都或多或少知道,Android系统有自已的任务管理器,当系统内存不足时,系统需要KILL一些进程(应用),以回收一部分资源,来保证系统仍可 ...
- 【HDOJ】2155 小黑的镇魂曲
线段树+SPFA最短路可以过.或者DP也能过.需要注意的是xl的范围是错的,测试用例中xl可能为0,他妈的,因为这个一直莫名其妙的wa.1. spfa建图增加一倍的点即可(讨论左端点和右端点). /* ...
- Oracle系列之游标
涉及到表的处理请参看原表结构与数据 Oracle建表插数据等等 游标: 1.目的 解决“ select * ”返回空.多行记录问题 但凡select,就可能多行结果集,也就需要用游标 2.原理 多行 ...
- WPF——控件之间的绑定
一.启动窗口 二.控件绑定(注意看光标的位置,一个是单向绑定,一个是双向绑定) 注意看单向绑定与双向绑定的绑定方法:
- SharePoint 2010 WSP包部署过程中究竟发生什么?
转:http://www.xue163.com/158/6/1585365.html 在SharePoint 2010中,我们可以使用Visual Studio 2010轻松创建WSP包来安装Web ...
- 一例胜千言,详谈SQL Sever数据库锁
1 前言 数据库大并发操作要考虑死锁和锁的性能问题.看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一 ...
- 用友U8账套的建立
第1步点击开始菜单进入系统管理模块 第2步点击系统菜单下的注册 第3步弹出登录系统对话框,操作员输入admin点确定 第4步点击权限菜单下的用户 第5步进入用户管理窗口,点击工具栏 ...
- POJ 2570
思路:floyd + 位运算.map[i][j]的二进制位前26位表示i到j路径里面字母a-z的存在情况,为1说明该字母存在,为0不存在. #include<iostream> #incl ...
- SQL经典题
1触发器的作用? 答:触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的.它可以强化约束,来维护数据的完整性和一致性, 可以跟踪数据库内的操作从而不允许未经许可的更新和变化.可以联级运算 ...