gpt4 book ai didi

python - 了解 scipy 反卷积

转载 作者:太空狗 更新时间:2023-10-29 16:56:22 24 4
gpt4 key购买 nike

我正在努力理解 scipy.signal.deconvolve .

从数学的角度来看,卷积只是傅立叶空间中的乘法,所以我期望对于两个函数 fg:
反卷积(卷积(f,g),g)== f

在 numpy/scipy 中,情况并非如此,或者我遗漏了重要的一点。尽管已经有一些与 SO 上的反卷积相关的问题(如 herehere),但它们并未解决这一点,其他问题仍不清楚(this)或未得到解答(here)。 SignalProcessing SE 上还有两个问题(thisthis),其答案对理解 scipy 的反卷积函数的工作原理没有帮助。

问题是:

  • 如何从卷积信号重建原始信号 f,假设你知道卷积函数 g.?
  • 或者换句话说:这个伪代码 Deconvolve(Convolve(f,g) , g) == f 如何转换为 numpy/scipy?

编辑:请注意,这个问题的目的不是为了防止数值不准确(尽管这也是一个 open question),而是为了理解卷积/反卷积在 scipy 中如何协同工作。

以下代码尝试使用 Heaviside 函数和高斯滤波器来实现。从图中可以看出,卷积反卷积的结果并不在所有原始的 Heaviside 函数。如果有人能阐明这个问题,我会很高兴。

import numpy as np
import scipy.signal
import matplotlib.pyplot as plt

# Define heaviside function
H = lambda x: 0.5 * (np.sign(x) + 1.)
#define gaussian
gauss = lambda x, sig: np.exp(-( x/float(sig))**2 )

X = np.linspace(-5, 30, num=3501)
X2 = np.linspace(-5,5, num=1001)

# convolute a heaviside with a gaussian
H_c = np.convolve( H(X), gauss(X2, 1), mode="same" )
# deconvolute a the result
H_dc, er = scipy.signal.deconvolve(H_c, gauss(X2, 1) )


#### Plot ####
fig , ax = plt.subplots(nrows=4, figsize=(6,7))
ax[0].plot( H(X), color="#907700", label="Heaviside", lw=3 )
ax[1].plot( gauss(X2, 1), color="#907700", label="Gauss filter", lw=3 )
ax[2].plot( H_c/H_c.max(), color="#325cab", label="convoluted" , lw=3 )
ax[3].plot( H_dc, color="#ab4232", label="deconvoluted", lw=3 )
for i in range(len(ax)):
ax[i].set_xlim([0, len(X)])
ax[i].set_ylim([-0.07, 1.2])
ax[i].legend(loc=4)
plt.show()

enter image description here

编辑:注意有一个matlab example ,展示了如何使用

对矩形信号进行卷积/反卷积
yc=conv(y,c,'full')./sum(c); 
ydc=deconv(yc,c).*sum(c);

本着这个问题的精神,如果有人能够将这个示例翻译成 python,它也会有所帮助。

最佳答案

经过反复试验,我发现了如何解释 scipy.signal.deconvolve() 的结果,并将我的发现作为答案发布。

让我们从一个工作示例代码开始

import numpy as np
import scipy.signal
import matplotlib.pyplot as plt

# let the signal be box-like
signal = np.repeat([0., 1., 0.], 100)
# and use a gaussian filter
# the filter should be shorter than the signal
# the filter should be such that it's much bigger then zero everywhere
gauss = np.exp(-( (np.linspace(0,50)-25.)/float(12))**2 )
print gauss.min() # = 0.013 >> 0

# calculate the convolution (np.convolve and scipy.signal.convolve identical)
# the keywordargument mode="same" ensures that the convolution spans the same
# shape as the input array.
#filtered = scipy.signal.convolve(signal, gauss, mode='same')
filtered = np.convolve(signal, gauss, mode='same')

deconv, _ = scipy.signal.deconvolve( filtered, gauss )
#the deconvolution has n = len(signal) - len(gauss) + 1 points
n = len(signal)-len(gauss)+1
# so we need to expand it by
s = (len(signal)-n)/2
#on both sides.
deconv_res = np.zeros(len(signal))
deconv_res[s:len(signal)-s-1] = deconv
deconv = deconv_res
# now deconv contains the deconvolution
# expanded to the original shape (filled with zeros)


#### Plot ####
fig , ax = plt.subplots(nrows=4, figsize=(6,7))

ax[0].plot(signal, color="#907700", label="original", lw=3 )
ax[1].plot(gauss, color="#68934e", label="gauss filter", lw=3 )
# we need to divide by the sum of the filter window to get the convolution normalized to 1
ax[2].plot(filtered/np.sum(gauss), color="#325cab", label="convoluted" , lw=3 )
ax[3].plot(deconv, color="#ab4232", label="deconvoluted", lw=3 )

for i in range(len(ax)):
ax[i].set_xlim([0, len(signal)])
ax[i].set_ylim([-0.07, 1.2])
ax[i].legend(loc=1, fontsize=11)
if i != len(ax)-1 :
ax[i].set_xticklabels([])

plt.savefig(__file__ + ".png")
plt.show()

此代码生成以下图像,准确显示我们想要的内容 (Deconvolve(Convolve(signal,gauss) , gauss) == signal)

enter image description here

一些重要的发现是:

  • 过滤器应该比信号短
  • 过滤器在任何地方都应该比零大得多(这里 > 0.013 就足够了)
  • 对卷积使用关键字参数 mode = 'same' 确保它与信号存在相同的数组形状。
  • 反卷积有 n = len(signal) - len(gauss) + 1 点。因此,为了让它也驻留在相同的原始数组形状上,我们需要在两侧将其扩展 s = (len(signal)-n)/2

当然,仍然欢迎对这个问题有进一步的发现、评论和建议。

关于python - 了解 scipy 反卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40615034/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com