E 'possibile utilizzare uno shader per trovare la “differenza” tra due trame? (XNA / HLSL)

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

  •  19-09-2019
  •  | 
  •  

Domanda

Ho fatto un'applicazione basata semplice webcam che rileva i "bordi del moto" così disegna una struttura che mostra dove i pixel del fotogramma corrente sono significativamente diverse al fotogramma precedente. Questo è il mio codice:

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

C'è un modo per scaricare questo calcolo alla GPU tramite shader (si può andare a circa 25/26 fps utilizzando il metodo di cui sopra, ma questo è un po 'lento)? Ho una conoscenza di base di come il lavoro shader HLSL e non mi aspetto una soluzione completa, voglio solo sapere se questo sarebbe possibile e come ottenere i dati delle texture "differenza" dal shader e se questo sarebbe effettivamente più veloce .

Grazie in anticipo.

È stato utile?

Soluzione

Per quanto riguarda il tuo commento di cui sopra su di decidere di utilizzare un approccio a doppio filo al tuo problema, controllare il .Net Parallel Extensions CTP di Microsoft. microsoft.com

Se non avete in programma di distribuzione a un XBox360, questa libreria funziona alla grande con XNA, e ho visto miglioramenti enormi velocità in alcuni loop e iterazioni.

Si sarebbe fondamentalmente solo cambiare un paio di righe di codice, ad esempio:

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

cambierebbe a:

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

per fare automaticamente ogni core nel processore aiutare fuori con il numero scricchiolio. E 'veloce ed eccellente.

In bocca al lupo!

Altri suggerimenti

Si potrebbe provare due texture all'interno del pixel shader, quindi scrivere la differenza come il valore del colore. Se si imposta un Render destinazione , il colore informazioni che ouput dalla shader verrà memorizzato in questa texture al posto del framebuffer.

Non so che tipo di guadagno di velocità che ci si aspetta di vedere, ma è così che lo farei.

* Modifica - Oh, e ho dimenticato di dire, essere a conoscenza del tipo di campionamento utilizzato, in quanto influenzerà i risultati. Se volete che il vostro algoritmo per tradurre direttamente alla GPU, usa il campionamento punto di partenza.

Il Sobel operatore o qualcosa di simile è usato in motori di gioco e altre applicazioni in tempo reale per il rilevamento dei bordi. E 'banale scrivere come un pixel shader.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top