【问题标题】:Converting 2d mask to 1d in Gaussian blur在高斯模糊中将 2d 蒙版转换为 1d
【发布时间】:2014-08-09 08:49:49
【问题描述】:

我正在尝试实现高斯模糊。我已经使用wikipedia 上提供的二维函数计算了掩码。我目前有一个二维矩阵。我知道为了提高运行时间,由于高斯的可分离性,可以避免使用标准卷积方法。换句话说,正如This answer 所说,“在高斯模糊情况下,它分解为两个一维操作”。

This page 很有帮助,但是,我不明白如何从现有的 2d 蒙版中获取 1d 蒙版。例如,this page 将图 3 中的 2d 掩码转换为图 4 中的 1d 掩码。如何进行这种转换?

[编辑]

是否足以计算一维掩码开始,并将其应用于 x 方向,然后应用于 y?

[编辑 2]

我发现是的,可以简单地生成一个 1d 蒙版并在 x 和 y 方向上使用它。然而,问题在于我应用高斯滤波器时生成的图像的质量。

我假设在计算蒙版的点积和原始图像的选定部分时需要进行一些操作。什么可能导致生成的图像是这样的?

[编辑]

除了@Jeremie Miserez 的回答之外,这个page 也非常有帮助。如果需要查看这是如何完成的,它也有代码。

【问题讨论】:

  • 我的回答解释了如何获取数字。但是,从您的图片来看,它看起来更像是一个实现问题。尝试在 Matlab 或 Octave 中测试过滤器(imfilterconv2)以确保数字不是问题(Octave 是免费的)。还要确保2d内核的总和为1,否则将无法工作。
  • 我只需要投票支持使用 Lenna 图像 (en.wikipedia.org/wiki/Lenna)

标签: image-processing linear-algebra gaussian convolution


【解决方案1】:

关于可分离卷积的This article 应该会澄清一点。

我最近不得不这样做,所以这里是:作为示例,我们使用基于标准差为 0.85 的二维高斯分布的内核。我们需要一个 3x3 内核(Matlab 代码)。

>> h = fspecial('gaussian',3,0.85)

h =
    0.0626    0.1250    0.0626
    0.1250    0.2497    0.1250
    0.0626    0.1250    0.0626

请注意,所有条目的总和为 1,即如果将其用作过滤器,图像的亮度不会改变:

>> sum(sum(h))

ans =
     1

还要注意rank 为 1,因此内核实际上是可分离的(两个向量 h1h2 相乘时将得到 hh1*h2=h

>> rank(h)

ans =
     1

太好了,我们可以继续了。请注意,如果排名大于 1,您仍然可以获得近似值,但您可能需要使用不同的技术(请参阅最后的链接)。

在不深入细节的情况下,我们使用svd 函数执行singular value decomposition。这是一个标准函数,计算 U*S*V'=h 并且在许多数学库中都可用。

>> [U,S,V] = svd(h)

U =
   -0.4085    0.9116   -0.0445
   -0.8162   -0.3867   -0.4292
   -0.4085   -0.1390    0.9021

S =
    0.3749         0         0
         0    0.0000         0
         0         0    0.0000

V =
   -0.4085   -0.3497   -0.8431
   -0.8162    0.5534    0.1660
   -0.4085   -0.7559    0.5115

我们现在知道U*S*V'=hV'V 的转置)。现在,对于秩为 1 的矩阵,S 应该只有 1 个奇异值,其余的应该是 0(有关更多信息,请参阅此答案末尾的讨论)。

所以我们现在需要的是(h1)*(h2)=h。我们可以将S 拆分为两个不同的值,这样s1*s2=S。因此我们得到:U*s1*s2*V'=h,然后是(U*s1)*(s2*V')=h

您可以根据需要选择如何拆分S,但使用平方根会将Sh1h2 之间平分:

>> h1 = U*sqrt(S)

h1 =
   -0.2501    0.0000   -0.0000
   -0.4997   -0.0000   -0.0000
   -0.2501   -0.0000    0.0000

>> h2 = sqrt(S)*V'

h2 =
   -0.2501   -0.4997   -0.2501
   -0.0000    0.0000   -0.0000
   -0.0000    0.0000    0.0000

请注意,我们不需要带零的额外行/列,因此我们可以像这样更简单:

>> h1 = U(:,1)*sqrt(S(1,1))

h1 =
   -0.2501
   -0.4997
   -0.2501

>> h2 = sqrt(S(1,1))*V(:,1)'

h2 =
   -0.2501   -0.4997   -0.2501

请注意,减号相互抵消,因此您也可以根据需要将它们从 h1h2 中删除:

h1 =
    0.2501
    0.4997
    0.2501
h2 =
    0.2501    0.4997    0.2501

>> h1*h2

ans =
    0.0626    0.1250    0.0626
    0.1250    0.2497    0.1250
    0.0626    0.1250    0.0626

这与我们之前的(几乎)相同:

>> h1*h2 - h

ans =
   1.0e-16 *
         0    0.2776   -0.1388
         0    0.5551   -0.2776
         0    0.2776   -0.1388

请注意,机器精度 eps 只是:

>> eps
ans =
   2.2204e-16

所以错误很小,在这种情况下是由于不精确造成的。如果您有任何比这大得多的错误,您很可能只是忽略了剩余的奇异值并计算了h 的 rank-1 近似值。在这种情况下,您可能需要查看其他选项以获得更好的近似值,例如this implementationthis implementation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 2022-01-17
    • 2019-02-03
    • 1970-01-01
    相关资源
    最近更新 更多