0

我正在尝试使用 WPF 应用程序显示 Kinect 传感器检测到的玩家数量。除了显示玩家数量之外,我还根据他们与 Kinect 的距离为像素着色。最初的目标是测量像素的距离并显示距离,但我还想显示框架中有多少人。这是我现在正在使用的代码片段。

PS 我从THIS教程中借用了这个想法,我正在使用 SDK 1.8 和 XBOX 360 Kinect (1414)

private void _sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
    {
        using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
        {
            if (depthFrame==null)
            {
                return;
            }
            byte[] pixels = GenerateColoredBytes(depthFrame);
            int stride = depthFrame.Width * 4;
            image.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 
            96, 96, PixelFormats.Bgr32, null, pixels, stride);
        }
    }

private byte[] GenerateColoredBytes(DepthImageFrame depthFrame)
    {   
       //get the raw data from kinect with the depth for every pixel
        short[] rawDepthData = new short[depthFrame.PixelDataLength];
        depthFrame.CopyPixelDataTo(rawDepthData);
        /*
        Use depthFrame to create the image to display on screen
        depthFrame contains color information for all pixels in image
        */
        //Height * Width *4 (Red, Green, Blue, Empty byte)
        Byte[] pixels = new byte[depthFrame.Height * depthFrame.Width * 4];
        //Hardcoded loactions for Blue, Green, Red (BGR) index positions
        const int BlueIndex = 0;
        const int GreenIndex = 1;
        const int RedIndex = 2;
        //Looping through all distances and picking a RGB colour based on distance

        for (int depthIndex = 0, colorIndex = 0; 
            depthIndex < rawDepthData.Length && 
            colorIndex<pixels.Length; depthIndex++, colorIndex+=4)
        {
            //Getting player
            int player = rawDepthData[depthIndex] & DepthImageFrame.PlayerIndexBitmask;

            //Getting depth value
            int depth =rawDepthData[depthIndex]>>DepthImageFrame.PlayerIndexBitmaskWidth;

            //.9M or 2.95'
            if (depth <=900 )
            {
                //Close distance
                pixels[colorIndex + BlueIndex] = 0;
                pixels[colorIndex + GreenIndex] = 0;
                pixels[colorIndex + RedIndex] = 255;
                //textBox.Text = "Close Object";
            }

            //.9M - 2M OR 2.95' - 6.56'
            else if (depth >900 && depth<2000)
            {
                //Bit further away
                pixels[colorIndex + BlueIndex] = 255;
                pixels[colorIndex + GreenIndex] = 0;
                pixels[colorIndex + RedIndex] = 0;
            }

            else if (depth > 2000)
            {
                //Far away
                pixels[colorIndex + BlueIndex] = 0;
                pixels[colorIndex + GreenIndex] = 255;
                pixels[colorIndex + RedIndex] = 0;
            }

            //Coloring all people in Gold
            if (player > 0)
            {
                pixels[colorIndex + BlueIndex] = Colors.Gold.B;
                pixels[colorIndex + GreenIndex] = Colors.Gold.G;
                pixels[colorIndex + RedIndex] = Colors.Gold.R;
                playersValue.Text = player.ToString();
            }
        }
        return pixels;
    }

目前的目标是——

  • 检测检测到的玩家总数并将其显示在textBox
  • 根据距离逻辑为它们着色,即depth <=900 is red

使用当前代码,我可以检测到玩家并将它们涂成金色,但是一旦检测到玩家就会image冻结,而当玩家离开框架时,就会image解冻并正常运行。是因为循环吗?欢迎提出想法、指导、推荐和批评。

谢谢!

截图:

在此处输入图像描述

在此处输入图像描述

4

1 回答 1

0

在表单代码中获取静态变量

然后使用您的视频帧例程设置此变量(不要在那里定义它)。

然后更新文本框视图,可能在您的 _sensor_AllFramesReady 由于新帧的到来在不同的线程中运行,我看不到所有代码可能会更新调用 textbox.show

主循环看起来有点奇怪,太复杂了。基本上,您使用它来为图像中的每个像素着色。因为 kinect360 有 320x240 像素,所以深度数组大小为 76800 您可以简单地为 X 和 Y 的下一个循环创建 2 个循环,然后在此循环内有一个变量增加以选择适当的深度值。

于 2016-02-05T16:08:26.767 回答