# 双边滤波函数
既然高斯模糊没有良好地保留边界,我们就选取一个能够保边去噪的滤波器,高斯双边滤波算法就是这样的一个滤波器。高斯模糊仅仅考虑了像素的空间分布,权重从中间向周边降低。而双边滤波则进一步考虑了图像的像素值,从而保证边缘部分不会被过滤掉。根据维基百科 [3][3],一个双边滤波器定义为:
Ifiltered(x)=1WpΣxi∈ΩI(xi)fr(∣∣I(xi)−I(x)∣∣)gs(∣∣xi−x∣∣)(8)
Ifiltered(x)=1WpΣxi∈ΩI(xi)fr(∣∣I(xi)−I(x)∣∣)gs(∣∣xi−x∣∣)
其中,Ifiltered (x) 是过滤后的图像,x 是被过滤的像素坐标,Ω 是像素 x 的滤波核领域,I (x) 是初始未被过滤的图像。然后 fr 是域值权重函数,gr 是空间权重函数。而 Wp 是归一化因子,其计算方式如下:
Wp=Σxi∈Ωfr(∣∣I(xi)−I(x)∣∣)gs(∣∣xi−x∣∣)(9)
Wp=Σxi∈Ωfr(∣∣I(xi)−I(x)∣∣)gs(∣∣xi−x∣∣)
可以看到 fr 函数输入的是两个像素之间的差,而 gs 输入的是两个像素坐标之间的差。考虑一个像素,其坐标为 (i,j),而其邻域像素的坐标为 (k,l),则计算与邻域像素 (k,l) 的滤波核函数为:
w(i,j,k,l)=exp(−(i−k)2+(j−l)22σ2d−∣∣I(i,j)−I(k,l)∣∣22σ2r)(10)
w(i,j,k,l)=exp(−(i−k)2+(j−l)22σd2−∣∣I(i,j)−I(k,l)∣∣22σr2)
公式给出的核函数包含了 frfr 和 gsgs,其中左边部分就是 gsgs,而右边部分则为 frfr。在片元着色器中,我实现的双边滤波函数如下所示。这是一个暴力的两重循环,因为图像的邻域是二维的。
“”1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #version 330 core
in vec2 Texcoord;
uniform sampler2D image; uniform float filterRadius;
const float blurScale = 0.05f; const float blurDepthFalloff = 500.0f;
void main(){ // gets size of single texel. vec2 tex_offset = 1.0 / textureSize(image, 0); float sum = 0.0f; float wsum = 0.0f; float value = texture(image, Texcoord).r; for(float y = -filterRadius;y <= filterRadius;y += 1.0f) { for(float x = -filterRadius;x <= filterRadius;x += 1.0f) { float sample = texture(image, Texcoord + vec2(x, y) * tex_offset).r; // spatial domain. float r = length(vec2(x, y)) * blurScale; float w = exp(-r * r); // range domain. float r2 = (sample - value) * blurDepthFalloff; float g = exp(-r2 * r2); sum += sample * w * g; wsum += w * g; } } if(wsum >= 0.0f) sum /= wsum; gl_FragDepth = sum; }
|