理解 scipy 反卷积

2023-12-21

我试图理解scipy.signal.deconvolve https://docs.scipy.org/doc/scipy-0.15.0/reference/generated/scipy.signal.deconvolve.html.

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

在 numpy/scipy 中,情况要么不是这样,要么我遗漏了重要的一点。 尽管已经存在一些与 SO 上的反卷积相关的问题(例如here https://stackoverflow.com/questions/17063775/convolution-and-deconvolution-in-python-using-scipy-signal and here https://stackoverflow.com/questions/15483346/scipy-deconvolution-function)他们没有解决这一点,其他人仍然不清楚(this https://stackoverflow.com/questions/21990327/convolution-deconvolution-using-scipy) 或未答复 (here https://stackoverflow.com/questions/36204207/what-are-the-constraints-on-the-divisor-argument-of-scipy-signal-deconvolve-to-e)。还有两个关于信号处理SE的问题(this https://dsp.stackexchange.com/questions/8287/deconvolution-in-python and this https://dsp.stackexchange.com/questions/32181/how-does-scipy-signal-deconvolve-work)的答案对于理解 scipy 的反卷积函数如何工作没有帮助。

问题是:

  • 如何重建原始信号f从复杂的信号中, 假设你知道卷积函数 g.?
  • 或者换句话说:这个伪代码是如何实现的Deconvolve(Convolve(f,g) , g) == f翻译成numpy/scipy?

Edit: 请注意,这个问题的目的并不是为了防止数字不准确(尽管这也是一个开放式问题 https://stackoverflow.com/questions/36204207/what-are-the-constraints-on-the-divisor-argument-of-scipy-signal-deconvolve-to-e)但要了解卷积/反卷积如何在 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()

Edit: 请注意,有一个matlab例子 https://terpconnect.umd.edu/~toh/spectrum/Deconvolution.html,展示如何使用以下方法对矩形信号进行卷积/解卷积

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)

一些重要的发现是:

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解 scipy 反卷积 的相关文章

随机推荐

  • C 新手,错误 C2371:“错误”:重新定义;不同的基本类型

    我必须在几个小时内提交这份作业 我很紧张 它有点像加油站管理程序 处理输入文件和打印结果 它只有 1 个 c 文件 这是我的第一行代码 它定义了结构 include
  • 在 Perl 中快速获取 YYYY-mm-dd HH:MM:SS

    在编写 Perl 脚本时 我经常发现需要获取表示为字符串格式的当前时间YYYY mm dd HH MM SS say 2009 11 29 14 28 29 在这样做的过程中 我发现自己走了这条相当麻烦的路 man perlfunc loc
  • 使用正则表达式将字符串映射到功能

    我有一个字符串和多个正则表达式 例如一个正则表达式检查字符串是否仅为数字 是否以字符 X 开头等等 根据正则表达式的匹配情况 我运行不同的代码 如下所示 if Regex IsMatch myString regex1 number els
  • JBoss 无法从 Eclipse 启动

    我最近从 Netbeans 和 GlassFish 迁移到 Eclipse 和 JBoss 我已经安装了 eclipse jboss 工具 并且服务器运行时设置正确 至少据我所知 我遇到的问题是 每当我尝试从 Eclipse 启动 JBos
  • 如何使 Realm (iOS) 中的写入操作同步?

    作为两步分析过程的一部分 我需要在第二步开始之前将数据写入持久存储 如果我通过 finagrain 通知异步执行此操作 则有点混乱 如果两个人在一个函数中内联完成这件事那就太好了 是否可以使 Realm write 操作同步 第二步需要读回
  • Android 活动 onDestroy() 在屏幕锁定时调用

    销毁时当屏幕休眠或屏幕锁定时 我的活动类中的函数会被调用 我知道这种情况不应该发生 因为控制流程应该是 onPause gt onStop 锁定屏幕上的控制流程如下 onPause gt onStop gt onDestroy 我给了and
  • gitlab CI:加载密钥时出错:格式无效

    两天以来我一直被这个问题困扰 尝试使用我的生产服务器中的 id rsa pub 和 id rsa 仍然出现相同的错误 SSH PRIVATE KEY 是我在 GitLab 上的 CI CD 设置中创建的变量 编辑 未受保护 未屏蔽 This
  • 是否可以将所有权从 void* 转移到 unique_ptr?

    我目前正在使用dlopen一些插件项目的功能 该函数句柄返回一个void 然后我将所有句柄保存到名为的地图中handles void handle dlopen path c str RTLD LAZY handles file handl
  • Android 的 Webkit 组件

    除了标准 WebView 之外 Android 是否还有 Webkit 组件 类 我已经受够了它的超级非禁用选项 例如触摸时图像抖动等 我正在寻找一个足够容易嵌入到 hello world 应用程序中的组件 因为我是 Android 开发的
  • solana web3 verifyTransaction @deprecated 使用 TransactionConfirmationConfig 示例

    使用此代码 VS 显示不推荐使用的警告 方法 Connection confirmTransaction 策略 字符串 承诺 承诺 Promise 1 重载 deprecated 相反 使用 交易确认配置 签名 策略 字符串 承诺 承诺 P
  • 按星期几过滤

    我有一个列需要按星期几进行过滤 该列的格式为 00 00 yyyy 06 09 2017 现在我必须每周二进行过滤 我需要一种只能显示星期二数据的语法 我没有 isdate 列有的星期几列 00 00 0000 我正在使用 Oracle 和
  • VisualVM 无​​法在 Eclipse 上分析 Web 应用程序

    我想分析一下在 Tomcat 和 Eclipse 上运行的 Spring Web 应用程序 我将 VisualVM 添加到 Eclipse 中 并按照以下步骤运行应用程序进行分析 Right click on the application
  • jquery 动画滚动顶部回调

    我有以下 jquery 将页面滚动到顶部 然后执行回调函数 问题是 即使页面已经位于顶部 它仍然会等待 1000 过去后再执行回调 这是我不希望的 html animate scrollTop 0 1000 swing function d
  • ng-init json 对象

    我使用 angularjs ng init 我想将值赋给变量作为 jsonObj 我尝试了这个 但它不起作用 ng init percentObj value 40 color F5A623 value 60 color F5A623 还有
  • 在嵌套 for 循环内创建小部件

    我无法访问内部 for 循环中的外部 for 循环计数器 关于如何做到这一点有什么想法吗 class buildsubcategories extends StatelessWidget List
  • 配置:错误:在 Linux Ubuntu 上为 Android 编译 python 时,C 编译器无法创建可执行文件

    几天前我已经为 android 文件夹创建了 python 但忘记包含一些模块 所以我只是想再做一次 这是 distribute sh 的结果 Python build finished but the necessary bits to
  • 如何使用 script/rails 生成添加新操作和视图?

    有什么方法可以为现有控制器生成新的操作和视图 我尝试对现有控制器执行以下操作 script rails 生成控制器帖子视图 where view是我想添加到控制器的新操作 我知道用手做这件事很简单 但我想知道这是我不知道或我梦想太多的事情
  • SQL:检查一个数字是否在多个范围内

    假设我们有 2 张桌子 Table Values Id Group Value A X 15 B Y 55 Table Ranges Group LowLimit HighLimit X 0 10 X 20 30 Y 30 40 Y 50
  • UITextView 末尾的省略号

    如果我有多行不可滚动的 UITextView 其文本长度超出了可见区域的容纳范围 那么文本就会像这样被切断 Congress shall make no law respecting an establishment of religion
  • 理解 scipy 反卷积

    我试图理解scipy signal deconvolve https docs scipy org doc scipy 0 15 0 reference generated scipy signal deconvolve html 从数学的