是 膨胀/侵蚀 使用固定核进行多次迭代类似于使用更大尺寸的等效核进行膨胀/侵蚀



在浏览OpenCV源代码时,我注意到对于多个迭代,它只是创建一个更大大小的内核并执行一次迭代。

所以我的问题是,如果我们采用 3x3 大小的 SQUARE 结构元素并在三次迭代中膨胀/侵蚀它,它是否与用 9x9 内核膨胀/侵蚀它相同一次。

if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols )
{
    anchor = Point(anchor.x*iterations, anchor.y*iterations);
    kernel = getStructuringElement(MORPH_RECT,
                                   Size(ksize.width + (iterations-1)*(ksize.width-1),
                                        ksize.height + (iterations-1)*(ksize.height-1)),
                                   anchor);
    iterations = 1;
}

参考Jordi的回答:

[引用] ...但是请注意,这并不适用于所有结构元素......

事实上,它以以下方式成立(不是在Jordi的例子中(:

第一步,在单个中心点 5x5 源图像上的 3x3 核中通过膨胀两次计算 5x5 核:

00000          00000          00100
00000   010    00100   010    01110
00100 + 111 -> 01110 + 111 -> 11111    ===> this is the equivalent 5x5 kernel for 2x 3x3 dilation
00000   010    00100   010    01110
00000          00000          00100

然后应用 3x3 原始膨胀核的两次相当于在更大的图像上应用这个 5x5 膨胀核。例如:

0000000000                   0000000000    00100
0000000000   010    010      0000000000    01110
0011100000 + 111  + 111  === 0011100000 +  11111
0000001000   010    010      0000001000    01110
0000000000                   0000000000    00100
0000000000                   0000000000

不过,这并不能直接回答您的问题。 但是,我不能只使用"注释",因为格式化所有这些方程/解释非常困难(如果不是不可能的话(。

事实上,对于用于膨胀的较大组合内核的二进制图像(每个像素中只有值 0 或 1 的图像(的证明很容易:

让我们将二元运算符+定义为膨胀运算符,其中第一个操作数是内核,第二个操作数是要膨胀的图像。 因此,如果我们想使用内核K对图像I进行膨胀,我们编写dilated-image = K + I

让我们将二元运算符U定义为联合运算符,或者换句话说,每个像素的二进制"OR"运算符,其中U的两个操作数必须是同一维度中的二进制图像。 例如:A U B表示在 A 和 B 的每个相应像素上执行 -OR-:

A= 0 0 1   B= 0 1 1
   1 0 1      1 1 1
   1 1 0      0 1 0

然后

A U B = 0 1 1
        1 1 1
        1 1 0

我们还定义U A(i), i=1, ..., n to be A(1) U A(2) U ... U A(n)

让我们通过在单个中心点图像上应用 n 次核K来定义K^n膨胀风格的较大内核。

注意,任何图像I,我们可以将其分解为单点图像的并集。 例如

    0 1 0      0 1 0     0 0 0     0 0 0
I = 0 0 0  === 0 0 0  U  0 0 0  U  0 0 0
    1 0 1      0 0 0     1 0 0     0 0 1

现在是时候证明这一点了:

对于任何图像I,我们定义D(i), i = 1, ..., nI的单点分解,从而I = U D(i), i = 1, ..., n

根据二元膨胀的定义,K + I == K + (U D(i)) == U (K+D(i)) .(请记住,膨胀是为了掩盖I的每个像素上的核K,并标记所有相应的 1(。

现在,让我们看看K + (K + I)是什么:

K + (K + I) == K + U (K + D(i)) 
            == U(K + (K + D(i)))     (Note: this is tricky. see Theorem 1 below)
            == U (K^2 + D(i))        (by definition of K^2)
            == K^2 + U D(i)          (by definition of the dilation)
            == K^2 + I               (since I = U D(i))

现在,我们已经知道了K + (K + I) == K^2 + I,并且很容易应用数学归纳法来证明K + K + K .. + K + I = K^n + I(注意:请应用右关联,因为我已经删除了括号(。


定理1:从K + U (K + D(i))U(K + (K+D(i)))的推论证明

只要证明对于同一维度中的任何两个二进制图像 A 和 B 就足够了, K + (A U B) = (K+A) U (K+B)

很容易看出,如果我们分解图像AB,并在分解的图像上应用核K,这些公共点(即AB的交点,或公共 1 的 AB 点(在应用核K后将贡献相同的结果点。 根据膨胀的定义,我们需要联合 A 和 B 的每个分解图像贡献的所有点。 因此定理 1 成立。

=== 更新 ===

关于kid.abr的评论"27个操作与7x7内核的49个操作":一般来说,它不是 27 个操作。 这要看情况。 例如,100x100 像素的源图像,具有 20 个奇异点 (1( 稀疏分布。 在其上应用 3x3 实体内核(即所有 1 个(3 次对于 20 个奇异点中的每一个,都需要执行以下步骤:

循环 1:9 次操作,并生成 9 个点。

循环 2:对于生成的 9 个点中的每一个,它需要 9 个操作 => 9 x 9 = 81 个步骤。它产生 25 分

循环 3:对于生成的 25 个点中的每一个,它需要 9 个操作 => 25 x 9 = 225 个步骤。

总计:9 + 81 + 225 = 315 步。

请注意,当我们访问源图像中值为 0 的像素时,我们不需要应用内核在这一点上,对吧?

因此,在应用较大内核的情况下,它需要 7x7 = 49 个步骤。

但是,如果源图像具有较大的实心区域(1(,则3步法获胜。

简短的回答:带有方形结构元素,是的。

长答案:您需要考虑侵蚀/膨胀操作的作用。 例如,膨胀将内核移动到图像上,并在它的任何网格位置为 1 时将其中心设置为 1(我假设二进制图像,它对灰度的工作方式相同(。增加结构元素中心与其边缘之间的距离与增加内核的大小相同。

但请注意,这并不适用于所有结构元素。假设你拿一个只是拉伸加号的结构元素,显然用 3 码扩张两次与用 5 码扩张一次是不一样的:

00000          00000          00100
00000   010    00100   010    01110
00100 + 111 -> 01110 + 111 -> 11111
00000   010    00100   010    01110
00000          00000          00100
00000   00100    00100
00000   00100    00100
00100 + 11111 -> 11111
00000   00100    00100
00000   00100    00100

当然,如果我们将加号的缩放版本定义为没有角的正方形(通常如此(,这确实有效。我认为一般来说,当大小为 k+1 的内核是大小为 k 的内核的膨胀版本时,此快捷方式有效,但我没有证据证明这一点。

一般内核的简短回答:膨胀/侵蚀是的,但不一定是等效内核。

来自维基百科:

    膨胀: (A⊕B(⊕C
  • = A⊕(B⊕C(
  • 侵蚀: (A⊖B(⊖C
  • = A⊖(B⊕C(

其中⊕表示形态膨胀,⊖表示形态侵蚀。

基本上,使用内核 B 对映像 A 执行侵蚀/膨胀,然后使用内核 C 对映像 C 执行侵蚀

/扩张等效于使用用 C 扩张 B 获得的内核对映像 A 执行侵蚀/扩张。这可以很容易地扩展到任意数量的侵蚀/扩张。

最新更新