OpenGL Shader-高斯模糊效果

3,797 阅读3分钟

「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战

均值模糊

均值模糊原理其实很简单通过多个纹理叠加,每个纹理uv偏移量设置不同达到一点重影效果来实现模糊。不过这里偏移量不能设置过于大,例如fStep一般要小于0.01的值。因为过大偏移量会就不是希望看到的模糊效果了。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    lowp vec4 sample0, sample1, sample2, sample3;
    
    float fStep = 0.005;
  
    //分别对应四个像素点
    sample0 = texture(iChannel2, vec2(uv.x - fStep, uv.y - fStep));
    sample1 = texture(iChannel2, vec2(uv.x + fStep, uv.y + fStep));
    sample2 = texture(iChannel2, vec2(uv.x + fStep, uv.y - fStep));
    sample3 = texture(iChannel2, vec2(uv.x - fStep, uv.y + fStep));

    //求平均值
    gl_FragColor = (sample0 + sample1 + sample2 + sample3) / 4.0;
}
fStep = 0.005fStep = 0.01
image.pngimage.png

均值模糊也可以加强效果,增加更多纹理图像叠加更多不同偏移量参数来实现更模糊的效果。

float fStep1 = 0.01;
sample4 = texture(iChannel2, vec2(uv.x - fStep1, uv.y - fStep1));
sample5 = texture(iChannel2, vec2(uv.x + fStep1, uv.y + fStep1));
sample6 = texture(iChannel2, vec2(uv.x + fStep1, uv.y - fStep1));
sample7 = texture(iChannel2, vec2(uv.x - fStep1, uv.y + fStep1));
gl_FragColor = (sample0 + sample1 + sample2 + sample3 + sample4 + sample5 + sample6 + sample7) / 8.0; 

image.png

不过均值模糊效果并不理想看上去并不自然,真正意义上来说更像是幻影效果。

高斯模糊

高斯模糊(Gaussian Bulr)是典型的模糊算法。高斯模糊在图像处理上通常用于减少图像噪声以及降低细节层次并对图像进行模糊处理。其实际表现效果上看就像是透过一个半透明玻璃来观察图像。在数字信号处理角度上看图片模糊本质上是过滤高频信号保留低频信号的过程,所以高斯模糊处理方式又叫做低通滤波器。 高斯模糊用到高斯核是正方形像素阵列,阵列数值对应2D高斯曲线值。

1/2561 / 256 * 1464141624164624362464162416414641\begin{vmatrix} 1 & 4 & 6 & 4 & 1 \\ 4 & 16 & 24 & 16 & 4 \\ 6 & 24 & 36 & 24 & 6 \\ 4 & 16 & 24 & 16 & 4 \\ 1 & 4 & 6 & 4 & 1 \end{vmatrix}

在阵列当中最中心位置数值越多,这和正态分布是一样的,越是接近中心点取值就越大。模糊的本质就是让当前像素值和周围像素值接近,各个像素和周围像素值同时作用。如下所示采用一个3x3的高斯核和5x5的高斯核来实现模糊效果:

// 卷积大小
const int KernelSize = 9;
const float stepValue = 0.005;
void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    int i;
    vec4 sum = vec4(0.0);
    
    //用来存储3x3的卷积矩阵
    float Kernel[KernelSize];
    Kernel[6] = 1.0; Kernel[7] = 2.0; Kernel[8] = 1.0;
    Kernel[3] = 2.0; Kernel[4] = 4.0; Kernel[5] = 2.0;
    Kernel[0] = 1.0; Kernel[1] = 2.0; Kernel[2] = 1.0;
    
     
    float fStep = stepValue;
    //像素点偏移位置
    vec2 Offset[KernelSize];
    Offset[0] = vec2(-fStep,-fStep); Offset[1] = vec2(0.0,-fStep); Offset[2] = vec2(fStep,-fStep);
    Offset[3] = vec2(-fStep,0.0);    Offset[4] = vec2(0.0,0.0);    Offset[5] = vec2(fStep,0.0);
    Offset[6] = vec2(-fStep, fStep); Offset[7] = vec2(0.0, fStep); Offset[8] = vec2(fStep, fStep);
    
    for (i = 0; i < KernelSize; i++)
    {
        vec4 tmp = texture(iChannel2, uv + Offset[i]);
        sum += tmp * Kernel[i];
    }

    gl_FragColor = sum/16.0;

}

相比较而言5x5的高斯核模糊效果好于3x3的高斯核。

3x35x5
image.pngimage.png

总结

总体来说高斯模糊效果会比均值模糊效果更好模糊效果也更加自然。虽然但是若把高斯模糊中偏移量调整到很高之后也会变成重叠阴影效果,高斯模糊更像是比均值模糊更加平滑的模糊效果。在偏移量参数调节上并不能把数值调整到太大,一般在0.005左右效果最佳。

参考

高斯模糊