代码之家  ›  专栏  ›  技术社区  ›  Callum Rogers

是否可以使用一个明暗器来查找两个纹理之间的“差异”?(XNA/HLSL)

  •  3
  • Callum Rogers  · 技术社区  · 15 年前

    我制作了一个简单的基于网络摄像头的应用程序,它可以检测“运动边缘”,从而绘制出一个纹理,显示当前帧的像素与前一帧有显著不同。这是我的代码:

    // LastTexture is a Texture2D of the previous frame.
    // CurrentTexture is a Texture2D of the current frame.
    // DifferenceTexture is another Texture2D.
    // Variance is an int, default 100;
    
    Color[] differenceData = new Color[CurrentTexture.Width * CurrentTexture.Height];
    Color[] currentData = new Color[CurrentTexture.Width * CurrentTexture.Height];
    Color[] lastData = new Color[LastTexture.Width * LastTexture.Height];
    
    CurrentTexture.GetData<Color>(currentData);
    LastTexture.GetData<Color>(lastData);
    
    for (int i = 0; i < currentData.Length; i++)
    {
        int sumCD = ColorSum(currentData[i]); // ColorSum is the same as c.R + c.B + c.G where c is a Color.
        int sumLD = ColorSum(lastData[i]);
        if ((sumCD > sumLD - Variance) && (sumCD < sumLD + Variance))
            differenceData[i] = new Color(0, 0, 0, 0); // If the current pixel is within the range of +/- the Variance (default: 100) variable, it has not significantly changes so is drawn black.
        else
            differenceData[i] = new Color(0, (byte)Math.Abs(sumCD - sumLD), 0); // This has changed significantly so is drawn a shade of green.
    }
    
    DifferenceTexture = new Texture2D(game1.GraphicsDevice, CurrentTexture.Width, CurrentTexture.Height);
    DifferenceTexture.SetData<Color>(differenceData);
    
    LastTexture = new Texture2D(game1.GraphicsDevice,CurrentTexture.Width, CurrentTexture.Height);
    LastTexture.SetData<Color>(currentData);
    

    有没有一种方法可以使用着色器将此计算卸载到GPU(使用上述方法,它可以以大约25/26 fps的速度进行计算,但速度有点慢)?我对HLSL材质球的工作原理有一个基本的了解,并不期望有一个完整的解决方案,我只是想知道这是否可行,以及如何从材质球中获得“差异”纹理数据,以及这是否真的更快。

    事先谢谢。

    3 回复  |  直到 13 年前
        1
  •  2
  •   bufferz    15 年前

    关于上面关于决定使用双线程方法解决问题的评论,请查看Microsoft提供的.NET并行扩展CTP。 microsoft.com

    如果您不打算部署到Xbox360,那么这个库在XNA中工作得很好,而且我在某些循环和迭代中看到了巨大的速度改进。

    您基本上只需要更改几行代码,例如:

    for (int i = 0; i < currentData.Length; i++)
    {
        // ...
    }
    

    将改为:

    Parallel.For(0, currentData.Length, delegate(int i)
    {
       // ...
    });
    

    自动使处理器中的每个核心都有助于数字处理。它既快又好。

    祝你好运!

        2
  •  3
  •   Mark Simpson    15 年前

    您可以在像素明暗器中采样两个纹理,然后将差异作为颜色值写入。如果你建立了 Render Target ,从材质球输出的颜色信息将存储在此纹理中,而不是帧缓冲区中。

    我不知道你希望看到什么样的速度提升,但我就是这么做的。

    *编辑-哦,我忘了说,注意你使用的采样类型,因为它会影响结果。如果您希望您的算法直接转换为GPU,请从点采样开始。

        3
  •  0
  •   bmcnett    13 年前

    这个 Sobel operator 或者类似于它被用于游戏引擎和其他实时边缘检测应用程序中。作为像素遮影器编写是很简单的。