numpy 应用scipy.signal.convolve产生的小值伪影

68de4m5k  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(105)

Python 3.11.5脚本:

import numpy as np
from skimage.io import imread
from scipy.signal import convolve

image = np.flipud(imread('conv-test.bmp').astype(np.float32))
con = convolve(image, np.ones((3, 3))/9, mode='valid')
print(image.min())
print(np.logical_and(image > 0, image < 1).any())
print(np.logical_and(con > 0, con < 0.00001).any())

生产:

0.0
False
True

如何得到小于0.00001的正值?1/9不应该是这个卷积产生的最小正值吗?

wz1wpwve

wz1wpwve1#

函数scipy.signal.convolve有一个method参数,允许您选择用于计算卷积的方法。可用的方法是直接法和FFT。如果您没有显式地设置方法,它将选择一个基于算法的方法,这通常会导致选择更快的方法。在你的情况下,它似乎选择了FFT方法。FFT受到正常浮点不精确性的影响,这可能导致理论上应该为零的值变得非常小但非零。下面是一个1D的小例子:

In [76]: x = np.zeros(18)

In [77]: x[9:] = 1

In [78]: convolve(x, np.ones(3)/3, method='fft', mode='valid')
Out[78]: 
array([-1.49880108e-16, -8.88178420e-17,  0.00000000e+00,  0.00000000e+00,
       -8.88178420e-17, -1.11022302e-16, -8.88178420e-17,  3.33333333e-01,
        6.66666667e-01,  1.00000000e+00,  1.00000000e+00,  1.00000000e+00,
        1.00000000e+00,  1.00000000e+00,  1.00000000e+00,  1.00000000e+00])

从理论上讲,该结果中的前七个值都应该为0。我们可以通过选择直接方法得到这个结果:

In [79]: convolve(x, np.ones(3)/3, method='direct', mode='valid')
Out[79]: 
array([0.        , 0.        , 0.        , 0.        , 0.        ,
       0.        , 0.        , 0.33333333, 0.66666667, 1.        ,
       1.        , 1.        , 1.        , 1.        , 1.        ,
       1.        ])

相关问题