¿Es posible utilizar un sombreado para encontrar la “diferencia” entre dos texturas? (XNA / HLSL)

StackOverflow https://stackoverflow.com/questions/1182158

  •  19-09-2019
  •  | 
  •  

Pregunta

He hecho una aplicación basada sencilla webcam que detecta los bordes de "movimiento", por lo dibuja una textura que muestra dónde los píxeles del fotograma actual son significativamente diferentes al cuadro anterior. Este es mi código:

// 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);

¿Hay una manera de descargar este cálculo en la GPU usando shaders (que puede ir en alrededor de 25/26 fps usando el método anterior, pero esto es un poco lento)? Tengo un conocimiento básico de cómo shaders HLSL trabajo y no espero una solución completa, sólo quiero saber si esto sería posible y cómo obtener los datos de textura "diferencia" del shader y si esto en realidad sería más rápido .

Gracias de antemano.

¿Fue útil?

Solución

En cuanto a su comentario anterior acerca de la decisión de utilizar un enfoque de doble hilo para su problema, echa un vistazo a la .Net paralelo Extensiones CTP de Microsoft. microsoft.com

Si usted no está planeando sobre el despliegue de una Xbox360, esta biblioteca funciona muy bien con XNA, y he visto grandes mejoras de velocidad en ciertos bucles e iteraciones.

Es, básicamente, sólo tiene que cambiar un par de líneas de código, por ejemplo:

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

cambiaría a:

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

para realizar automáticamente cada núcleo en su procesador de ayudar con el procesamiento de números. Es rápido y excelente.

Buena suerte!

Otros consejos

Se podría probar dos texturas dentro del sombreado de píxeles, a continuación, escribir la diferencia como el valor del color. Si se configura una Render Target , el color información que oUPUT del shader se almacenará en esta textura en lugar del uso de este dispositivo.

No sé qué tipo de velocidad de ganancia que esperaba ver, pero así es como yo lo haría.

* Editar - Ah, y me olvidaba decir, tener en cuenta el tipo de muestreo que utilice, ya que afectará a los resultados. Si desea que su algoritmo para traducir directamente a la GPU, utilice punto de muestreo para empezar.

El operador de Sobel o algo parecido se utiliza en motores de juegos y otras aplicaciones en tiempo real para la detección de bordes. Es trivial para escribir como un sombreado de píxeles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top