【问题标题】:Is there a equivalent of scipy.signal.deconvolve for 2D arrays?二维数组是否有等效的 scipy.signal.deconvolve ?
【发布时间】:2017-07-26 20:44:15
【问题描述】:

我想用点扩散函数 (PSF) 对 2D 图像进行反卷积。我看到有一个scipy.signal.deconvolve 函数适用于一维数组,scipy.signal.fftconvolve 用于卷积多维数组。 scipy 中是否有特定的函数来反卷积二维数组?

我定义了一个 fftdeconvolve 函数,将 fftconvolve 中的乘积替换为除法:

def fftdeconvolve(in1, in2, mode="full"):
    """Deconvolve two N-dimensional arrays using FFT. See convolve.

    """
    s1 = np.array(in1.shape)
    s2 = np.array(in2.shape)
    complex_result = (np.issubdtype(in1.dtype, np.complex) or
                      np.issubdtype(in2.dtype, np.complex))
    size = s1+s2-1

    # Always use 2**n-sized FFT
    fsize = 2**np.ceil(np.log2(size))
    IN1 = fftpack.fftn(in1,fsize)
    IN1 /= fftpack.fftn(in2,fsize)
    fslice = tuple([slice(0, int(sz)) for sz in size])
    ret = fftpack.ifftn(IN1)[fslice].copy()
    del IN1
    if not complex_result:
        ret = ret.real
    if mode == "full":
        return ret
    elif mode == "same":
        if np.product(s1,axis=0) > np.product(s2,axis=0):
            osize = s1
        else:
            osize = s2
        return _centered(ret,osize)
    elif mode == "valid":
        return _centered(ret,abs(s2-s1)+1)

但是,下面的代码在卷积和反卷积后并没有恢复原始信号:

sx, sy = 100, 100
X, Y = np.ogrid[0:sx, 0:sy]
star = stats.norm.pdf(np.sqrt((X - sx/2)**2 + (Y - sy/2)**2), 0, 4)
psf = stats.norm.pdf(np.sqrt((X - sx/2)**2 + (Y - sy/2)**2), 0, 10)

star_conv = fftconvolve(star, psf, mode="same")
star_deconv = fftdeconvolve(star_conv, psf, mode="same")

f, axes = plt.subplots(2,2)
axes[0,0].imshow(star)
axes[0,1].imshow(psf)
axes[1,0].imshow(star_conv)
axes[1,1].imshow(star_deconv)
plt.show()

生成的二维数组显示在下图中的下一行。如何使用 FFT 反卷积恢复原始信号?

【问题讨论】:

    标签: numpy scipy convolution


    【解决方案1】:

    这些使用来自 SciPy 的 fftpack 包的 fftn、ifftn、fftshift 和 ifftshift 的函数似乎可以工作:

    from scipy import fftpack
    
    def convolve(star, psf):
        star_fft = fftpack.fftshift(fftpack.fftn(star))
        psf_fft = fftpack.fftshift(fftpack.fftn(psf))
        return fftpack.fftshift(fftpack.ifftn(fftpack.ifftshift(star_fft*psf_fft)))
    
    def deconvolve(star, psf):
        star_fft = fftpack.fftshift(fftpack.fftn(star))
        psf_fft = fftpack.fftshift(fftpack.fftn(psf))
        return fftpack.fftshift(fftpack.ifftn(fftpack.ifftshift(star_fft/psf_fft)))
    
    star_conv = convolve(star, psf)
    star_deconv = deconvolve(star_conv, psf)
    
    f, axes = plt.subplots(2,2)
    axes[0,0].imshow(star)
    axes[0,1].imshow(psf)
    axes[1,0].imshow(np.real(star_conv))
    axes[1,1].imshow(np.real(star_deconv))
    plt.show()
    

    左下图为上排两个高斯函数的卷积,右下为卷积效果的反转。

    【讨论】:

      【解决方案2】:

      请注意,傅立叶域中的除法反卷积除了演示目的之外并没有真正的用处;任何类型的噪音,即使是数字,都可能使您的结果完全无法使用。可以通过多种方式对噪声进行正则化;但根据我的经验,RL iteration 更容易实现,并且在许多方面更合理。

      【讨论】:

      • f 域中的水位划分怎么样,spec_out = spec_signal / (spec_to_deconv+waterlevel) 而不是spec_out = spec_signal / spec_to_deconv?避免 spec_to_deconv 中的小值的小扰动导致 spec_out 中的大变化。
      • 这基本上就是维纳滤波器背后的想法;但它充其量也有严格的物理理由,并且设置阈值将始终涉及噪声抑制和引入的失真之间的折衷。
      • RL 迭代是否也适用于一维时间序列?
      • 它适用于任何右手边、解和算子都具有严格非负系数的线性反演问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      相关资源
      最近更新 更多