1

我尝试使用 FFT 卷积计算形态侵蚀。我知道腐蚀是膨胀的双重操作。第一个问题是我不能像往常一样使用 0 作为背景。所以我有偏见我的价值观。让 0.1 值表示背景,1.0 表示前景。将背景反转为前景并使用结构元素执行 FFT 卷积(使用 scipy.signal.fftconvolve)我得到了我无法进一步解释的结果。我知道我应该以某种方式阈值解决方案并再次反转。怎么做?

我的二维信号 A:

1 1 0 1 1
1 1 1 1 1
0 1 1 1 0
1 1 1 1 1
1 1 0 1 1

结构元素 B:

0 1 0
1 1 1
0 1 0

侵蚀(A,B):

0 0 0 0 0
0 1 0 1 0
0 0 1 0 0
0 1 0 1 0
0 0 0 0 0

使用 FFT 卷积,inv(A):

0.1 0.1 1.0 0.1 0.1
0.1 0.1 0.1 0.1 0.1
1.0 0.1 0.1 0.1 1.0
0.1 0.1 0.1 0.1 0.1
0.1 0.1 1.0 0.1 0.1

和乙:

0.1 1.0 0.1
1.0 1.0 1.0
0.1 1.0 0.1

结果如下:

0.31 1.32 1.32 1.32 0.31
1.32 0.72 1.44 0.72 1.32
1.32 1.44 0.54 1.44 1.32
1.32 0.72 1.44 0.72 1.32
0.31 1.32 1.32 1.32 0.31

接下来是什么?标准化/阈值然后反转?

此致

4

2 回答 2

1

我的答案来得太晚了,但我还是给了。

  • Erode(A,B) 是错误的。这应该是答案:

1 0 0 0 1

0 1 0 1 0

0 0 1 0 0

0 1 0 1 0

1 0 0 0 1

  • 腐蚀/膨胀是秩运算,更特别是最小/最大运算,但绝对不是卷积。因此,您无法使用 FFT 执行它们。
于 2015-08-24T07:20:26.020 回答
1

通过在频率空间中相乘并逆变换回真实空间来执行卷积后,您必须将结果阈值设置为高于某个值。根据J. Kukal、D. Majerova、A. Prochazka 的白皮书 Dilation and Erosion of Gray Images with Spherical Masks>0.5 ,该阈值用于膨胀,而对于腐蚀,它是>m-0.5结构元素的体积(B 中 1 的数量) , 5 在这种情况下)。

简而言之:此代码将为您提供预期的结果。

from scipy.signal import fftconvolve
import numpy as np
def erode(A,B):
    thresh = np.count_nonzero(B)-0.5
    return fftconvolve(A,B,'same') > thresh

这将适用于任何维度并准确再现 scipy.ndimage.binary_erosion 的结果 - 至少,我已经在 2D 和 3D 中对其进行了测试。

至于此处发布的另一个对侵蚀的预期结果提出异议的答案:它取决于边界条件。scipy.ndimage.binary_erosion 和erode(A,B)这里编写的自定义函数都假设侵蚀可能从输入 A 的所有边缘发生 - 即 A 在侵蚀之前用 0 填充。如果你不喜欢这个边界条件——例如,如果你认为它应该被视为反射边界条件——那么你应该考虑使用 eg 自己填充数组np.pad(A,np.shape(B)[0],'reflect')。然后你需要在之后取消填充结果。

我在这里对细节很清楚,因为我在您提出的另一个问题上写了一个关于使用频率空间卷积执行腐蚀膨胀的更全面的答案,但我认为在这里为任何寻求它的人发布一个结论性答案是值得的。

于 2018-07-05T14:48:39.420 回答