3.2.1 高斯滤波(Gauss Filter)

高斯滤波是我们最常用的一种滤波器。

想要理解高斯滤波的作用,首先需要回顾一下 高斯分布(Gaussian Distribution),即 正态分布(Normal Distribution) 的数学特征。高斯分布公式 :

f(x,μ)=12πδe(xμ)22δ2 f(x,\mu) = \frac{1}{\sqrt{2\pi} \cdot \delta} e ^{-\tfrac{(x-\mu)^2}{2 \cdot \delta^2}}

其在 xx 为一维时的平面的对应分布如下:

图 3.2.1-1 一维正态分布示意图

从图像可见,高斯分布的 μ\mu 决定了分部的中心,而 δ\delta 决定了形变的剧烈程度。而线下曲线面积,则代表了对应区间段内的取值发生概率。从离散角度则指 xint[xcn2,xc+n2]x \in int[x_c-\tfrac{n}2, x_c+\tfrac{n}2] 范围内,有 x=xcx = x_c 的取值概率为 f(xc)f(x_c)

记原信号为 S(x)S(x) 。以 target1\vert target \vert_1 表示归一化操作,则 xcn/2xc+n/2(f(x)S(x))1\vert {\sum}_{x_c -n/2}^{x_c+n/2}(f(x) \cdot S(x)) \vert_1 代表在当前给定 (δ,μ)(\delta, \mu) 的高斯分布 f(x,μ)f(x, \mu) 下,考虑 x=xcx = x_c 时左右相邻含 xcx_c 在内共 nn 个节点取值情况的 S(xc)S(x_c) 的概率均值。我们记 xcx_c 为中心点,数据采样数为 TT ,有:

xcint[n2,Tn2],nintoddsFn(xc)=xcn/2xc+n/2(f(x,xc)S(x))1 {\displaystyle \begin{aligned} x_c \in &int [\tfrac{n}{2}, T-\tfrac{n}{2}], \quad n \in int_{odds} \\ \\ F_n(x_c) &= \vert {\sum}_{x_c -n/2}^{x_c+n/2}(f(x, x_c) \cdot S(x)) \vert_1 \\ \end{aligned} }

上式中,Fn(xc)F_n(x_c) 即为一维情况下的 nn 步滑动窗口,也可以称为 n×1n \times 1 卷积核。通过沿信号的数据顺序,滑动 Fn(xc)F_n(x_c) 求取原值 xcx_c 替换值的操作。我们可以在一定程度上利用分布的概率关系,以调整 δ\delta 取值的方式来影响核内相邻数据的波动性,进而影响整体波动性达到滤波目的。 δ\delta 越小,波动性越强越激烈,图片越尖锐;反之 δ\delta 越大,波动性越弱越平缓,图片越模糊。

一维信号早期常用这种手段来一定程度的进行降噪(现今已被优秀和复杂的多的算法替换了)。而二维信号,即图片,在我们之前讲解傅里叶变化时以提到过,和一维主要差别是在维度上。所以当我们记数据采样数为 (W×H)(W \times H) ,有将 xx 换为向量 x=(x,y)\vec{x} = (x,y) 表示:

xcint[n2,Wn2],ycint[n2,Hn2]nintoddsFn(xc)=Fn(xc,yc)=ycn/2yc+n/2xcn/2xc+n/2(f(x,xc)S(x))1 {\displaystyle \begin{aligned} x_c \in &int [\tfrac{n}{2}, W-\tfrac{n}{2}], \quad y_c \in int [\tfrac{n}{2}, H-\tfrac{n}{2}] \quad n \in int_{odds} \\ \\ F_n(\vec{x_c}) &= F_n(x_c, y_c) =\vert {\sum}_{y_c -n/2}^{y_c+n/2}{\sum}_{x_c -n/2}^{x_c+n/2}(f(\vec{x}, \vec{x_c}) \cdot S(\vec{x})) \vert_1 \\ \end{aligned} }

Fn(xc)F_n(\vec{x_c}) 即为二维情况下的 n×nn \times n 高斯滤波卷积核。同理,更多维情况只需要扩展参数 x\vec{x} 的向量空间即可。

可是看上去,目前的公式算不上简单。但真的是这样吗?

假设 n=3n = 3 那么 3×33 \times 3 高斯滤波卷积核,实际描述的是 xc\vec{x_c} 点周围单位距离内,相邻含 xc\vec{x_c} 在内共 99 个节点的波动关系,有:

