Moe*_*oeb 54 c image-processing gaussianblur
我想使用原生高斯模糊公式来模糊我的图像.我读过这篇文章,但我不知道如何实现这一点.
如何使用公式来确定权重?
我不想使用MATLAB所具有的任何内置函数
Goz*_*Goz 129
写一个天真的高斯模糊实际上非常容易.它的完成方式与任何其他卷积滤波器完全相同.框和高斯滤波器之间的唯一区别是您使用的矩阵.
想象一下,您的图像定义如下:
0 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 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
Run Code Online (Sandbox Code Playgroud)
3x3盒式滤波器矩阵定义如下:
0.111 0.111 0.111
0.111 0.111 0.111
0.111 0.111 0.111
Run Code Online (Sandbox Code Playgroud)
要应用高斯模糊,您可以执行以下操作:
对于像素11,您需要加载像素0,1,2,10,11,12,20,21,22.
然后,您将像素0乘以3x3模糊滤镜的左上部分.像素1由顶部中间,像素2,像素3由右上角,像素10由中间左侧等.
然后完全添加它们并将结果写入像素11.正如您所见,Pixel 11现在是其自身和周围像素的平均值.
边缘情况确实变得复杂一些.您使用什么值来表示纹理边缘的值?一种方法可以绕到另一边.这对于稍后平铺的图像看起来很好.另一种方法是将像素推入周围的地方.
因此,对于左上角,您可以将样本放置如下:
0 0 1
0 0 1
10 10 11
Run Code Online (Sandbox Code Playgroud)
我希望你能看到它如何很容易地扩展到大型滤波器内核(即5x5或9x9等).
高斯滤波器和盒式滤波器之间的差异是矩阵中的数字.高斯滤波器在行和列上使用高斯分布.
例如,对于任意定义的滤波器(即,这不是高斯,但可能不远)
0.1 0.8 0.1
Run Code Online (Sandbox Code Playgroud)
第一列将相同但乘以上一行的第一项.
0.01 0.8 0.1
0.08
0.01
Run Code Online (Sandbox Code Playgroud)
第二列是相同的,但值将乘以上面的行中的0.8(依此类推).
0.01 0.08 0.01
0.08 0.64 0.08
0.01 0.08 0.01
Run Code Online (Sandbox Code Playgroud)
将所有上述共同的的应等于1.上述过滤器和原箱式滤波器之间的差异的结果将是写入的结束像素将具有朝向中心像素中的更重的权重(即,一种是在那个位置已经).出现模糊是因为周围的像素会模糊到该像素,尽管不是那么多.使用这种滤镜可以获得模糊,但不会破坏高频率(即从像素到像素的颜色快速变化)信息.
这些过滤器可以做很多有趣的事情.您可以通过从当前像素中减去周围像素来使用这种滤镜进行边缘检测.这将只留下颜色(高频率)的巨大变化.
编辑:5x5过滤器内核的定义与上面完全相同.
例如,如果你的行0.1 0.2 0.4 0.2 0.1然后如果你在他们乘每个值通过的第一项,形成一列,然后乘以每个通过的第二项,形成第二列等等,你会用过滤结束的
0.01 0.02 0.04 0.02 0.01
0.02 0.04 0.08 0.04 0.02
0.04 0.08 0.16 0.08 0.04
0.02 0.04 0.08 0.04 0.02
0.01 0.02 0.04 0.02 0.01
Run Code Online (Sandbox Code Playgroud)
采取一些任意位置,你可以看到位置0,0简单0.1*0.1.位置0,2为0.1*0.4,位置2,2为0.4*0.4,位置1,2为0.2*0.4.
我希望能给你一个足够好的解释.
Cec*_*ame 11
这是我在C#中用来计算内核的代码的伪代码.我不敢说我正确对待最终条件,但是:
double[] kernel = new double[radius * 2 + 1];
double twoRadiusSquaredRecip = 1.0 / (2.0 * radius * radius);
double sqrtTwoPiTimesRadiusRecip = 1.0 / (sqrt(2.0 * Math.PI) * radius);
double radiusModifier = 1.0;
int r = -radius;
for (int i = 0; i < kernel.Length; i++)
{
double x = r * radiusModifier;
x *= x;
kernel[i] =
sqrtTwoPiTimesRadiusRecip * Exp(-x * sqrtTwoPiTimesRadiusRecip);
r++;
}
double div = Sum(kernel);
for (int i = 0; i < kernel.Length; i++)
{
kernel[i] /= div;
}
Run Code Online (Sandbox Code Playgroud)
希望这可以提供帮助.