Imp*_*est 19 python signals numpy scipy deconvolution
我想了解一下scipy.signal.deconvolve
.
从数学的角度来看,卷积只是傅立叶空间中的乘法,所以我希望它有两个函数f
和g
:
Deconvolve(Convolve(f,g) , g) == f
在numpy/scipy中,要么不是这种情况,要么我错过了一个重要的观点.虽然有一些与SO解卷积相关的问题(如此处和此处)但是它们没有解决这一问题,其他问题仍然不清楚(这个)或未答复(这里).SignalProcessing SE还有两个问题(这个和这个),其答案对于理解scipy的解卷积函数是如何工作没有帮助的.
问题是:
f
假设你知道卷积函数g,你如何从一个回旋信号重建原始信号?Deconvolve(Convolve(f,g) , g) == f
转化为numpy/scipy?编辑:请注意,这个问题不是针对防止数字不准确(尽管这也是一个悬而未决的问题),而是要了解如何在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()
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,有一个matlab示例,显示如何使用矩阵信号进行卷积/反卷积
yc=conv(y,c,'full')./sum(c);
ydc=deconv(yc,c).*sum(c);
Run Code Online (Sandbox Code Playgroud)
根据这个问题的精神,如果有人能够将这个例子翻译成python,也会有所帮助.
Imp*_*est 11
经过一些反复试验后,我发现了如何解释结果,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()
Run Code Online (Sandbox Code Playgroud)
此代码生成以下图像,准确显示我们想要的内容(Deconvolve(Convolve(signal,gauss) , gauss) == signal
)
一些重要发现是:
mode = 'same'
卷积的关键字参数可确保它与信号位于相同的数组形状上.n = len(signal) - len(gauss) + 1
有点.因此,为了让它也位于相同的原始阵列形状上,我们需要s = (len(signal)-n)/2
在两侧进行扩展.当然,仍然欢迎对这个问题的进一步调查结果,评论和建议.
正如评论中所写,我对你最初发布的例子无能为力.正如@Stelios指出的那样,由于数值问题,反卷积可能无法解决.
但是,我可以重现您在编辑中发布的示例:
这是从matlab源代码直接翻译的代码:
import numpy as np
import scipy.signal
import matplotlib.pyplot as plt
x = np.arange(0., 20.01, 0.01)
y = np.zeros(len(x))
y[900:1100] = 1.
y += 0.01 * np.random.randn(len(y))
c = np.exp(-(np.arange(len(y))) / 30.)
yc = scipy.signal.convolve(y, c, mode='full') / c.sum()
ydc, remainder = scipy.signal.deconvolve(yc, c)
ydc *= c.sum()
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(4, 4))
ax[0][0].plot(x, y, label="original y", lw=3)
ax[0][1].plot(x, c, label="c", lw=3)
ax[1][0].plot(x[0:2000], yc[0:2000], label="yc", lw=3)
ax[1][1].plot(x, ydc, label="recovered y", lw=3)
plt.show()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8769 次 |
最近记录: |