Fn(xc)=xySxyf((xc,yc)[(1,1),(0,1),(1,1)(1,0),(0,0),(1,0)(1,1),(0,1),(1,1)])1=xySxyf(xcN3×3)1 {\displaystyle \begin{aligned} F_n(\vec{x_c}) &= \vert \sum_{xy} S_{xy} \cdot f ( (x_c,y_c) - { \begin{bmatrix} (-1, -1) ,& \quad (\quad 0, -1) ,& \quad (\quad 1, -1) \\ (-1,\quad 0) ,& \quad (\quad 0,\quad 0) ,& \quad (\quad 1,\quad 0) \\ (-1,\quad 1) ,& \quad (\quad 0,\quad 1) ,& \quad (\quad 1,\quad 1) \end{bmatrix} }) \vert_1 \\ &= \vert \sum_{xy}S_{xy} \cdot f ( \vec{x_c} - \vec{N_{3 \times 3}} ) \vert_1 \\ \end{aligned} }

一般情况,我们不会在单批(single batch)数据处理时,改变 δ\delta 的取值。假设 δ\delta 为标准正态分布取值 δ=1\delta=1 ,那么 f(x,μ)f(\vec{x},\vec{\mu}) 有:

f(x,μ)=12πe12(xμ)2 f(\vec{x},\vec{\mu}) = \frac{1}{\sqrt{2\pi}} e ^{-\tfrac{1}{2}(\vec{x}-\vec{\mu})^2}

显然, f(x,μ)f(\vec{x},\vec{\mu})δ\delta 取固定值的情况下,只和 (xμ)(\vec{x}-\vec{\mu}) 的计算有关。而由于我们取 μ=xc\vec{\mu} = \vec{x_c} ,在 (xμ)(\vec{x}-\vec{\mu}) 的计算中:

(xμ)=(xxc)=N3×3 \sum(\vec{x}-\vec{\mu}) = \sum(\vec{x}-\vec{x_c}) = \vec{N_{3 \times 3}}

正好消除了变化的 x\vec{x} 的部分,因此 Fn(xc)F_n(\vec{x_c}) 可以被化简为:

Fn(xc)=xySxyf(xcN3×3)1=xySxyf(N3×3)1=xySxy(12πe12(Δx2+Δy2))xy1=xySxy[0.075,0.124,0.0750.124,1.000,0.1240.075,0.124,0.075]1 {\displaystyle \begin{aligned} F_n(\vec{x_c}) &= \vert \sum_{xy}S_{xy} \cdot f ( \vec{x_c} - \vec{N_{3 \times 3}} ) \vert_1 = \vert \sum_{xy}S_{xy} \cdot f (\vec{N_{3 \times 3}} ) \vert_1 \\ &= \sum_{xy}S_{xy} \cdot \vert ( \frac{1}{\sqrt{2\pi}} e ^{-\tfrac{1}{2}(\Delta x^2+\Delta y^2)} )_{xy} \vert_1 \\ &= \sum_{xy}S_{xy} \cdot \vert { \begin{bmatrix} 0.075 ,& \quad 0.124 ,& \quad 0.075 \\ 0.124 ,& \quad 1.000 ,& \quad 0.124 \\ 0.075 ,& \quad 0.124 ,& \quad 0.075 \end{bmatrix} } \vert_1 \\ \end{aligned} }

我们只需要依次计算卷积核范围内的点,对应信号值与概率相乘之和即可,即:

Fn(xc)=0.075S(xc1,yc1)+0.124S(xc,yc1) +0.075S(xc+1,yc1) +0.124S(xc1,yc)+1.000S(xc,yc)+0.124S(xc+1,yc) +0.075S(xc1,yc1)+0.124S(xc,yc+1) +0.075S(xc+1,yc+1)1 {\displaystyle \begin{aligned} F_n(\vec{x_c}) = \vert & 0.075 \cdot S_{(x_c-1,y_c-1)} + 0.124 \cdot S_{(x_c,y_c-1)}\ + 0.075 \cdot S_{(x_c+1,y_c-1)} \ + \\ & 0.124 \cdot S_{(x_c-1,y_c )}\quad + 1.000 \cdot S_{(x_c,y_c)}\quad + 0.124 \cdot S_{(x_c+1,y_c)} \quad \ + \\ & 0.075 \cdot S_{(x_c-1,y_c-1)} + 0.124 \cdot S_{(x_c,y_c+1)}\ + 0.075 \cdot S_{(x_c+1,y_c+1)} \vert_1 \\ \end{aligned} }

