Можно ли использовать шейдер, чтобы найти «разницу» между двумя текстурами?(XNA/HLSL)

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

  •  19-09-2019
  •  | 
  •  

Вопрос

Я создал простое приложение на основе веб-камеры, которое обнаруживает «края движения» и рисует текстуру, которая показывает, где пиксели текущего кадра значительно отличаются от предыдущего кадра.Это мой код:

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

Есть ли способ перенести эти вычисления на графический процессор с помощью шейдеров (при использовании описанного выше метода он может работать со скоростью около 25/26 кадров в секунду, но это немного медленно)?У меня есть базовое понимание того, как работают шейдеры HLSL, и я не ожидаю полного решения, я просто хочу знать, возможно ли это и как получить «разностные» данные текстуры из шейдера и будет ли это на самом деле быстрее. .

Заранее спасибо.

Это было полезно?

Решение

Что касается вашего комментария выше о решении использовать двухпоточный подход к вашей проблеме, ознакомьтесь с CTP .Net Parallel Extensions от Microsoft. microsoft.com

Если вы не планируете развертывать систему на XBox360, эта библиотека отлично работает с XNA, и я видел значительное улучшение скорости в определенных циклах и итерациях.

По сути, вам нужно будет изменить всего пару строк кода, например:

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

изменится на:

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

чтобы каждое ядро ​​вашего процессора автоматически помогало в обработке чисел.Это быстро и отлично.

Удачи!

Другие советы

Вы можете попробовать две текстуры внутри пиксельного шейдера, а затем записать разницу в виде значения цвета.Если вы установили Цель рендеринга, информация о цвете, выводимая из шейдера, будет храниться в этой текстуре, а не в буфере кадра.

Я не знаю, какого прироста скорости вы ожидаете увидеть, но я бы это сделал именно так.

*edit - Да, и я забыл сказать, помните о типе выборки, который вы используете, так как это повлияет на результаты.Если вы хотите, чтобы ваш алгоритм напрямую транслировался в графический процессор, для начала используйте точечную выборку.

А Оператор Собеля или что-то подобное используется в игровых движках и других приложениях реального времени для обнаружения границ.Написать как пиксельный шейдер тривиально.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top