在高斯模糊中将2d掩模转换为1d [英] Converting 2d mask to 1d in Gaussian blur
问题描述
我正在尝试实现高斯模糊。我已经使用非常有帮助。它还有代码,如果需要看看如何完成。
这篇关于可分卷积的文章应该清楚一点。
我最近不得不这样做,所以这里是:作为一个例子,我们使用基于二维高斯分布的核,标准差为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,即如果将其应用为过滤器,图像的亮度不会改变:
>>总和(总和(h))
ans =
1
另请注意,排名为1,因此内核实际上是可分的(两个向量)乘以时, h1
和 h2
将导致 h
: h1 * h2 = h
)
>>等级(h)
ans =
1
很棒,我们可以继续请注意,如果排名大于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
我们现在知道了那个 所以我们现在需要的是 您可以选择如何拆分 请注意,我们不需要带有零的额外行/列,因此我们可以更简单地执行此操作: 注意减号相互抵消,所以你也可以从 这几乎与以前相同: 请注意机器精度 所以错误是微不足道的在这种情况下由于不精确。如果您有任何大于此的误差,您很可能只是忽略剩余的奇异值并计算 I am trying to implement the Gaussian blur. I have already computed the mask using the 2d function provided on wikipedia. I currently have a 2d matrix. I understand that in order to improve the running time, one can avoid using standard convolution methods due to the seperability of the Gaussian. In other words, as this This answer says, "In the Gaussian blur case it breaks down to two one dimensional operations". This page has been helpful, however, I do not understand how to obtain a 1d mask from the existing 2d mask. For instance, this page converts the 2d mask in figure 3 to the 1d mask in figure 4. How does one do this conversion? [EDIT] Is is sufficient to compute a 1d mask to begin with, and apply it the x direction and then the y? [EDIT 2] I have figured out that yes, one can simply generate a 1d mask and use it on both x and y directions. The problem, however, is the quality of the resulting image when I apply my Gaussian filter. I assume there are manipulations that need to be done when one computes the dot product of the mask and the selected section of the original image. What could cause the resultant image to be like this? [EDIT] In addition to @Jeremie Miserez's answer, this page was extremely helpful. It also has code if one needs to see how this is done. This article on separable convolution should clear things up a bit. I just recently had to do this, so here goes: As an example, we use a kernel based on a 2-dimensional Gaussian distribution with a standard deviation of 0.85. We'll want a 3x3 kernel (Matlab code). Note that the sum of all entries is 1, i.e. the brightness of an image will not change if you apply this as a filter: Also note that the rank is 1, thus the kernel is actually separable (two vectors Great, we can proceed. Note that if the rank is greater than 1, you could still get an approximation, but you might need to use a different technique (see links at the end). Without going into the details, we do singular value decomposition using the We now know that So what we need now is You can choose how to split Note that we don't need the extra rows/columns with zeros, so we can do it simpler like this: Note the minus signs cancel each other out, so you could also just remove them from Which is (almost) the same as what we had before: Note that machine precision so the error is miniscule and in this case due to imprecision. If you have any error much larger than this, you most likely simply ignored the remaining singular values and calculated a rank-1 approximation of 这篇关于在高斯模糊中将2d掩模转换为1d的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! U * S * V'= h
( V'
是 V <的转置/ code>)。现在,对于排名1矩阵,
S
应该只有1个奇异值,其余应该为0(有关详细信息,请参阅本答案末尾的讨论)。 / p>
(h1)*(h2)= h
。我们可以将 S
拆分为两个不同的值,以便 s1 * s2 = S
。因此我们得到: U * s1 * s2 * V'= h
,然后(U * s1)*(s2 * V')= h
。
S
然后使用平方根将在 h1
和 h2
之间平均分配 S
:
>> 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
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
>> 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
的等级1近似值。在这种情况下,您可能需要查看其他选项以获得更好的近似值,例如此实施或此实现。>> 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
>> sum(sum(h))
ans =
1
h1
and h2
that will result in h
when multiplied: h1*h2=h
)>> rank(h)
ans =
1
svd
function. This is a standard function, computes U*S*V'=h
and is available in many math libraries.>> [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'=h
(V'
is the transpose of V
). Now, for a rank 1 matrix, S
should just have 1 singular value, the rest should be 0 (see discussion at the end of this answer for more on that).(h1)*(h2)=h
. We can split S
in two different values so that s1*s2=S
. Thus we get: U*s1*s2*V'=h
, and then (U*s1)*(s2*V')=h
.S
however you want, but using the square root will divide S
equally between h1
and 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
>> 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
h1
and h2
if you like: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
is just:>> eps
ans =
2.2204e-16
h
. In that case, you might want look into other options to get better approximations, e.g. this implementation or this implementation.