为了保证输入输出数据一致。根据卷积核的大小,我们还需要在数据的外围补充一圈空值,以保证感受野等大数据源。如果当前需要处理的数据为 (W×H)=(5×5)(W \times H) = (5 \times 5) ,即总共 2525 个像素的单通道灰度图。经过 n×n=3×3n \times n = 3 \times 3 大小的高斯卷积核处理后,有如下结果:



不难发现上面的 求值过大,这是因为我们 并没有 使用 δ=1.0\delta = 1.0 时归一化后的高斯算子:

f(N3×3)=[0.075,0.124,0.0750.124,1.000,0.1240.075,0.124,0.075]1=[0.042,0.069,0.0420.069,0.557,0.0690.042,0.069,0.042] {\displaystyle \begin{aligned} f(\vec{N_{3 \times 3}}) &= \vert { \begin{bmatrix} 0.075 ,& \quad 0.124 ,& \quad 0.075 \\ 0.124 ,& \quad 1.000 ,& \quad 0.124 \\ 0.075 ,& \quad 0.124 ,& \quad 0.075 \end{bmatrix} } \vert_1 = { \begin{bmatrix} 0.042 ,& \quad 0.069 ,& \quad 0.042 \\ 0.069 ,& \quad 0.557 ,& \quad 0.069 \\ 0.042 ,& \quad 0.069 ,& \quad 0.042 \end{bmatrix} } \\ \end{aligned} }

当然,也可以直接除以 f(N3×3)f(\vec{N_{3 \times 3}}) 矩阵的秩,即 f(N3×3)δ=1.0=1.796\vert f(\vec{N_{3 \times 3}}) \vert_{\delta = 1.0} = 1.796 ,作用在最终结果上。完成这一步后,整个高斯滤波单元才真正封装完毕。

对一张 (W×H)(W \times H) 的图片,单次标准高斯滤波需要经过 O(N)=((W(n2))×(H(n2))×8)O(N) =((W-(n-2)) \times (H-(n-2)) \times 8) 次加法运算,外加单独进行的一次 n×nn \times n 卷积核大小的 f(x,μ)f(\vec{x},\vec{\mu}) 归一化概率计算。而通过计算 f(x,μ)f(\vec{x},\vec{\mu}) 得到的 f(N3×3)f(\vec{N_{3 \times 3}}) ,在 δ\delta 发生改变前都可以无限复用。因此,算法非常快捷。

高斯滤波的简易 GLSL 渲染程序片

现在,我们可以依据理论来做 GPU 的动态管线程序片封装了。

首先,我们需要定义 顶点程序片(Vertex Shader)。通过该程序片指定 GPU 的绘制区域,以及纹理与物体的点位映射。由于我们是对整个视窗界面进行处理,所以可以采用对传入的顶点数据进行坐标变换的方式,来求得顶点映射的纹理坐标,减少少量数据通信:

attribute vec3 position;

varying vec4 fs_position;
varying vec2 fs_texcoord;

void main()
{
    fs_position = vec4(position.x, position.y, position.z, 1.0);
    fs_texcoord = (position.xy + vec2(1.0, 1.0)) / 2.0;
    gl_Position = fs_position;
}

没有太多操作,因为关键的部分在 像素程序片(Pixel Shader/Fragment Shader) 上:

precision mediump float;

varying vec4 fs_position;
varying vec2 fs_texcoord;

uniform vec2 pixel_bias;
uniform mat3 gaussian_matrix;
uniform sampler2D target_texture;

void main()
{
    vec3 output_;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            vec2 bias = vec2(i-1, j-1) * pixel_bias;
            output_ += texture2D(target_texture, fs_texcoord.xy + bias).rgb * gaussian_matrix[i][j];
        }
    }
    gl_FragColor = vec4(output_, 1.0);
}

完成对算法求和过程的迁移。传入的 高斯算子 gaussian_matrix相邻像素归一化的偏移距离 pixel_bias 的操作,只需要在执行前由 CPU 计算一次即可。由于采用 Web 展示,此处方法以 JavaScript 语法实现:

function pixel_bias(width, height) {
    return new Float32Array([
        1.0 / width, 1.0 / height
    ]);
}

