wowgm可以直接查到超能游戏者1电影的id吗

kinect(7)
Kinect开发学习笔记之(六)带游戏者ID的深度数据的提取
我的Kinect开发平台是:
Win7x86 + VS2010 + Kinect for Windows SDK v1.6 + OpenCV2.3.0
开发环境的搭建见上一文:
本学习笔记以下面的方式组织:编程前期分析、代码与注释和重要代码解析三部分。
要实现目标:通过微软的SDK提取带游戏者ID的深度数据并用OpenCV显示,不同用户,显示的颜色不同
一、编程前期分析
&&&&& 我们在上一文中提到的是不带游戏者ID的深度数据的提取,具体见下面:
Kinect开发学习笔记之(五)不带游戏者ID的深度数据的提取
&&&&&& 首先,Kinect传感器核心是发射红外结构光,并探测红外光反射,从而可以计算出视场范围内每一个像素的深度值。从深度数据中最先提取出来的是物体主体和形状,以及每一个像素点的游戏者索引信息。然后用这些形状信息来匹配人体的各个部分,最后计算匹配出来的各个关节在人体中的位置。而Kinect具有一次识别多达6个游戏者的能力,并能跟踪最多两个人的骨骼(对于XBOX360来说,就是可以同时两个人玩游戏了)。
&&&&& 可能有点奇怪哦,这一个带游戏者ID,一个不带,还得那么严肃地给它单独开一文来学习。究竟啥来头啊。呵呵,实际上,既然微软提供了这种差别,那么它的存在肯定是有意义的,所谓存在即合理嘛。多个选择嘛。需要用到游戏者ID的时候就用,不需要的时候就不用费那么大劲。也不能说费劲,就是使用游戏者ID的时候,我们需要再做一些工作,去把不同游戏者的轮廓找出来,然后为了区别,标上不同的颜色,这就是本文想实现的。有点啰嗦了。
&&&&& 上一文中,我们讲到,Kinect的深度图像数据有两种格式,一种是带游戏者ID的,一种是不带的。两种格式都是用两个字节来保存一个像素的深度值,而两方式的差别在于:
(1)唯一表示深度值:那么像素的低12位表示一个深度值,高4位未使用;
(2)既表示深度值又含有游戏者ID:Kinect为每一个追踪到的游戏者编号作为索引。而这个方式中,像素值的高13位保存了深度值,低三位保存用户序号,7 ()这个位掩码能够帮助我们从深度数据中获取到游戏者索引值。
&&&&&& 要注意的是,不要对特定的游戏者索引位进行编码,因为他们是会变化的。实际的游戏者索引位并不总是和Kinect前面的游戏者编号一致。啥意思呢?例如,Kinect视野中只有一个游戏者,但是返回的游戏者索引位值可能是3或者4。也就是说有时候第一个游戏者的游戏者索引位可能不是1。还有,如果走进Kinect视野再走出去,然后再走进来,虽然你还是你,但是Kinect给你的索引ID可能就和原来的不一样了,例如之前返回的索引位是1,走出去后再次走进,可能索引位变为其他值了。所以开发Kinect应用程序的时候应该注意到这一点。
&&&&& 说得有点乱哦,咱们还是看代码吧。
二、代码与注释
#include &windows.h&&
#include &iostream& & #include &NuiApi.h&&
#include &opencv2/opencv.hpp&&
& using namespace&
using namespace&
RGBQUAD shortDepth2RGBquad( USHORT depthID )&
&&& USHORT realDepth = (depthID & 0xfff8) && 3;
& &&& USHORT player =& depthID & 0x07 ;&
& && &&& &
&&& BYTE depth = 255 - (BYTE)(256*realDepth/0x0fff);&&
&& &&& RGBQUAD&& &&& q.rgbRed = q.rgbBlue = q.rgbGreen = 0;&& && &&& &
&&& switch( player )&&
&&& {&& &&&&&&& case 0:&&&
&&&&&&&&&&& q.rgbRed = depth / 2;&& &&&&&&&&&&& q.rgbBlue = depth / 2;&& &&&&&&&&&&& q.rgbGreen = depth / 2;&& &&&&&&&&&&& break;&&
&&&&&&& case 1:&& &&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& break;&& &&&&&&& case 2:&&
&&&&&&&&&&& q.rgbGreen =&&& &&&&&&&&&&& break;&&
&&&&&&& case 3:&& &&&&&&&&&&& q.rgbRed = depth / 4;&& &&&&&&&&&&& q.rgbGreen =&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&& &&&&&&& case 4:&&
&&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& q.rgbGreen =&& &&&&&&&&&&& q.rgbBlue = depth / 4;&& &&&&&&&&&&& break;&&
&&&&&&& case 5:&& &&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& q.rgbGreen = depth / 4;&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&& &&&&&&& case 6:&&
&&&&&&&&&&& q.rgbRed = depth / 2;&& &&&&&&&&&&& q.rgbGreen = depth / 2;&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&&
&&&&&&& case 7:&& &&&&&&&&&&& q.rgbRed = 255 - ( depth / 2 );&& &&&&&&&&&&& q.rgbGreen = 255 - ( depth / 2 );&& &&&&&&&&&&& q.rgbBlue = 255 - ( depth / 2 );&& &&&&&&& }&& && &&& return&& }& & int main(int argc,
char *argv[])& {& &&& M& &&& image.create(240, 320, CV_8UC3);&& && &&& &
&&& HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX);&&
&&& if (FAILED(hr))&& &&& {&& &&&&&&& cout&&&NuiInitialize failed&&&&&
&&&&&&& return&&
&&& }&& & &&& & &&& &
&&& HANDLE nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );&
&&& HANDLE depthStreamHandle = NULL;
& && &&& &
&&& hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240,&&
&&&&&&&&&&&&&&&&&&&&&&&&&&& 0, 2, nextColorFrameEvent, &depthStreamHandle);&&
&&& if( FAILED( hr ) )& &&& {&& &&&&&&& cout&&&Could not open color image stream video&&&&&
&&&&&&& NuiShutdown();&& &&&&&&& return&& &&& }& &&& namedWindow(&depthImage&, CV_WINDOW_AUTOSIZE);&
&& &&& & &&& while(1)&& &&& {&& &&&&&&& const NUI_IMAGE_FRAME * pImageFrame = NULL;&&
& &&&&&&& &
&&&&&&& if (WaitForSingleObject(nextColorFrameEvent, INFINITE)==0)&&
&&&&&&& {&& &&&&&&&&&&& &
&&&&&&&&&&& hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame);&&
&&&&&&&&&&& if (FAILED(hr))&
&&&&&&&&&&& {& &&&&&&&&&&&&&&& cout&&&Could not get depth image&&&&&
&&&&&&&&&&&&&&& NuiShutdown();& &&&&&&&&&&&&&&& return -1;& &&&&&&&&&&& }& & &&&&&&&&&&& INuiFrameTexture * pTexture = pImageFrame-&pFrameT&
&&&&&&&&&&& NUI_LOCKED_RECT LockedR& & &&&&&&&&&&& &
&&&&&&&&&&& &
&&&&&&&&&&& pTexture-&LockRect(0, &LockedRect, NULL, 0);&& &&&&&&&&&&& &
&&&&&&&&&&& if( LockedRect.Pitch != 0 )&&
&&&&&&&&&&& {&& &&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&& for (int i=0; i&image. i++)&&
&&&&&&&&&&&&&&& {& &&&&&&&&&&&&&&&&&&& uchar *ptr = image.ptr&uchar&(i);& & &&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&& uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.P&
&&&&&&&&&&&&&&&&&&& USHORT * pBuffer = (USHORT*) pBufferR&
&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&& for (int j=0; j&image. j++)&&
&&&&&&&&&&&&&&&&&&& {& &&&&&&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&&&&&& RGBQUAD rgb = shortDepth2RGBquad(pBuffer[j]);&
&&&&&&&&&&&&&&&&&&&&&&& ptr[3*j] = rgb.rgbB&& &&&&&&&&&&&&&&&&&&&&&&& ptr[3*j+1] = rgb.rgbG&&
&&&&&&&&&&&&&&&&&&&&&&& ptr[3*j+2] = rgb.rgbR&& &&&&&&&&&&&&&&&&&&& }&& &&&&&&&&&&&&&&& }&& &&&&&&&&&&&&&&& imshow(&depthImage&, image);
& &&&&&&&&&&& }&& &&&&&&&&&&& else&&
&&&&&&&&&&& {&& &&&&&&&&&&&&&&& cout&&&Buffer length of received texture is bogus\r\n&&&&&
&&&&&&&&&&& }& & &&&&&&&&&&& &
&&&&&&&&&&& pTexture-&UnlockRect(0);& &&&&&&&&&&& &
&&&&&&&&&&& NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame );&&
&&&&&&& }&& &&&&&&& if (cvWaitKey(20) == 27)&&
&&&&&&&&&&& break;&& &&& }&& &&& & &&& NuiShutdown();&& &&& return 0;& }&
#include &windows.h&
#include &iostream&
#include &NuiApi.h&
#include &opencv2/opencv.hpp&
//处理深度数据的每一个像素,如果属于同一个用户的ID,那么像素就标为同种颜色,不同的用户,
//其ID不一样,颜色的标示也不一样,如果不属于某个用户的像素,那么就采用原来的深度值
RGBQUAD shortDepth2RGBquad( USHORT depthID )
//每像素共16bit的信息,其中最低3位是ID(所捕捉到的人的ID),剩下的13位才是信息
USHORT realDepth = (depthID & 0xfff8) && 3; //提取距离信息,高13位
USHORT player =
depthID & 0x07 ;
//提取ID信息 ,低3位
//因为提取的信息是距离信息,为了便于显示,这里归一化为0-255
BYTE depth = 255 - (BYTE)(256*realDepth/0x0fff);
q.rgbRed = q.rgbBlue = q.rgbGreen = 0;
//RGB三个通道的值都是相等的话,就是灰度的
//Kinect系统能够处理辨识传感器前多至6个人物的信息,但同一时刻最多只有2个玩家可被追踪(即骨骼跟踪)
switch( player )
q.rgbRed = depth / 2;
q.rgbBlue = depth / 2;
q.rgbGreen = depth / 2;
q.rgbRed =
q.rgbGreen =
q.rgbRed = depth / 4;
q.rgbGreen =
q.rgbBlue =
q.rgbRed =
q.rgbGreen =
q.rgbBlue = depth / 4;
q.rgbRed =
q.rgbGreen = depth / 4;
q.rgbBlue =
q.rgbRed = depth / 2;
q.rgbGreen = depth / 2;
q.rgbBlue =
q.rgbRed = 255 - ( depth / 2 );
q.rgbGreen = 255 - ( depth / 2 );
q.rgbBlue = 255 - ( depth / 2 );
int main(int argc, char *argv[])
image.create(240, 320, CV_8UC3);
//1、初始化NUI,注意这里是DEPTH_AND_PLAYER_INDEX
HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX);
if (FAILED(hr))
cout&&&NuiInitialize failed&&&
//2、定义事件句柄
//创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据
HANDLE nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
HANDLE depthStreamHandle = NULL; //保存图像数据流的句柄,用以提取数据
//3、打开KINECT设备的彩色图信息通道,并用depthStreamHandle保存该流的句柄,以便于以后读取
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240,
0, 2, nextColorFrameEvent, &depthStreamHandle);
if( FAILED( hr ) )//判断是否提取正确
cout&&&Could not open color image stream video&&&
NuiShutdown();
namedWindow(&depthImage&, CV_WINDOW_AUTOSIZE);
//4、开始读取深度数据
const NUI_IMAGE_FRAME * pImageFrame = NULL;
//4.1、无限等待新的数据,等到后返回
if (WaitForSingleObject(nextColorFrameEvent, INFINITE)==0)
//4.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame
hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame);
if (FAILED(hr))
cout&&&Could not get depth image&&&
NuiShutdown();
return -1;
INuiFrameTexture * pTexture = pImageFrame-&pFrameT
NUI_LOCKED_RECT LockedR
//4.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址
//并锁定数据,这样当我们读数据的时候,kinect就不会去修改它
pTexture-&LockRect(0, &LockedRect, NULL, 0);
//4.4、确认获得的数据是否有效
if( LockedRect.Pitch != 0 )
//4.5、将数据转换为OpenCV的Mat格式
for (int i=0; i&image. i++)
uchar *ptr = image.ptr&uchar&(i);
//第i行的指针
//其二是既表示深度值又含有人物序号,则像素值的高13位保存了深度值,低三位保存用户序号,
//注意这里需要转换,因为每个数据是2个字节,存储的同上面的颜色信息不一样,
uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.P
USHORT * pBuffer = (USHORT*) pBufferR
for (int j=0; j&image. j++)
//对于每一个像素,我们通过它的深度数据去修改它的RGB值;
RGBQUAD rgb = shortDepth2RGBquad(pBuffer[j]);
ptr[3*j] = rgb.rgbB
ptr[3*j+1] = rgb.rgbG
ptr[3*j+2] = rgb.rgbR
imshow(&depthImage&, image); //显示图像
cout&&&Buffer length of received texture is bogus\r\n&&&
//5、这帧已经处理完了,所以将其解锁
pTexture-&UnlockRect(0);
//6、释放本帧数据,准备迎接下一帧
NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame );
if (cvWaitKey(20) == 27)
//7、关闭NUI链接
NuiShutdown();
三、代码解析
&&&&&& 首先,这里基本上和上一文说的深度数据的获取的流程和API都是一样的,具体的话,参考上一文。只是有几个点需要说明下:
(1)初始化和打开深度数据流的时候传入的参数是不同的,这个需要注意下,我们需要的是DEPTH_AND_PLAYER_INDEX数据;
(2)每个像素的深度数据由两个字节来保存,高13位保存了深度值,低三位保存用户序号。
(3)具体显示的时候我们是这样处理的:
&&&&&& 对于每一个像素,我们通过它的深度数据去修改它的RGB值,如果属于同一个用户的ID,那么像素就标为同种颜色,不同的用户,其ID不一样,颜色的标示也不一样,如果不属于某个用户的像素,那么就采用原来的深度值。
首先,这里涉及到了:
USHORTrealDepth = (depthID & 0xfff8) && 3; //提取距离信息,高13位
USHORTplayer =& depthID & 0x07 ;& //提取ID信息,低3位
然后RGBQUAD是一个结构体,其保存一个像素点的RGB值,定义如下:
typedef struct tagRGBQUAD {
BYTE&&& rgbB
BYTE&&& rgbG
BYTE&&& rgbR
BYTE&&& rgbR
} RGBQUAD;
&&&&& 至此,目标达成。
&&&& 下面是结果,感觉似乎如果两个人靠得太近的话,也会被识别为同一个用户,标示同样的颜色,这点感觉有点不太稳定,这种情况应该挺容易避免的啊,是我高估了Kinect,还是我高估了我。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:19783次
排名:千里之外
转载:26篇
(1)(2)(1)(1)(6)(17)kinect(7)
Kinect开发学习笔记之(六)带游戏者ID的深度数据的提取
我的Kinect开发平台是:
Win7x86 + VS2010 + Kinect for Windows SDK v1.6 + OpenCV2.3.0
开发环境的搭建见上一文:
本学习笔记以下面的方式组织:编程前期分析、代码与注释和重要代码解析三部分。
要实现目标:通过微软的SDK提取带游戏者ID的深度数据并用OpenCV显示,不同用户,显示的颜色不同
一、编程前期分析
&&&&& 我们在上一文中提到的是不带游戏者ID的深度数据的提取,具体见下面:
Kinect开发学习笔记之(五)不带游戏者ID的深度数据的提取
&&&&&& 首先,Kinect传感器核心是发射红外结构光,并探测红外光反射,从而可以计算出视场范围内每一个像素的深度值。从深度数据中最先提取出来的是物体主体和形状,以及每一个像素点的游戏者索引信息。然后用这些形状信息来匹配人体的各个部分,最后计算匹配出来的各个关节在人体中的位置。而Kinect具有一次识别多达6个游戏者的能力,并能跟踪最多两个人的骨骼(对于XBOX360来说,就是可以同时两个人玩游戏了)。
&&&&& 可能有点奇怪哦,这一个带游戏者ID,一个不带,还得那么严肃地给它单独开一文来学习。究竟啥来头啊。呵呵,实际上,既然微软提供了这种差别,那么它的存在肯定是有意义的,所谓存在即合理嘛。多个选择嘛。需要用到游戏者ID的时候就用,不需要的时候就不用费那么大劲。也不能说费劲,就是使用游戏者ID的时候,我们需要再做一些工作,去把不同游戏者的轮廓找出来,然后为了区别,标上不同的颜色,这就是本文想实现的。有点啰嗦了。
&&&&& 上一文中,我们讲到,Kinect的深度图像数据有两种格式,一种是带游戏者ID的,一种是不带的。两种格式都是用两个字节来保存一个像素的深度值,而两方式的差别在于:
(1)唯一表示深度值:那么像素的低12位表示一个深度值,高4位未使用;
(2)既表示深度值又含有游戏者ID:Kinect为每一个追踪到的游戏者编号作为索引。而这个方式中,像素值的高13位保存了深度值,低三位保存用户序号,7 ()这个位掩码能够帮助我们从深度数据中获取到游戏者索引值。
&&&&&& 要注意的是,不要对特定的游戏者索引位进行编码,因为他们是会变化的。实际的游戏者索引位并不总是和Kinect前面的游戏者编号一致。啥意思呢?例如,Kinect视野中只有一个游戏者,但是返回的游戏者索引位值可能是3或者4。也就是说有时候第一个游戏者的游戏者索引位可能不是1。还有,如果走进Kinect视野再走出去,然后再走进来,虽然你还是你,但是Kinect给你的索引ID可能就和原来的不一样了,例如之前返回的索引位是1,走出去后再次走进,可能索引位变为其他值了。所以开发Kinect应用程序的时候应该注意到这一点。
&&&&& 说得有点乱哦,咱们还是看代码吧。
二、代码与注释
#include &windows.h&&
#include &iostream& & #include &NuiApi.h&&
#include &opencv2/opencv.hpp&&
& using namespace&
using namespace&
RGBQUAD shortDepth2RGBquad( USHORT depthID )&
&&& USHORT realDepth = (depthID & 0xfff8) && 3;
& &&& USHORT player =& depthID & 0x07 ;&
& && &&& &
&&& BYTE depth = 255 - (BYTE)(256*realDepth/0x0fff);&&
&& &&& RGBQUAD&& &&& q.rgbRed = q.rgbBlue = q.rgbGreen = 0;&& && &&& &
&&& switch( player )&&
&&& {&& &&&&&&& case 0:&&&
&&&&&&&&&&& q.rgbRed = depth / 2;&& &&&&&&&&&&& q.rgbBlue = depth / 2;&& &&&&&&&&&&& q.rgbGreen = depth / 2;&& &&&&&&&&&&& break;&&
&&&&&&& case 1:&& &&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& break;&& &&&&&&& case 2:&&
&&&&&&&&&&& q.rgbGreen =&&& &&&&&&&&&&& break;&&
&&&&&&& case 3:&& &&&&&&&&&&& q.rgbRed = depth / 4;&& &&&&&&&&&&& q.rgbGreen =&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&& &&&&&&& case 4:&&
&&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& q.rgbGreen =&& &&&&&&&&&&& q.rgbBlue = depth / 4;&& &&&&&&&&&&& break;&&
&&&&&&& case 5:&& &&&&&&&&&&& q.rgbRed =&& &&&&&&&&&&& q.rgbGreen = depth / 4;&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&& &&&&&&& case 6:&&
&&&&&&&&&&& q.rgbRed = depth / 2;&& &&&&&&&&&&& q.rgbGreen = depth / 2;&& &&&&&&&&&&& q.rgbBlue =&& &&&&&&&&&&& break;&&
&&&&&&& case 7:&& &&&&&&&&&&& q.rgbRed = 255 - ( depth / 2 );&& &&&&&&&&&&& q.rgbGreen = 255 - ( depth / 2 );&& &&&&&&&&&&& q.rgbBlue = 255 - ( depth / 2 );&& &&&&&&& }&& && &&& return&& }& & int main(int argc,
char *argv[])& {& &&& M& &&& image.create(240, 320, CV_8UC3);&& && &&& &
&&& HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX);&&
&&& if (FAILED(hr))&& &&& {&& &&&&&&& cout&&&NuiInitialize failed&&&&&
&&&&&&& return&&
&&& }&& & &&& & &&& &
&&& HANDLE nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );&
&&& HANDLE depthStreamHandle = NULL;
& && &&& &
&&& hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240,&&
&&&&&&&&&&&&&&&&&&&&&&&&&&& 0, 2, nextColorFrameEvent, &depthStreamHandle);&&
&&& if( FAILED( hr ) )& &&& {&& &&&&&&& cout&&&Could not open color image stream video&&&&&
&&&&&&& NuiShutdown();&& &&&&&&& return&& &&& }& &&& namedWindow(&depthImage&, CV_WINDOW_AUTOSIZE);&
&& &&& & &&& while(1)&& &&& {&& &&&&&&& const NUI_IMAGE_FRAME * pImageFrame = NULL;&&
& &&&&&&& &
&&&&&&& if (WaitForSingleObject(nextColorFrameEvent, INFINITE)==0)&&
&&&&&&& {&& &&&&&&&&&&& &
&&&&&&&&&&& hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame);&&
&&&&&&&&&&& if (FAILED(hr))&
&&&&&&&&&&& {& &&&&&&&&&&&&&&& cout&&&Could not get depth image&&&&&
&&&&&&&&&&&&&&& NuiShutdown();& &&&&&&&&&&&&&&& return -1;& &&&&&&&&&&& }& & &&&&&&&&&&& INuiFrameTexture * pTexture = pImageFrame-&pFrameT&
&&&&&&&&&&& NUI_LOCKED_RECT LockedR& & &&&&&&&&&&& &
&&&&&&&&&&& &
&&&&&&&&&&& pTexture-&LockRect(0, &LockedRect, NULL, 0);&& &&&&&&&&&&& &
&&&&&&&&&&& if( LockedRect.Pitch != 0 )&&
&&&&&&&&&&& {&& &&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&& for (int i=0; i&image. i++)&&
&&&&&&&&&&&&&&& {& &&&&&&&&&&&&&&&&&&& uchar *ptr = image.ptr&uchar&(i);& & &&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&& uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.P&
&&&&&&&&&&&&&&&&&&& USHORT * pBuffer = (USHORT*) pBufferR&
&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&& for (int j=0; j&image. j++)&&
&&&&&&&&&&&&&&&&&&& {& &&&&&&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&&&&&&&&&& RGBQUAD rgb = shortDepth2RGBquad(pBuffer[j]);&
&&&&&&&&&&&&&&&&&&&&&&& ptr[3*j] = rgb.rgbB&& &&&&&&&&&&&&&&&&&&&&&&& ptr[3*j+1] = rgb.rgbG&&
&&&&&&&&&&&&&&&&&&&&&&& ptr[3*j+2] = rgb.rgbR&& &&&&&&&&&&&&&&&&&&& }&& &&&&&&&&&&&&&&& }&& &&&&&&&&&&&&&&& imshow(&depthImage&, image);
& &&&&&&&&&&& }&& &&&&&&&&&&& else&&
&&&&&&&&&&& {&& &&&&&&&&&&&&&&& cout&&&Buffer length of received texture is bogus\r\n&&&&&
&&&&&&&&&&& }& & &&&&&&&&&&& &
&&&&&&&&&&& pTexture-&UnlockRect(0);& &&&&&&&&&&& &
&&&&&&&&&&& NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame );&&
&&&&&&& }&& &&&&&&& if (cvWaitKey(20) == 27)&&
&&&&&&&&&&& break;&& &&& }&& &&& & &&& NuiShutdown();&& &&& return 0;& }&
#include &windows.h&
#include &iostream&
#include &NuiApi.h&
#include &opencv2/opencv.hpp&
//处理深度数据的每一个像素,如果属于同一个用户的ID,那么像素就标为同种颜色,不同的用户,
//其ID不一样,颜色的标示也不一样,如果不属于某个用户的像素,那么就采用原来的深度值
RGBQUAD shortDepth2RGBquad( USHORT depthID )
//每像素共16bit的信息,其中最低3位是ID(所捕捉到的人的ID),剩下的13位才是信息
USHORT realDepth = (depthID & 0xfff8) && 3; //提取距离信息,高13位
USHORT player =
depthID & 0x07 ;
//提取ID信息 ,低3位
//因为提取的信息是距离信息,为了便于显示,这里归一化为0-255
BYTE depth = 255 - (BYTE)(256*realDepth/0x0fff);
q.rgbRed = q.rgbBlue = q.rgbGreen = 0;
//RGB三个通道的值都是相等的话,就是灰度的
//Kinect系统能够处理辨识传感器前多至6个人物的信息,但同一时刻最多只有2个玩家可被追踪(即骨骼跟踪)
switch( player )
q.rgbRed = depth / 2;
q.rgbBlue = depth / 2;
q.rgbGreen = depth / 2;
q.rgbRed =
q.rgbGreen =
q.rgbRed = depth / 4;
q.rgbGreen =
q.rgbBlue =
q.rgbRed =
q.rgbGreen =
q.rgbBlue = depth / 4;
q.rgbRed =
q.rgbGreen = depth / 4;
q.rgbBlue =
q.rgbRed = depth / 2;
q.rgbGreen = depth / 2;
q.rgbBlue =
q.rgbRed = 255 - ( depth / 2 );
q.rgbGreen = 255 - ( depth / 2 );
q.rgbBlue = 255 - ( depth / 2 );
int main(int argc, char *argv[])
image.create(240, 320, CV_8UC3);
//1、初始化NUI,注意这里是DEPTH_AND_PLAYER_INDEX
HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX);
if (FAILED(hr))
cout&&&NuiInitialize failed&&&
//2、定义事件句柄
//创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据
HANDLE nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
HANDLE depthStreamHandle = NULL; //保存图像数据流的句柄,用以提取数据
//3、打开KINECT设备的彩色图信息通道,并用depthStreamHandle保存该流的句柄,以便于以后读取
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240,
0, 2, nextColorFrameEvent, &depthStreamHandle);
if( FAILED( hr ) )//判断是否提取正确
cout&&&Could not open color image stream video&&&
NuiShutdown();
namedWindow(&depthImage&, CV_WINDOW_AUTOSIZE);
//4、开始读取深度数据
const NUI_IMAGE_FRAME * pImageFrame = NULL;
//4.1、无限等待新的数据,等到后返回
if (WaitForSingleObject(nextColorFrameEvent, INFINITE)==0)
//4.2、从刚才打开数据流的流句柄中得到该帧数据,读取到的数据地址存于pImageFrame
hr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame);
if (FAILED(hr))
cout&&&Could not get depth image&&&
NuiShutdown();
return -1;
INuiFrameTexture * pTexture = pImageFrame-&pFrameT
NUI_LOCKED_RECT LockedR
//4.3、提取数据帧到LockedRect,它包括两个数据对象:pitch每行字节数,pBits第一个字节地址
//并锁定数据,这样当我们读数据的时候,kinect就不会去修改它
pTexture-&LockRect(0, &LockedRect, NULL, 0);
//4.4、确认获得的数据是否有效
if( LockedRect.Pitch != 0 )
//4.5、将数据转换为OpenCV的Mat格式
for (int i=0; i&image. i++)
uchar *ptr = image.ptr&uchar&(i);
//第i行的指针
//其二是既表示深度值又含有人物序号,则像素值的高13位保存了深度值,低三位保存用户序号,
//注意这里需要转换,因为每个数据是2个字节,存储的同上面的颜色信息不一样,
uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.P
USHORT * pBuffer = (USHORT*) pBufferR
for (int j=0; j&image. j++)
//对于每一个像素,我们通过它的深度数据去修改它的RGB值;
RGBQUAD rgb = shortDepth2RGBquad(pBuffer[j]);
ptr[3*j] = rgb.rgbB
ptr[3*j+1] = rgb.rgbG
ptr[3*j+2] = rgb.rgbR
imshow(&depthImage&, image); //显示图像
cout&&&Buffer length of received texture is bogus\r\n&&&
//5、这帧已经处理完了,所以将其解锁
pTexture-&UnlockRect(0);
//6、释放本帧数据,准备迎接下一帧
NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame );
if (cvWaitKey(20) == 27)
//7、关闭NUI链接
NuiShutdown();
三、代码解析
&&&&&& 首先,这里基本上和上一文说的深度数据的获取的流程和API都是一样的,具体的话,参考上一文。只是有几个点需要说明下:
(1)初始化和打开深度数据流的时候传入的参数是不同的,这个需要注意下,我们需要的是DEPTH_AND_PLAYER_INDEX数据;
(2)每个像素的深度数据由两个字节来保存,高13位保存了深度值,低三位保存用户序号。
(3)具体显示的时候我们是这样处理的:
&&&&&& 对于每一个像素,我们通过它的深度数据去修改它的RGB值,如果属于同一个用户的ID,那么像素就标为同种颜色,不同的用户,其ID不一样,颜色的标示也不一样,如果不属于某个用户的像素,那么就采用原来的深度值。
首先,这里涉及到了:
USHORTrealDepth = (depthID & 0xfff8) && 3; //提取距离信息,高13位
USHORTplayer =& depthID & 0x07 ;& //提取ID信息,低3位
然后RGBQUAD是一个结构体,其保存一个像素点的RGB值,定义如下:
typedef struct tagRGBQUAD {
BYTE&&& rgbB
BYTE&&& rgbG
BYTE&&& rgbR
BYTE&&& rgbR
} RGBQUAD;
&&&&& 至此,目标达成。
&&&& 下面是结果,感觉似乎如果两个人靠得太近的话,也会被识别为同一个用户,标示同样的颜色,这点感觉有点不太稳定,这种情况应该挺容易避免的啊,是我高估了Kinect,还是我高估了我。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:19788次
排名:千里之外
转载:26篇
(1)(2)(1)(1)(6)(17)}

我要回帖

更多关于 超能游戏者1电影 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信