在高斯模糊中将2d掩模转换为1d

Ade*_*eeb 4 image-processing gaussian linear-algebra convolution

我正在尝试实现高斯模糊.我已经使用维基百科上提供的2d函数计算了掩码.我目前有一个2d矩阵.据我所知,为了改善运行时间,可以避免使用标准卷积方法,因为高斯的可分离性.换句话说,正如本答案所说,"在高斯模糊情况下,它分解为两个一维操作".

这个页面有帮助,但是,我不明白如何从现有的2d掩码中获取1d掩码.例如,此页面将图3中的2d掩码转换为图4中的1d掩码.如何进行此转换?

[编辑]

是否足以计算1d掩模开始,并将其应用于x方向然后y?

[编辑2]

我已经弄清楚是的,人们可以简单地生成一个1d蒙版并在x和y方向上使用它.然而,问题是当我应用高斯滤波器时所得图像的质量.

原始图像(输入) 产量

我假设当计算蒙版的点积和原始图像的选定部分时,需要进行操作.什么可能导致结果图像像这样?

[编辑]

除了@Jeremie Miserez的回答之外,这个页面非常有帮助.如果需要了解如何完成,它还有代码.

jmi*_*rez 8

关于可分离卷积的这篇文章应该清楚一点.

我最近不得不这样做,所以这里是:作为一个例子,我们使用基于二维高斯分布的核,标准偏差为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
Run Code Online (Sandbox Code Playgroud)

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

>> sum(sum(h))

ans =
     1
Run Code Online (Sandbox Code Playgroud)

还要注意的是,等级为1,因此内核其实是分开的(两个矢量h1h2,这将导致在h成倍时:h1*h2=h)

>> rank(h)

ans =
     1
Run Code Online (Sandbox Code Playgroud)

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

在不详细介绍的情况下,我们使用函数进行奇异值分解svd.这是一个标准函数,计算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
Run Code Online (Sandbox Code Playgroud)

我们现在知道U*S*V'=h(V'是转置V).现在,对于秩1矩阵,S应该只有1个奇异值,其余应该为0(参见本答案末尾的讨论以获得更多信息).

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

你可以选择如何分割S你想要的,但使用平方根将Sh1和之间平均分配h2:

>> 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
Run Code Online (Sandbox Code Playgroud)

请注意,我们不需要带有零的额外行/列,因此我们可以更简单地执行此操作:

>> 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
Run Code Online (Sandbox Code Playgroud)

请注意,减号相互抵消,因此您也可以将它们从中删除h1,h2如果您愿意:

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
Run Code Online (Sandbox Code Playgroud)

这几乎与我们以前的相同:

>> h1*h2 - h

ans =
   1.0e-16 *
         0    0.2776   -0.1388
         0    0.5551   -0.2776
         0    0.2776   -0.1388
Run Code Online (Sandbox Code Playgroud)

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

>> eps
ans =
   2.2204e-16
Run Code Online (Sandbox Code Playgroud)

所以错误是微不足道的,在这种情况下由于不精确.如果你有任何比这大得多的误差,你很可能只是忽略剩余的奇异值并计算出秩-1的近似值h.在这种情况下,您可能需要查看其他选项以获得更好的近似值,例如此实现此实现.