function calculate_gaussian_kernel(step, delta) {
    let n = step * 2 + 1;
    let kernel = new Float32Array(n * n);
    let factor_1 = 1.0 / (Math.sqrt(2.0 * Math.PI) * delta);
    let factor_2 = 1.0 / (2.0 * delta * delta);

    let normalize_div = 0;
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            let diff = Math.pow(i - step, 2) + Math.pow(j - step, 2);
            kernel[j + n * i] = factor_1 * Math.exp(-diff * factor_2);
            normalize_div += kernel[i];
        }
    }
    for (let i = 0; i < kernel.length; i++) {
        kernel[i] /= normalize_div;
    }
    return kernel;
}

至此,一个简单但实用的高斯滤波器就完成了。除了上述这种使用卷积核大小一对一采样的方式外,采用单一方向的高斯滤波滑动窗口,如 vn×1=(vx,vy)orient\vec{v}_{n \times 1} = (v_x, v_y)_{orient} ,也是一种减少采样数量,从而提高运算效率的方式。但由于只有指定方向的颜色关系参与了运算,单一方向高斯滤波,或者说更为通用的是近乎所有单一方向的滤波器,对数据处理后的结果,都只会表现为固定方向的过滤效果。这会使画面显得有些割裂,因此建议慎重使用。

而如果要求在保证滤波效果的同时,还能精简运算。那么我们就需更为快捷且采样更少的高斯单元了。

高斯滤波的线性插值采加速

一种通用的方式,就是在采样时引入 线性插值(Linear Sampling),减少采样次数。我们用 WW 代表高斯算子,用 Wij=w(x)W_{ij} =w(\vec{x}) 代表高斯算子在 x\vec{x} 所处 N3×3\vec{N_{3 \times 3}} 中位置的对应 fij(N3×3)f_{ij} ( \vec{N_{3 \times 3}}) 值,用 s(x)s(\vec{x}) 代表 x\vec{x} 在图片中的像素值。则对于采样 3×33 \times 3N3×3\vec{N_{3 \times 3}} 来说,由差值公式:

sdst(x1,x2)=ssrc(x1)wsrc(x1)+ssrc(x2)wsrc(x2)wsrc(x1)+wsrc(x2) {\displaystyle \begin{aligned} s_{dst}(\vec{x_1},\vec{x_2}) &= \frac{s_{src}(\vec{x_1}) \cdot w_{src}(\vec{x_1}) + s_{src}(\vec{x_2}) \cdot w_{src}(\vec{x_2})}{w_{src}(\vec{x_1}) + w_{src}(\vec{x_2})} \\ \end{aligned} }

可知,99 次采样能够两两差值,从而减少到只需 55 次实际的纹理数据读。卷积核的采样位置,取四角记为 [C1,C2,C3,C4]=[S(xc1,yc1),S(xc1,yc+1),S(xc+1,yc1),S(xc+1,yc+1)][C_1, C_2, C_3, C_4] =[S_{(x_c-1,y_c-1)} , S_{(x_c-1,y_c+1)}, S_{(x_c+1,y_c-1)}, S_{(x_c+1,y_c+1)}] 和中心 C0=S(xc,yc)C_0 = S_{(x_c,y_c)} ,如下:

Samplexy[1,0,10,1,01,0,1]=[C1C2C0C3C4] {\displaystyle \begin{aligned} Sample_{xy} \cdot { \begin{bmatrix} 1 ,& \quad 0 ,& \quad 1 \\ 0 ,& \quad 1 ,& \quad 0 \\ 1 ,& \quad 0 ,& \quad 1 \end{bmatrix} } = { \begin{bmatrix} C_1 & \quad & \quad C_2 \\ & \quad C_0 \\ C_3 & \quad & \quad C_4 \end{bmatrix} } \\ \end{aligned} }

Fn(xc)F_n(\vec{x_c}) 就可以表示为:

