本文主要是介绍Kinect for windows 开发入门 八:景深数据获取和使用 下,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景知识
1. 前面已经有提到,所谓直方图就是不同深度的像素分布图。
2. Player id只有在打开SkeletonStream的时候才会产生。
SkeletonStream skeletonStream =kinectSensor.SkeletonStream;
skeletonStream.Enable();
Playerid是动态分配的,同一个人走出视线再回来id会改变。Playerid也不是从0开始,从小到大排序的。
3. 如何计算人体的高度和宽度。如下图所示,根据Player id和深度数据,我们可以获取到人体的平均深度d。根据Kinect支持的水平角度(57度)和d,我们可以通过如下的两个直角三角形计算出人体所在切面的1/2实际宽度d *Pi * (57度/2)/180度 得到b。根据DepthStream的分辨率中的横向像素总数和人体所占像素,可以知道人体所占切面比例r。然后b*2* r就得到了人体的宽度。
比如,人体深度为2m,分辨率为1024 * 768,人体所占横向像素平均为300,那么人体的宽度为(2m * Pi * 28.5度 / 180 度)* 2 * (300 / 1024)=0.58米。对于高度的计算也是一样的。
示例代码
1. 直方图
privatevoidCreateDepthHistogram(short[] pixelData, DepthImageFrame frame)
{
int[] depths = newint[4096];
DepthHistogram.Children.Clear();
int depth = 0;
int max = 0;
for (int i = 0; i <pixelData.Length; i++)
{
depth = pixelData[i] >> DepthImageFrame.PlayerIndexBitmaskWidth;
if (depth > 0 && depth < 4096)
{
depths[depth]++;
max = depths[depth] >max ? depths[depth] : max;
}
}
for (int index = 0; index <depths.Length; index++)
{
if (depths[index] > 0)
{
Rectangle rect = newRectangle();
rect.Fill = Brushes.DarkBlue;
rect.Width =DepthHistogram.ActualWidth / 4096;
rect.Height =DepthHistogram.ActualHeight * ((double)depths[index]/ max);
rect.Margin = newThickness(1, 0, 1, 0);
rect.VerticalAlignment =System.Windows.VerticalAlignment.Bottom;
DepthHistogram.Children.Add(rect);
}
}
}
2. 抠像
privatevoid CatchPlayer(short[] pixelData, DepthImageFrame frame)
{
int playId = 0;
byte[] playerPixelData = newbyte[frame.Width * frame.Height *4];
for (int i = 0; i <pixelData.Length; i++)
{
playId = pixelData[i] & DepthImageFrame.PlayerIndexBitmask;
if (playId > 0)
{
ShowThePlayerId.Text = string.Format("PlayerId:{0}", playId.ToString());
playerPixelData[i * 4] = (byte)0;
playerPixelData[i * 4 + 1]= (byte)0;
playerPixelData[i * 4 + 2]= (byte)255;
}
else
{
playerPixelData[i * 4] = (byte)0;
playerPixelData[i * 4 + 1]= (byte)0;
playerPixelData[i * 4 + 2]= (byte)0;
}
}
this.playerImageBitmap.WritePixels(this.playerImageBitmapRect, playerPixelData, frame.Width * 4, 0);
}
3. 计算高度宽度
privatevoidCaculateHightAndWidth(DepthImageFrame frame)
{
double avgDepth = 0.0;
int sumDepth = 0;
int pixelCount = 0;
int minX = frame.Width;
int maxX = 0;
int minY = frame.Height;
int maxY = 0;
for (int i = 0; i < frame.Width;i++)
{
for (int j = 0; j < frame.Height;j++)
{
if (playerData[i,j] <= 0)
{
continue;
}
pixelCount++;
minX = i < minX ? i :minX;
maxX = i > maxX ? i :maxX;
minY = j < minY ? j :minY;
maxY = j > maxY ? j :maxY;
sumDepth += playerData[i,j];
}
}
if (pixelCount <= 0)
{
return;
}
int widthPixel = maxX - minX;
int heightPixel = maxY - minY;
avgDepth = sumDepth / pixelCount;
double actualWidth = avgDepth * 28.5 * 3.14159 * 2 / 180;
double actualHeight = avgDepth * 21.5 * 3.14159 * 2 /180;
double width = actualWidth * widthPixel / frame.Width;
double height = actualHeight * heightPixel /frame.Height;
ShowThePlayerWidthAndHeight.Text = string.Format("Player width:{0} \nPlayerHeight:{1}",width, height);
}
效果演示
1. 直方图,展示统一深度出现的次数。
如图所示,人,椅子,背景三个高峰。
2. 抠像
将playerid 不为0的像素显示为红色。
3. 深度宽度
很粗劣的用最大值减最小值计算出来的。偏差比较大。实际高度应该是1.6米。不过,我们的目的是展示如何计算。
这篇关于Kinect for windows 开发入门 八:景深数据获取和使用 下的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!