【问题标题】:Is it possible to extract the player's depth pixels only, out of the depth bitmap?是否可以仅从深度位图中提取玩家的深度像素?
【发布时间】:2012-11-27 14:12:23
【问题描述】:

我是 kinect 开发的新手,也是 stackoverflow 的新手! 这是我的情况:

拥有深度相机,我可以轻松获取深度数据。我想要做的是,一旦我检测到相机前存在一个人(玩家),我将只提取玩家的深度像素,并将其放在透明背景上,这样输出只是播放器深度图像的静态图像,在透明背景上。

我想问有没有可能做这项工作?我做了一些研究,发现一些函数可能有助于这样做,例如 SkeletonToDepthImage() 或深度像素数据(包括距离和玩家索引)。

【问题讨论】:

    标签: c# kinect pixel depth


    【解决方案1】:

    我假设您的意思是要根据深度数据渲染玩家的剪影,只显示他们的轮廓。对吗?

    Kinect for Windows Developer Toolkit 提供了多个可以做到这一点的示例。 “绿屏”示例向您展示如何提取深度数据并将其映射到颜色流以仅在所选背景上显示播放器。 “基本交互”示例有一个剪影示例,它完全符合我的解释。

    查看 Microsoft 提供的示例,以更好地了解 Kinect 的许多基本使用场景。

    基于 Basic Interactions 项目中的剪影示例,我编写了一个剪影控件。控件的核心由以下两个函数组成(即实际产生轮廓的函数。

    private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
    {
        using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
        {
            if (skeletonFrame != null && skeletonFrame.SkeletonArrayLength > 0)
            {
                if (_skeletons == null || _skeletons.Length != skeletonFrame.SkeletonArrayLength)
                {
                    _skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                }
    
                skeletonFrame.CopySkeletonDataTo(_skeletons);
    
                // grab the tracked skeleton and set the playerIndex for use pulling
                // the depth data out for the silhouette.
                // TODO: this assumes only a single tracked skeleton, we want to find the
                // closest person out of the tracked skeletons (see above).
                this.playerIndex = -1;
                for (int i = 0; i < _skeletons.Length; i++)
                {
                    if (_skeletons[i].TrackingState != SkeletonTrackingState.NotTracked)
                    {
                        this.playerIndex = i+1;
                    }
                }
            }
        }
    }
    
    private void OnDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
    {
        using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
        {
            if (depthFrame != null)
            {
                // check if the format has changed.
                bool haveNewFormat = this.lastImageFormat != depthFrame.Format;
    
                if (haveNewFormat)
                {
                    this.pixelData = new short[depthFrame.PixelDataLength];
                    this.depthFrame32 = new byte[depthFrame.Width * depthFrame.Height * Bgra32BytesPerPixel];
                    this.convertedDepthBits = new byte[this.depthFrame32.Length];
                }
    
                depthFrame.CopyPixelDataTo(this.pixelData);
    
                for (int i16 = 0, i32 = 0; i16 < pixelData.Length && i32 < depthFrame32.Length; i16++, i32 += 4)
                {
                    int player = pixelData[i16] & DepthImageFrame.PlayerIndexBitmask;
                    if (player == this.playerIndex)
                    {
                        convertedDepthBits[i32 + RedIndex] = 0x44;
                        convertedDepthBits[i32 + GreenIndex] = 0x23;
                        convertedDepthBits[i32 + BlueIndex] = 0x59;
                        convertedDepthBits[i32 + 3] = 0x66;
                    }
                    else if (player > 0)
                    {
                        convertedDepthBits[i32 + RedIndex] = 0xBC;
                        convertedDepthBits[i32 + GreenIndex] = 0xBE;
                        convertedDepthBits[i32 + BlueIndex] = 0xC0;
                        convertedDepthBits[i32 + 3] = 0x66;
                    }
                    else
                    {
                        convertedDepthBits[i32 + RedIndex] = 0x0;
                        convertedDepthBits[i32 + GreenIndex] = 0x0;
                        convertedDepthBits[i32 + BlueIndex] = 0x0;
                        convertedDepthBits[i32 + 3] = 0x0;
                    }
                }
    
                if (silhouette == null || haveNewFormat)
                {
                    silhouette = new WriteableBitmap(
                        depthFrame.Width,
                        depthFrame.Height,
                        96,
                        96,
                        PixelFormats.Bgra32,
                        null);
    
                    SilhouetteImage.Source = silhouette;
                }
    
                silhouette.WritePixels(
                    new Int32Rect(0, 0, depthFrame.Width, depthFrame.Height),
                    convertedDepthBits,
                    depthFrame.Width * Bgra32BytesPerPixel,
                    0);
    
                Silhouette = silhouette;
    
                this.lastImageFormat = depthFrame.Format;
            }
        }
    }
    

    【讨论】:

    • 是的,这正是我想要的!非常感谢,我会继续工作的:)
    • @Evil Closet Monkey,是否可以为骨架添加额外的关节?例如,如果一个人拿着一根棍子,那么骨架会添加一个额外的关节来代表棍子吗?如果可以请告诉我是否有任何解决方案可以解决这个问题?
    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    相关资源
    最近更新 更多