Fn(xc)=W00C1 +W01C12 +W02C2  +W10C13+W11C0  +W12C24 +W20C3 +W21C34 +W22C4=W00C1 +W01W00C1+W02C2W00+W02  +W02C2 +W10W00C1+W20C3W00+W20  +W11C0 +W12W02C2+W22C4W02+W22  +W20C3 +W21W20C3+W22C4W20+W22  +W22C4=(W00 + W00W01W00 + W02+W00W10W00 + W20)C1 +(W02 + W02W01W00 + W02+W02W12W02 + W22)C2 +(W20 + W20W10W00 + W20+W20W21W20 + W22)C3 +(W22 + W22W12W02 + W22+W22W21W20 + W22)C4 +W11C0 {\displaystyle \begin{aligned} F_n(\vec{x_c}) =& W_{00} \cdot C_1 \ + W_{01} \cdot C_{12} \ + W_{02} \cdot C_{2} \ \ + \\ & W_{10} \cdot C_{13} + W_{11} \cdot C_{0} \ \ + W_{12} \cdot C_{24} \ + \\ & W_{20} \cdot C_3 \ + W_{21} \cdot C_{34} \ + W_{22} \cdot C_{4} \\ =& W_{00} \cdot C_1 \ + W_{01} \cdot \tfrac{W_{00} \cdot C_1 + W_{02} \cdot C_2}{W_{00} + W_{02} } \ \ + \\ & W_{02} \cdot C_{2} \ + W_{10} \cdot \tfrac{W_{00} \cdot C_1 + W_{20} \cdot C_3}{W_{00} + W_{20} } \ \ + \\ & W_{11} \cdot C_{0} \ + W_{12} \cdot \tfrac{W_{02} \cdot C_2 + W_{22} \cdot C_4}{W_{02} + W_{22} } \ \ + \\ & W_{20} \cdot C_{3} \ + W_{21} \cdot \tfrac{W_{20} \cdot C_3 + W_{22} \cdot C_4}{W_{20} + W_{22} } \ \ + \\ & W_{22} \cdot C_{4} \\ =& (W_{00}\ +\ \tfrac{W_{00} \cdot W_{01}}{W_{00}\ +\ W_{02}} + \tfrac{W_{00} \cdot W_{10}}{W_{00}\ +\ W_{20}})\cdot C_1 \ + \\ & (W_{02}\ +\ \tfrac{W_{02} \cdot W_{01}}{W_{00}\ +\ W_{02}} + \tfrac{W_{02} \cdot W_{12}}{W_{02}\ +\ W_{22}})\cdot C_2 \ + \\ & (W_{20}\ +\ \tfrac{W_{20} \cdot W_{10}}{W_{00}\ +\ W_{20}} + \tfrac{W_{20} \cdot W_{21}}{W_{20}\ +\ W_{22}})\cdot C_3 \ + \\ & (W_{22}\ +\ \tfrac{W_{22} \cdot W_{12}}{W_{02}\ +\ W_{22}} + \tfrac{W_{22} \cdot W_{21}}{W_{20}\ +\ W_{22}})\cdot C_4 \ + \\ & W_{11} \cdot C_{0} \\ \end{aligned} }

看上去很复杂,但取中心点的二维高斯分布,其 fij(N3×3)f_{ij} (\vec{N_{3 \times 3}} ) 的值是随 xc\vec{x_c} 中心对称的,有:

W0=[W11]W1=[W01=W10=W12=W21]W2=[W00=W02=W20=W22] {\displaystyle \begin{aligned} W_0 &= [W_{11}] \\ W_1 &= [W_{01} = W_{10} = W_{12} = W_{21}] \\ W_2 &= [W_{00} = W_{02} = W_{20} = W_{22}] \\ \end{aligned} }

带入到线性插值 Fn(xc)F_n(\vec{x_c}) 表达式,则:

Fn(xc)=W0C0+[(W1 + W2)(C1 +C2 +C3 +C4 )] {\displaystyle \begin{aligned} F_n(\vec{x_c}) =& W_0 \cdot C_0 +[(W_1\ +\ W_2)\cdot (C_1 \ + C_2 \ + C_3 \ + C_4 \ )] \\ \end{aligned} }

当取 δ=1.0\delta = 1.0 时,三值得到固定的归一化取值 [W0,W1,W2]=[0.557, 0.069, 0.042][W_0,W_1,W_2] = [0.557,\ 0.069,\ 0.042] ,而 Fn(xc)F_n(\vec{x_c}) 的表达式就只和采样相关了:

Fn(xc)=0.557C0 + 0.111(C1 +C2 +C3 +C4 ) {\displaystyle \begin{aligned} F_n(\vec{x_c}) = 0.557 \cdot C_0\ +\ 0.111 \cdot (C_1 \ + C_2 \ + C_3 \ + C_4 \ ) \\ \end{aligned} }

所以,插值采样的高斯滤波非常精简。只需要略微调整像素程序片(Pixel Shader/Fragment Shader)的实现,而不需要对其他处理进行改动,就能完成改造

