kinect学习笔记(四)——各种数据流

2023-05-26,,

一、kinect开发的一个流程图

1、我们可以知道一个简单的框架就是几部分

(1)选择使用的kinect传感器

KinectSensor.KinectSensors[]

(2)打开需要的数据流

_kinect.DepthStream.Enable();
_kinect.ColorStream.Enable();
_kinect.SkeletonStream.Enable();

(3)注册事件

其实就是主要的算法在这里体现。

有个小窍门:VS的CodeSnippet快速生成事件代码,如在代码“_kinect.DepthFrameReady+=”后面连续按两次“Tab”键,就会生成相应的时间并处理相应的代码。

二、初始化、启用kinect设备

代码如下,记得要声明一个私有成员变量_kinect,并在MainWindow()里面调用。

KinectSensor _kinect;

        private void startKinect()
{
if(KinectSensor.KinectSensors.Count>)
{
//选择第一个kinect设备
_kinect = KinectSensor.KinectSensors[];
MessageBox.Show("Kinect目前状态为:" + _kinect.Status); //初始化设定,启用彩色图像,深度图像和骨骼追踪
_kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
_kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
_kinect.SkeletonStream.Enable(); //注册时间,该方法将保证彩色图像,深度图像和骨骼图像的同步
_kinect.AllFramesReady += _kinect_AllFramesReady; //启动kinect
_kinect.Start();
}
else
{
MessageBox.Show("没有发现任何kinect设备");
}
}

void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{

}

三、彩色图像流数据处理

1、在MainWindows窗体上新增一个Image控件,命名为imageCamera

2、在_kinect_AllFramesReady事件处理中增加如下代码、

//显示彩色摄像头
using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if(colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); }

BGR32图像的1像素对应4字节(32位),分别是B,G,R,阿尔法通道(透明度)。

BitmapSource.Create是一个从数组到二维矩阵的过程。

Stride为图片步长,代表图片一行像素所占的字节数,为摄像头传输图片的宽度乘以4,

DPI,越高越清晰,普通的显示器就是96差不多。

3、效果图

四、深度数据捕获

1、定义深度图像的有效视角范围。

const float MaxDepthDistance = ;
const float MinDepthDistance = ;
const float MaxDepthDistanceOffest = MaxDepthDistance - MinDepthDistance; private const int RedIndex = ;
private const int GreenIndex = ;
private const int BlueIndex = ;

2、代码

private byte[]convertDepthFrameToColorFrame(DepthImageFrame depthFrame)
{
short[] rawDepthData = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(rawDepthData); Byte[] piexls = new byte[depthFrame.Height * depthFrame.Width * ]; for(int depthIndex = ,colorIndex=;depthIndex<rawDepthData.Length&&colorIndex<piexls.Length;depthIndex++,colorIndex+=)
{
int player = rawDepthData[depthIndex] & DepthImageFrame.PlayerIndexBitmask; int depth = rawDepthData[depthIndex];
if(depth<=)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
}
else if(depth>&&depth<)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
}
else if(depth>)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
} byte intensity = CalculateIntensityFromDepth(depth);
piexls[colorIndex + BlueIndex] = intensity;
piexls[colorIndex + GreenIndex] = intensity;
piexls[colorIndex + RedIndex] = intensity; if(player>)
{
piexls[colorIndex + BlueIndex] = Colors.LightGreen.B;
piexls[colorIndex + GreenIndex] = Colors.LightGreen.G;
piexls[colorIndex + RedIndex] = Colors.LightGreen.R;
}
}
return piexls;
} void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
//显示彩色摄像头
using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if(colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); } using(DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if(depthFrame==null)
{
return;
} byte[] piexls = convertDepthFrameToColorFrame(depthFrame); int stride = depthFrame.Width * ;
imageDepth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, , , PixelFormats.Bgr32, null, piexls, stride); }

3、效果图

五、骨骼追踪

1、首先注释掉我们之前注册的时间,重新注册一个彩色数据流时间和一个骨骼事件,然后添加如下代码

private Skeleton[] skeletons;
void _kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
bool isSkeletonDataEeady = false;
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if(skeletonFrame!=null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
isSkeletonDataEeady = true;
} } if(isSkeletonDataEeady==true)
{
Skeleton currentSkeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
if(currentSkeleton !=null)
{
lockHeadWithSpot(currentSkeleton);
} }
} void lockHeadWithSpot(Skeleton s)
{
Joint head = s.Joints[JointType.Head];
ColorImagePoint colorPoint = _kinect.MapSkeletonPointToColor(head.Position, _kinect.ColorStream.Format); Point p = new Point((int)(ImageCamera.Width * colorPoint.X / _kinect.ColorStream.FrameWidth),
(int)(ImageCamera.Height * colorPoint.Y / _kinect.ColorStream.FrameHeight)); Canvas.SetLeft(ellipseHead, p.X);
Canvas.SetRight(ellipseHead, p.Y);
} void _kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); } }

2、效果图

六关闭kinect设备

private void stopKinect()
{
if(_kinect != null)
{
if(_kinect.Status== KinectStatus.Connected)
{
_kinect.Stop();
}
}
}

kinect学习笔记(四)——各种数据流的相关教程结束。

《kinect学习笔记(四)——各种数据流.doc》

下载本文的Word格式文档,以方便收藏与打印。