На самом деле двустороннее размытие не сильно отличается от размытия по Гауссу, вам просто нужно умножить значение выборки на коэффициент Гаусса, умноженный на результат функции «близости» между фактическими значениями центрального пикселя и выбранный пиксель.
Итак, в псевдониме GLSL
vec3 centreColour = texture2D(image,texCoord);
vec3 result = centreColour;
float normalization = 1;
for (int i = 0; i < NUM_SAMPLES; ++1)
{
vec3 sample = texture2D(image, texCoord + offsets[i]);
float gaussianCoeff = computeGaussianCoeff(offsets[i]);
//depends on your implementation, this is quick
float closeness = 1.0f - distance(sample,centreColour) / length(vec3(1,1,1));
float sampleWeight = closeness * gaussian;
result += sample * sampleWeight;
noralization += sampleWeight;
}
vec3 bilateral = result / normalization;
Вероятно, у вас должен быть лучший способ определить значение близости, например, сделать это в восприимчиво однородном пространстве, таком как LUV.
Для оптимизации вы можете применять все методы, которые работают для размытия по Гауссу, кроме тех, которые игнорируют тот факт, что вы должны знать значение пикселя. Например, с чистым гауссовским языком вы можете мудро выбирать текстовые строки и объединять 4 пикселя в одну выборку. Это не сработает.
Большие вещи, которые работают:
* Отделите свой фильтр. Вместо 5х5 образцов (25), сделайте 5 по горизонтали, сохраните в промежуточный буфер и сделайте 5 по вертикали. Это не будет выглядеть точно так же, но все равно удалит шум.
* Выполните фильтр с меньшим разрешением и скомбинируйте его с оригиналом, чтобы вернуть некоторые детали.