precision mediump float;

varying vec4 fs_position;
varying vec2 fs_texcoord;

uniform vec2 pixel_bias;
uniform mat3 gaussian_matrix;
uniform sampler2D target_texture;

void main()
{
    float gauss_factor = gaussian_matrix[0][0]+gaussian_matrix[0][1];
    vec3 output_;
    output_ += texture2D(target_texture, fs_texcoord.xy ).rgb * gaussian_matrix[1][1];
    output_ += texture2D(target_texture, fs_texcoord.xy + vec2(-1, -1) * pixel_bias).rgb * gauss_factor;
    output_ += texture2D(target_texture, fs_texcoord.xy + vec2(-1, +1) * pixel_bias).rgb * gauss_factor;
    output_ += texture2D(target_texture, fs_texcoord.xy + vec2(+1, -1) * pixel_bias).rgb * gauss_factor;
    output_ += texture2D(target_texture, fs_texcoord.xy + vec2(+1, +1) * pixel_bias).rgb * gauss_factor;
    gl_FragColor = vec4(output_, 1.0);
}

加速后的高斯滤波单元,对一张 (W×H)(W \times H) 图片的处理的理论耗时,减少到了原耗时的 0.625O(N)0.625 \cdot O(N) 。采样数也同比减少了 37.5%37.5\% 。效果上和直算相比,几乎无差别

高斯滤波的局限性

由于高斯滤波的通用卷积核是 各向同性(Isotropic) 的,在核范围内的各方向向量与中心点的方差,仅和向量终点与核中心点的相对距离有关。因此,高斯滤波并不是没有弊端的。

我们仍然选择 μ=xc\mu = \vec{x_c} 为核中心,假设核范围内有不包含 xc\vec{x_c} 在内的,总计为 NNnn 维向量 x=(x1,x2, ... ,xn)Rn\vec{x} = (x_1,x_2,\ ...\ ,x_n) \in \mathbb{R}^n 的采样数据 SN={Sx1,Sx2, ... ,SxN}S_N = \{ S_{\vec{x_1}} , S_{\vec{x_2}},\ ...\ , S_{\vec{x_N}} \} 。将高斯滤波卷积核的离散程度,以非概率密度 协方差矩阵(Covariance Matrix)Mcov(x)M_{cov}(\vec{x}) 形式表示,记 II 为单位对角矩阵,有:

Mcov(x)=1Ni=1NSxi[(x1xc1)2(x2xc2)2...(xnxcn)2]=Δx2IRn×n {\displaystyle \begin{aligned} M_{cov}(\vec{x}) &= \tfrac{1}{N} \sum_{i = 1}^{N} S_{\vec{x_i}} \cdot { \begin{bmatrix} (x_1-x_{c1})^2 & \quad & \quad & \quad \\ & \quad (x_2-x_{c2})^2 & \quad & \quad \\ & \quad & \quad ... & \quad\\ & \quad & \quad & \quad (x_n-x_{cn})^2 \end{bmatrix} } \\ &= \sum \Delta x^2 \cdot I \in \mathbb{R}^{n \times n} \\ \end{aligned} }

多维高斯的协方差矩阵,只有对角线的 方差(Variance)存在非 00 取值,而衡量参数交叠影响的 协方差(Covariance)皆为 00。所以,高斯滤波没有考虑维度方位信息带来的数据间的差异,每一个维度仅对自身属性产生影响。因此,高斯核总是中心对称

这一特征体现在二维信号的处理上时,就表现为经过高斯滤波处理的图片,轮廓细节会有所丢失(物体更不容易分辨,而非单纯颜色变得规整)。同时,也更容易因为算法导致的频率扰动,产生高频变化规律缺失,像素朝核的外边缘等量的分散运动而出现摩尔纹(Moire Pattern)。毕竟图片的高频部分,才是保存轮廓信息的关键。但高斯滤波本质上却是全通量的概率权重控制。

那么有没有能够在一定程度上,既保留高频细节的同时,又能够相对独立的处理低频波动的算法呢?

考虑问题主要出现在高斯滤波的各向同性,或许可以通过引入高低频差异修饰滤波器,来达成要求。这种做法被称为 边缘保存(Edge Preserving)

Copyright © Since 2021 李述博 (Arikan.Li) , All Rights Reserved all right reserved,powered by GitbookLast Updated: 2024-03-22 18:02:17

results matching ""

    No results matching ""