Kinect for Windows SDK开发入门(五)景深数据处理 下
Kinect for Windows SDK开发入门(五)景深数据处理 下
1. 简单的景深影像处理
在上篇文章中,我们讨论了如何获取像素点的深度值以及如何根据深度值产生影像。在之前的例子中,我们过滤掉了阈值
之外的点。这就是一种简单的图像处理,叫阈值处理。使用的阈值方法虽然有点粗糙,但是有用。更好的方法是利用机器
学习来从每一帧影像数据中计算出阈值。Kinect深度值最大为4096mm,0值通常表示深度值不能确定,一般应该将0值过
滤掉。微软建议在开发中使用1220mm(4’)~3810mm(12.5’)范围内的值。在进行其他深度图像处理之前,应该使用阈值方法过滤深度数据至1220mm-3810mm这一范围内。
使用统计方法来处理深度影像数据是一个很常用的方法。阈值可以基于深度数据的平均值或者中值来确定。统计方法可以
帮助确定某一点是否是噪声、阴影或者是其他比较有意义的物体,比如说用户的手的一部分。有时候如果不考虑像素的视
觉意义,可以对原始深度进行数据挖掘。对景深数据处理的目的是进行形状或者物体的识别。通过这些信息,程序可以确
定人体相对于Kinect的位置及动作。
1.1深度影像数据直方图
直方图是统计数据分布的一个很有效的工具。在这里我们关心的是一个景深影像图中深度值的分布。直方图能够直观地反
映给定数据集中数据的分布状况。从直方图中,我们能够看出深度值出现的频率以及聚集分组。通过这些信息,我们能够
确定阈值以及其他能够用来对图像进行过滤的指标,使得能够最大化的揭示深度影像图中的深度信息。为了展示这一点,
接下来我们将会展示一副景深影像数据的直方图,并通过直方图,使用一些简单的技术来过滤掉我们不想要的像素点。
首先创建一个新的项目。然后根据之前文章中讲的步骤发现和初始化KinectSensor对象来进行深度影像数据处理,包括
注册DepthFrameReady事件。在添加实现深度直方图之前,将UI界面更改为如下:
创建直方图的方法很简单,就是创建一系列的矩形元素,然后将它添加到名为DepthHistogram的StackPanel元素中,由
于DepthHistogram对象的Orientation属性设置为Horizontal,所以这些矩形会水平排列。大多数应用程序计算直方图只
是用来进行中间过程处理用,如果想要将直方图展现出来,则需要在绘图上面做些工作。下面的代码展现了如何绘制直方图:
private void KinectDevice_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame frame = e.OpenDepthImageFrame())
{
if (frame != null)
{
frame.CopyPixelDataTo(this._DepthPixelData);
CreateBetterShadesOfGray(frame, this._DepthPixelData);
CreateDepthHistogram(frame, this._DepthPixelData);
}
}
}
private void CreateDepthHistogram(DepthImageFrame depthFrame, short[] pixelData)
{
int depth;
int[] depths = new int[4096];
double chartBarWidth = Math.Max(3, DepthHistogram.ActualWidth / depths.Length);
int maxValue = 0;
DepthHistogram.Children.Clear();
//计算并获取深度值.并统计每一个深度值出现的次数
for (int i = 0; i < pixelData.Length; i++)
{
depth = pixelData[i] >> DepthImageFrame.PlayerIndexBitmaskWidth;
if (depth >= LoDepthThreshold && depth <= HiDepthThreshold)
{
depths[depth]++;
}
}
//查找最大的深度值
for (int i = 0; i < depths.Length; i++)
{
maxValue = Math.Max(maxValue, depths[i]);
}
//绘制直方图
for (int i = 0; i < depths.Length; i++)
{
if (depths[i] > 0)
{
Rectangle r = new Rectangle();
r.Fill = Brushes.Black;
r.Width = chartBarWidth;
r.Height = DepthHistogram.ActualHeight * (depths[i] / (double)maxValue);
r.Margin = new Thickness(1, 0, 1, 0);
r.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
DepthHistogram.Children.Add(r);
}
}
}