SciPy-1-12-中文文档-二十八-

83 阅读35分钟

SciPy 1.12 中文文档(二十八)

原文:docs.scipy.org/doc/scipy-1.12.0/index.html

scipy.signal.medfilt2d

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.medfilt2d.html#scipy.signal.medfilt2d

scipy.signal.medfilt2d(input, kernel_size=3)

对 2 维数组进行中值滤波。

使用由kernel_size(必须为奇数)给定的局部窗口大小对input数组应用中值滤波。数组会自动进行零填充。

参数:

input数组型

一个 2 维输入数组。

kernel_size数组型,可选

标量或长度为 2 的列表,分别指定每个维度中的中值滤波窗口大小。kernel_size的元素应为奇数。如果kernel_size是标量,则在每个维度上使用此标量作为大小。默认为大小为(3, 3)的核。

返回:

out ndarray

与输入大小相同的数组,其中包含中值滤波的结果。

另请参阅

scipy.ndimage.median_filter

注意事项

当输入的数据类型为uint8float32float64时,此方法比medfilt更快;对于其他类型,会回退到medfilt。在某些情况下,scipy.ndimage.median_filter可能比此函数更快。

示例

>>> import numpy as np
>>> from scipy import signal
>>> x = np.arange(25).reshape(5, 5)
>>> x
array([[ 0,  1,  2,  3,  4],
 [ 5,  6,  7,  8,  9],
 [10, 11, 12, 13, 14],
 [15, 16, 17, 18, 19],
 [20, 21, 22, 23, 24]]) 

将 i,j 替换为默认 5*5 窗口中的中值

>>> signal.medfilt2d(x, kernel_size=5)
array([[ 0,  0,  2,  0,  0],
 [ 0,  3,  7,  4,  0],
 [ 2,  8, 12,  9,  4],
 [ 0,  8, 12,  9,  0],
 [ 0,  0, 12,  0,  0]]) 

将 i,j 替换为默认 3*3 窗口中的中值

>>> signal.medfilt2d(x)
array([[ 0,  1,  2,  3,  0],
 [ 1,  6,  7,  8,  4],
 [ 6, 11, 12, 13,  9],
 [11, 16, 17, 18, 14],
 [ 0, 16, 17, 18,  0]]) 

将 i,j 替换为默认 5*3 窗口中的中值

>>> signal.medfilt2d(x, kernel_size=[5,3])
array([[ 0,  1,  2,  3,  0],
 [ 0,  6,  7,  8,  3],
 [ 5, 11, 12, 13,  8],
 [ 5, 11, 12, 13,  8],
 [ 0, 11, 12, 13,  0]]) 

将 i,j 替换为默认 3*5 窗口中的中值

>>> signal.medfilt2d(x, kernel_size=[3,5])
array([[ 0,  0,  2,  1,  0],
 [ 1,  5,  7,  6,  3],
 [ 6, 10, 12, 11,  8],
 [11, 15, 17, 16, 13],
 [ 0, 15, 17, 16,  0]]) 

如示例中所示,#内核数量必须是奇数,不能超过原始数组维度

scipy.signal.wiener

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.wiener.html#scipy.signal.wiener

scipy.signal.wiener(im, mysize=None, noise=None)

对 N 维数组执行 Wiener 滤波。

对 N 维数组im应用 Wiener 滤波器。

参数:

imndarray

一个 N 维数组。

mysizeint 或 array_like,可选

一个标量或者一个长度为 N 的列表,其中的元素指定 Wiener 滤波器在每个维度上的窗口大小。mysize 的元素应为奇数。如果 mysize 是标量,则在每个维度上使用此标量作为大小。

noisefloat,可选

用于计算噪声功率。如果为 None,则噪声被估计为输入的局部方差的平均值。

返回:

outndarray

Wiener 滤波后的结果与im具有相同的形状。

注意

此实现类似于 Matlab/Octave 中的 wiener2。更多细节参见[1]

参考文献

[1]

Lim, Jae S., 《二维信号与图像处理》,Englewood Cliffs, NJ, Prentice Hall, 1990, p. 548.

示例

>>> from scipy.datasets import face
>>> from scipy.signal import wiener
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> rng = np.random.default_rng()
>>> img = rng.random((40, 40))    #Create a random image
>>> filtered_img = wiener(img, (5, 5))  #Filter the image
>>> f, (plot1, plot2) = plt.subplots(1, 2)
>>> plot1.imshow(img)
>>> plot2.imshow(filtered_img)
>>> plt.show() 

../../_images/scipy-signal-wiener-1.png

scipy.signal.symiirorder1

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.symiirorder1.html#scipy.signal.symiirorder1

scipy.signal.symiirorder1(input, c0, z1, precision=-1.0)

使用一系列一阶段级联实现具有镜像对称边界条件的平滑 IIR 滤波器。第二个阶段使用了反转序列。这实现了以下传递函数和镜像对称边界条件的系统:

 c0              
H(z) = ---------------------    
        (1-z1/z) (1 - z1 z) 

结果信号将具有镜像对称的边界条件。

参数:

inputndarray

输入信号。

c0, z1scalar

传递函数中的参数。

precision

根据镜像对称输入计算递归滤波器初始条件的精度。

返回:

outputndarray

过滤后的信号。

scipy.signal.symiirorder2

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.symiirorder2.html#scipy.signal.symiirorder2

scipy.signal.symiirorder2(input, r, omega, precision=-1.0)

使用二阶段级联实现具有镜像对称边界条件的平滑 IIR 滤波器。第二阶段使用了反转的序列。这实现了以下传递函数:

 cs²
H(z) = ---------------------------------------
       (1 - a2/z - a3/z²) (1 - a2 z - a3 z² ) 

其中:

a2 = (2 r cos omega)
a3 = - r²
cs = 1 - 2 r cos omega + r² 

参数:

输入ndarray

输入信号。

r, omegafloat

传递函数中的参数。

精度float

指定根据镜像对称输入计算递归滤波器初始条件的精度。

返回:

输出ndarray

过滤后的信号。

scipy.signal.lfilter

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.lfilter.html#scipy.signal.lfilter

scipy.signal.lfilter(b, a, x, axis=-1, zi=None)

沿着一维数据使用 IIR 或 FIR 滤波器滤波。

使用数字滤波器滤波数据序列 x。这适用于许多基本数据类型(包括对象类型)。滤波器是标准差分方程的直接 II 转置实现(见注意事项)。

函数 sosfilt(使用 output='sos' 进行滤波器设计)应优先于 lfilter 用于大多数滤波任务,因为二阶段节拍具有较少的数值问题。

参数:

b 数组样

1-D 序列中的分子系数向量。

a 数组样

1-D 序列中的分母系数向量。如果 a[0] 不为 1,则 ab 都将被 a[0] 标准化。

x 数组样

N 维输入数组。

axis 整型,可选

应用线性滤波器的输入数据数组的轴。该滤波器应用于此轴上的每个子数组。默认为 -1。

zi 数组样,可选

滤波器延迟的初始条件。它是长度为 max(len(a), len(b)) - 1 的向量(或者对于 N 维输入是向量数组)。如果 zi 为 None 或未给出,则假定初始休息。详见 lfiltic 获取更多信息。

返回:

y 数组

数字滤波器的输出。

zf 数组,可选

如果 zi 为 None,则不返回,否则 zf 包含最终滤波器延迟值。

另见

lfiltic

构建 lfilter 的初始条件。

lfilter_zi

计算 lfilter 的初始状态(阶跃响应的稳态)。

filtfilt

前向后向滤波器,以获得零相位滤波器。

savgol_filter

Savitzky-Golay 滤波器。

sosfilt

使用级联二阶段节拍滤波数据。

sosfiltfilt

使用二阶段节拍进行前向后向滤波器。

注意事项

该滤波函数实现为直接 II 转置结构。这意味着滤波器实现:

a[0]*y[n] = b[0]*x[n] + b[1]*x[n-1] + ... + b[M]*x[n-M]
                      - a[1]*y[n-1] - ... - a[N]*y[n-N] 

其中M是分子的次数,N是分母的次数,n是样本数。它使用以下差分方程实现(假设 M = N):

a[0]*y[n] = b[0] * x[n]               + d[0][n-1]
  d[0][n] = b[1] * x[n] - a[1] * y[n] + d[1][n-1]
  d[1][n] = b[2] * x[n] - a[2] * y[n] + d[2][n-1]
...
d[N-2][n] = b[N-1]*x[n] - a[N-1]*y[n] + d[N-1][n-1]
d[N-1][n] = b[N] * x[n] - a[N] * y[n] 

其中d是状态变量。

描述该滤波器在 z 变换域中的有理传递函数为:

 -1              -M
        b[0] + b[1]z  + ... + b[M] z
Y(z) = -------------------------------- X(z)
                    -1              -N
        a[0] + a[1]z  + ... + a[N] z 

示例

生成一个噪声信号进行滤波:

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt
>>> rng = np.random.default_rng()
>>> t = np.linspace(-1, 1, 201)
>>> x = (np.sin(2*np.pi*0.75*t*(1-t) + 2.1) +
...      0.1*np.sin(2*np.pi*1.25*t + 1) +
...      0.18*np.cos(2*np.pi*3.85*t))
>>> xn = x + rng.standard_normal(len(t)) * 0.08 

创建一个 3 阶低通巴特沃斯滤波器:

>>> b, a = signal.butter(3, 0.05) 

将滤波器应用于 xn。使用 lfilter_zi 选择滤波器的初始条件:

>>> zi = signal.lfilter_zi(b, a)
>>> z, _ = signal.lfilter(b, a, xn, zi=zi*xn[0]) 

再次应用滤波器,使得结果与 filtfilt 中的同阶滤波器相同:

>>> z2, _ = signal.lfilter(b, a, z, zi=zi*z[0]) 

使用 filtfilt 来应用滤波器:

>>> y = signal.filtfilt(b, a, xn) 

绘制原始信号和各种滤波版本:

>>> plt.figure
>>> plt.plot(t, xn, 'b', alpha=0.75)
>>> plt.plot(t, z, 'r--', t, z2, 'r', t, y, 'k')
>>> plt.legend(('noisy signal', 'lfilter, once', 'lfilter, twice',
...             'filtfilt'), loc='best')
>>> plt.grid(True)
>>> plt.show() 

../../_images/scipy-signal-lfilter-1.png

scipy.signal.lfiltic

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.lfiltic.html#scipy.signal.lfiltic

scipy.signal.lfiltic(b, a, y, x=None)

为 lfilter 构造输入和输出向量的初始条件。

给定线性滤波器 (b, a) 和输出 y 以及输入 x 的初始条件,返回 lfilter 使用的状态向量 zi 的初始条件,用于生成输出。

参数:

barray_like

线性滤波器项。

aarray_like

线性滤波器项。

yarray_like

初始条件。

如果 N = len(a) - 1,则 y = {y[-1], y[-2], ..., y[-N]}

如果 y 太短,会用零填充。

xarray_like,可选

初始条件。

如果 M = len(b) - 1,则 x = {x[-1], x[-2], ..., x[-M]}

如果没有给出 x,则假设其初始条件为零。

如果 x 太短,会用零填充。

返回:

zindarray

状态向量 zi = {z_0[-1], z_1[-1], ..., z_K-1[-1]},其中 K = max(M, N)

另请参见

lfilterlfilter_zi

scipy.signal.lfilter_zi

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.lfilter_zi.html#scipy.signal.lfilter_zi

scipy.signal.lfilter_zi(b, a)

构造 lfilter 的阶跃响应稳态的初始条件。

lfilter 函数计算一个初始状态 zi,对应于阶跃响应的稳态。

此函数的典型用途是设置初始状态,使得滤波器的输出从与待滤波信号的第一个元素相同的值开始。

参数:

b, a array_like (1-D)

IIR 滤波器系数。详见 lfilter

返回值:

zi 1-D ndarray

滤波器的初始状态。

参见

lfilterlfilticfiltfilt

注意事项

具有阶数 m 的线性滤波器具有状态空间表示 (A, B, C, D),滤波器的输出 y 可以表示为:

z(n+1) = A*z(n) + B*x(n)
y(n)   = C*z(n) + D*x(n) 

其中 z(n) 是长度为 m 的向量,A 的形状为 (m, m),B 的形状为 (m, 1),C 的形状为 (1, m),D 的形状为 (1, 1)(假设 x(n) 是标量)。lfilter_zi 解决:

zi = A*zi + B 

换句话说,它找到了哪个初始条件,使得对全 1 输入的响应是一个常数。

给定滤波器系数 ab,用于线性滤波器的转置直接形式 II 实现的状态空间矩阵,即 scipy.signal.lfilter 使用的实现方式如下:

A = scipy.linalg.companion(a).T
B = b[1:] - a[1:]*b[0] 

假设 a[0] 为 1.0;如果 a[0] 不是 1,ab 首先将被除以 a[0]。

示例

下面的代码创建一个低通 Butterworth 滤波器。然后将该滤波器应用于一个所有值均为 1.0 的数组;输出也全部为 1.0,符合低通滤波器的预期行为。如果未提供 lfilterzi 参数,输出将显示瞬态信号。

>>> from numpy import array, ones
>>> from scipy.signal import lfilter, lfilter_zi, butter
>>> b, a = butter(5, 0.25)
>>> zi = lfilter_zi(b, a)
>>> y, zo = lfilter(b, a, ones(10), zi=zi)
>>> y
array([1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]) 

另一个示例:

>>> x = array([0.5, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0])
>>> y, zf = lfilter(b, a, x, zi=zi*x[0])
>>> y
array([ 0.5       ,  0.5       ,  0.5       ,  0.49836039,  0.48610528,
 0.44399389,  0.35505241]) 

注意,lfilterzi 参数是通过 lfilter_zi 计算并缩放为 x[0]。然后输出 y 在输入从 0.5 下降到 0.0 之前没有瞬态信号。

scipy.signal.filtfilt

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.filtfilt.html#scipy.signal.filtfilt

scipy.signal.filtfilt(b, a, x, axis=-1, padtype='odd', padlen=None, method='pad', irlen=None)

对信号应用线性数字滤波器,向前和向后。

此函数对信号应用线性数字滤波器两次,一次向前,一次向后。组合的滤波器具有零相位和原始滤波器两倍的滤波器阶数。

此函数提供处理信号边缘的选项。

函数 sosfiltfilt(和使用 output='sos' 进行滤波器设计)应优先于 filtfilt 用于大多数滤波任务,因为二阶段节省去了更多的数值问题。

参数:

b(N,) array_like

过滤器的分子系数向量。

a(N,) array_like

过滤器的分母系数向量。如果 a[0] 不为 1,则 ab 都将被 a[0] 归一化。

xarray_like

需要过滤的数据数组。

axisint, 可选

要应用滤波器的 x 的轴。默认为 -1。

padtypestr 或 None, 可选

必须是 'odd', 'even', 'constant' 或 None。这决定了要应用滤波器的填充信号的扩展类型。如果 padtype 是 None,则不使用填充。默认值为 'odd'。

padlenint 或 None, 可选

x 的两端的 axis 扩展元素的数量。此值必须小于 x.shape[axis] - 1padlen=0 表示不填充。默认值为 3 * max(len(a), len(b))

methodstr, 可选

决定信号边缘处理方法的方法,可以是 “pad” 或 “gust”。当 method 是 “pad” 时,信号被填充;填充的类型由 padtypepadlen 决定,irlen 被忽略。当 method 是 “gust” 时,使用 Gustafsson 方法,padtypepadlen 被忽略。

irlenint 或 None, 可选

method 是 “gust” 时,irlen 指定滤波器的脉冲响应长度。如果 irlen 是 None,则不会忽略脉冲响应的任何部分。对于长信号,指定 irlen 可显著改善滤波器的性能。

返回:

yndarray

输出的滤波后的形状与 x 相同。

另请参阅

sosfiltfilt, lfilter_zi, lfilter, lfiltic, savgol_filter, sosfilt

注意

method 为 “pad” 时,函数在给定的轴上以三种方式之一填充数据:奇数、偶数或常数。奇数和偶数扩展在数据端点处具有相应的对称性。常数扩展使用端点处的值延伸数据。在前向和后向传递中,滤波器的初始条件通过使用 lfilter_zi 找到,并通过扩展数据的端点进行缩放。

method 为 “gust” 时,使用 Gustafsson 方法 [1]。选择前向和后向传递的初始条件,以便前后向滤波器给出与后前向滤波器相同的结果。

在 scipy 版本 0.16.0 中添加了使用 Gustaffson 方法的选项。

参考文献

[1]

F. Gustaffson,“确定前向-后向滤波中的初始状态”,信号处理交易,Vol. 46,pp. 988-992,1996。

示例

示例将使用 scipy.signal 中的多个函数。

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

首先,我们创建一个持续一秒钟的信号,这个信号是两个纯正弦波(频率分别为 5 Hz 和 250 Hz)的和,采样率为 2000 Hz。

>>> t = np.linspace(0, 1.0, 2001)
>>> xlow = np.sin(2 * np.pi * 5 * t)
>>> xhigh = np.sin(2 * np.pi * 250 * t)
>>> x = xlow + xhigh 

现在创建一个低通巴特沃斯滤波器,截止频率为 0.125 倍的奈奎斯特频率,即 125 Hz,并用 filtfilt 应用于 x。结果应该是近似于 xlow,没有相移。

>>> b, a = signal.butter(8, 0.125)
>>> y = signal.filtfilt(b, a, x, padlen=150)
>>> np.abs(y - xlow).max()
9.1086182074789912e-06 

对于这个人工示例,我们得到了一个相当干净的结果,因为奇数扩展是精确的,并且通过适度长的填充,滤波器的瞬态效应在实际数据到达时已经消失。一般来说,边缘处的瞬态效应是不可避免的。

下面的示例演示了选项 method="gust"

首先,创建一个滤波器。

>>> b, a = signal.ellip(4, 0.01, 120, 0.125)  # Filter to be applied. 

sig 是一个要进行滤波的随机输入信号。

>>> rng = np.random.default_rng()
>>> n = 60
>>> sig = rng.standard_normal(n)**3 + 3*rng.standard_normal(n).cumsum() 

分别对 sig 应用 filtfilt,一次使用 Gustafsson 方法,一次使用填充,并绘制结果进行比较。

>>> fgust = signal.filtfilt(b, a, sig, method="gust")
>>> fpad = signal.filtfilt(b, a, sig, padlen=50)
>>> plt.plot(sig, 'k-', label='input')
>>> plt.plot(fgust, 'b-', linewidth=4, label='gust')
>>> plt.plot(fpad, 'c-', linewidth=1.5, label='pad')
>>> plt.legend(loc='best')
>>> plt.show() 

../../_images/scipy-signal-filtfilt-1_00_00.png

irlen 参数可用于改善 Gustafsson 方法的性能。

估计滤波器的脉冲响应长度。

>>> z, p, k = signal.tf2zpk(b, a)
>>> eps = 1e-9
>>> r = np.max(np.abs(p))
>>> approx_impulse_len = int(np.ceil(np.log(eps) / np.log(r)))
>>> approx_impulse_len
137 

对较长的信号应用滤波器,有或没有 irlen 参数。y1y2 之间的差异很小。对于长信号,使用 irlen 可显著提高性能。

>>> x = rng.standard_normal(4000)
>>> y1 = signal.filtfilt(b, a, x, method='gust')
>>> y2 = signal.filtfilt(b, a, x, method='gust', irlen=approx_impulse_len)
>>> print(np.max(np.abs(y1 - y2)))
2.875334415008979e-10 

scipy.signal.savgol_filter

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.savgol_filter.html#scipy.signal.savgol_filter

scipy.signal.savgol_filter(x, window_length, polyorder, deriv=0, delta=1.0, axis=-1, mode='interp', cval=0.0)

对数组应用 Savitzky-Golay 滤波器。

这是一个 1-D 滤波器。如果x的维度大于 1,则axis确定应用滤波器的轴。

参数:

xarray_like

要过滤的数据。如果x不是单精度或双精度浮点数组,则在过滤之前将其转换为numpy.float64类型。

window_lengthint

滤波窗口的长度(即系数的数量)。如果mode为‘interp’,window_length必须小于或等于x的大小。

polyorderint

用于拟合样本的多项式的阶数。polyorder必须小于window_length

derivint,可选

要计算的导数阶数。这必须是非负整数。默认值为 0,表示在不进行微分的情况下过滤数据。

deltafloat,可选

应用过滤器的样本间距。仅在 deriv > 0 时使用。默认值为 1.0。

axisint,可选

要应用过滤器的数组x的轴。默认值为-1。

modestr,可选

必须为‘mirror’、‘constant’、‘nearest’、‘wrap’或‘interp’。这决定了要用于填充信号的填充类型。当mode为‘constant’时,填充值由cval给出。有关‘mirror’、‘constant’、‘wrap’和‘nearest’的更多详细信息,请参阅注释。当选择‘interp’模式(默认情况下)时,不使用扩展。相反,对边缘的最后window_length个值拟合一个polyorder次多项式,并使用此多项式来评估最后window_length // 2个输出值。

cvalscalar,可选

如果mode为‘constant’,则在输入的边缘之外填充的值。默认值为 0.0。

返回:

yndarray,与x相同的形状

过滤后的数据。

另请参阅

savgol_coeffs

注意事项

mode选项的详细信息:

‘mirror’:

以相反顺序重复边缘处的值。不包括最接近边缘的值。

‘nearest’:

扩展包含最接近的输入值。

‘constant’:

扩展包含由cval参数给出的值。

‘wrap’:

扩展包含数组另一端的值。

例如,如果输入为[1, 2, 3, 4, 5, 6, 7, 8],window_length为 7,则以下显示了各种mode选项的扩展数据(假设cval为 0):

mode       |   Ext   |         Input          |   Ext
-----------+---------+------------------------+---------
'mirror'   | 4  3  2 | 1  2  3  4  5  6  7  8 | 7  6  5
'nearest'  | 1  1  1 | 1  2  3  4  5  6  7  8 | 8  8  8
'constant' | 0  0  0 | 1  2  3  4  5  6  7  8 | 0  0  0
'wrap'     | 6  7  8 | 1  2  3  4  5  6  7  8 | 1  2  3 

从版本 0.14.0 开始。

示例

>>> import numpy as np
>>> from scipy.signal import savgol_filter
>>> np.set_printoptions(precision=2)  # For compact display.
>>> x = np.array([2, 2, 5, 2, 1, 0, 1, 4, 9]) 

使用窗口长度为 5 和二次多项式进行滤波。对所有其他参数使用默认值。

>>> savgol_filter(x, 5, 2)
array([1.66, 3.17, 3.54, 2.86, 0.66, 0.17, 1\.  , 4\.  , 9\.  ]) 

注意,x 中的最后五个值是抛物线的样本,因此当 mode=’interp’(默认情况)与 polyorder=2 结合使用时,最后三个值保持不变。与 mode=’nearest’ 相比,例如:

>>> savgol_filter(x, 5, 2, mode='nearest')
array([1.74, 3.03, 3.54, 2.86, 0.66, 0.17, 1\.  , 4.6 , 7.97]) 

scipy.signal.deconvolve

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.deconvolve.html#scipy.signal.deconvolve

scipy.signal.deconvolve(signal, divisor)

使用逆滤波器将signal中的divisor去卷积出来。

返回商和余数,使得signal = convolve(divisor, quotient) + remainder

参数:

signal(N,) 数组型

信号数据,通常是记录的信号。

divisor(N,) 数组型

除数数据,通常是应用于原始信号的冲激响应或滤波器

返回:

quotientndarray

商,通常是恢复的原始信号。

remainderndarray

余数

另请参阅

numpy.polydiv

执行多项式除法(相同操作,但也接受 poly1d 对象)

示例

去卷积已经被过滤的信号:

>>> from scipy import signal
>>> original = [0, 1, 0, 0, 1, 1, 0, 0]
>>> impulse_response = [2, 1]
>>> recorded = signal.convolve(impulse_response, original)
>>> recorded
array([0, 2, 1, 0, 2, 3, 1, 0, 0])
>>> recovered, remainder = signal.deconvolve(recorded, impulse_response)
>>> recovered
array([ 0.,  1.,  0.,  0.,  1.,  1.,  0.,  0.]) 

scipy.signal.sosfilt

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.sosfilt.html#scipy.signal.sosfilt

scipy.signal.sosfilt(sos, x, axis=-1, zi=None)

使用级联的二阶段进行数据滤波。

使用数字 IIR 滤波器 sos 过滤数据序列 x

参数:

sos 数组类型

第二阶滤波器系数的数组,必须具有形状 (n_sections, 6)。每行对应一个二阶段,前三列提供分子系数,最后三列提供分母系数。

x 数组类型

输入数组的 N 维。

axis 整数,可选

应用线性滤波器的输入数据数组的轴。该滤波器应用于沿此轴的每个子数组。默认为 -1。

zi 数组类型,可选

级联滤波器延迟的初始条件。它是形状为 (n_sections, ..., 2, ...) 的(至少是二维的)向量,其中 ..., 2, ... 表示 x 的形状,但将 x.shape[axis] 替换为 2。如果 zi 为 None 或未给出,则假定初始休息(即全部为零)。请注意,这些初始条件与 lfilticlfilter_zi 给出的初始条件不同。

返回:

y 数组

数字滤波器的输出。

zf 数组,可选

如果 zi 为 None,则不返回,否则 zf 保存最终的滤波器延迟值。

另请参阅:

zpk2sos, sos2zpk, sosfilt_zi, sosfiltfilt, sosfreqz

注意事项

该滤波器函数实现为直接 II 转置结构的多个二阶滤波器的序列。它旨在减少高阶滤波器的数值精度误差。

0.16.0 版本的新功能。

示例:

使用 lfiltersosfilt 绘制一个 13 阶滤波器的脉冲响应,显示尝试在单个阶段进行 13 阶滤波器时产生的不稳定性(数值误差使一些极点超出单位圆):

>>> import matplotlib.pyplot as plt
>>> from scipy import signal
>>> b, a = signal.ellip(13, 0.009, 80, 0.05, output='ba')
>>> sos = signal.ellip(13, 0.009, 80, 0.05, output='sos')
>>> x = signal.unit_impulse(700)
>>> y_tf = signal.lfilter(b, a, x)
>>> y_sos = signal.sosfilt(sos, x)
>>> plt.plot(y_tf, 'r', label='TF')
>>> plt.plot(y_sos, 'k', label='SOS')
>>> plt.legend(loc='best')
>>> plt.show() 

../../_images/scipy-signal-sosfilt-1.png

scipy.signal.sosfilt_zi

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.sosfilt_zi.html#scipy.signal.sosfilt_zi

scipy.signal.sosfilt_zi(sos)

为阶跃响应稳态的sosfilt构造初始条件。

计算sosfilt函数的初始状态zi,该状态对应于阶跃响应的稳态。

该函数的典型用法是设置初始状态,使滤波器的输出与要滤波信号的第一个元素的值相同。

参数:

sos数组样式

第二阶滤波器系数数组,必须具有形状(n_sections, 6)。参见sosfilt以获取 SOS 滤波器格式规范。

返回:

zi数组

适用于与sosfilt一起使用的初始条件,形状为(n_sections, 2)

另请参阅

sosfilt, zpk2sos

注释

自 0.16.0 版新增。

示例

对 0 时刻开始的矩形脉冲进行滤波,使用和不使用scipy.signal.sosfiltzi参数。

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt 
>>> sos = signal.butter(9, 0.125, output='sos')
>>> zi = signal.sosfilt_zi(sos)
>>> x = (np.arange(250) < 100).astype(int)
>>> f1 = signal.sosfilt(sos, x)
>>> f2, zo = signal.sosfilt(sos, x, zi=zi) 
>>> plt.plot(x, 'k--', label='x')
>>> plt.plot(f1, 'b', alpha=0.5, linewidth=2, label='filtered')
>>> plt.plot(f2, 'g', alpha=0.25, linewidth=4, label='filtered with zi')
>>> plt.legend(loc='best')
>>> plt.show() 

../../_images/scipy-signal-sosfilt_zi-1.png

scipy.signal.sosfiltfilt

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.sosfiltfilt.html#scipy.signal.sosfiltfilt

scipy.signal.sosfiltfilt(sos, x, axis=-1, padtype='odd', padlen=None)

使用级联二阶节创建前向-后向数字滤波器。

更完整信息,请参见filtfilt方法。

参数:

sosarray_like

第二阶滤波器系数数组,必须具有形状(n_sections, 6)。每行对应一个二阶节,前三列提供分子系数,后三列提供分母系数。

xarray_like

要进行滤波的数据数组。

axisint,可选

应用滤波器的x的轴。默认为-1。

padtypestr 或 None,可选

必须为'odd'、'even'、'constant'或 None。这决定要用于填充信号的扩展类型,以便应用滤波器。如果padtype为 None,则不使用填充。默认为'odd'。

padlenint 或 None,可选

在应用滤波器之前,沿axis两端延伸x的元素数。该值必须小于x.shape[axis] - 1padlen=0表示无填充。默认值为:

3 * (2 * len(sos) + 1 - min((sos[:, 2] == 0).sum(),
                            (sos[:, 5] == 0).sum())) 

最后的额外减法试图补偿在原点处的极点和零点(例如,对于奇阶滤波器),以产生与用scipy.signal函数构建的二阶节滤波器的filtfilt相当的padlen估计。

返回:

yndarray

x具有相同形状的滤波输出。

另请参阅

filtfilt, sosfilt, sosfilt_zi, sosfreqz

注意事项

新版本 0.18.0 中新增。

示例

>>> import numpy as np
>>> from scipy.signal import sosfiltfilt, butter
>>> import matplotlib.pyplot as plt
>>> rng = np.random.default_rng() 

创建一个有趣的信号以进行滤波。

>>> n = 201
>>> t = np.linspace(0, 1, n)
>>> x = 1 + (t < 0.5) - 0.25*t**2 + 0.05*rng.standard_normal(n) 

创建一个低通巴特沃斯滤波器,并用它来滤波x

>>> sos = butter(4, 0.125, output='sos')
>>> y = sosfiltfilt(sos, x) 

为了比较,使用sosfilt应用一个 8 阶滤波器。滤波器使用x的前四个值的均值进行初始化。

>>> from scipy.signal import sosfilt, sosfilt_zi
>>> sos8 = butter(8, 0.125, output='sos')
>>> zi = x[:4].mean() * sosfilt_zi(sos8)
>>> y2, zo = sosfilt(sos8, x, zi=zi) 

绘制结果。注意y的相位与输入匹配,而y2存在显著的相位延迟。

>>> plt.plot(t, x, alpha=0.5, label='x(t)')
>>> plt.plot(t, y, label='y(t)')
>>> plt.plot(t, y2, label='y2(t)')
>>> plt.legend(framealpha=1, shadow=True)
>>> plt.grid(alpha=0.25)
>>> plt.xlabel('t')
>>> plt.show() 

../../_images/scipy-signal-sosfiltfilt-1.png

scipy.signal.hilbert

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.hilbert.html#scipy.signal.hilbert

scipy.signal.hilbert(x, N=None, axis=-1)

使用希尔伯特变换计算解析信号。

默认情况下,转换沿最后一个轴执行。

参数:

xarray_like

信号数据。必须是实数。

Nint,可选

傅里叶分量的数量。默认值为x.shape[axis]

axisint,可选

变换的轴线。默认值为-1。

返回:

xandarray

x的解析信号,沿axis的每个 1-D 数组

注意事项

信号*x(t)*的解析信号x_a(t)是:

[x_a = F^{-1}(F(x) 2U) = x + i y]

其中F是傅里叶变换,U是单位阶跃函数,yx的希尔伯特变换。[1]

换句话说,负频谱的负半部分被置零,将实值信号转换为复杂信号。希尔伯特变换信号可以通过np.imag(hilbert(x))获取,原始信号可以通过np.real(hilbert(x))获取。

参考文献

[1]

维基百科,“解析信号”。en.wikipedia.org/wiki/Analytic_signal

[2]

Leon Cohen,“时频分析”,1995. 第二章。

[3]

Alan V. Oppenheim, Ronald W. Schafer. Discrete-Time Signal Processing, Third Edition, 2009. Chapter 12. ISBN 13: 978-1292-02572-8

示例

在这个例子中,我们使用希尔伯特变换来确定调幅信号的幅度包络和即时频率。

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from scipy.signal import hilbert, chirp 
>>> duration = 1.0
>>> fs = 400.0
>>> samples = int(fs*duration)
>>> t = np.arange(samples) / fs 

我们创建一个从 20 Hz 到 100 Hz 频率增加并应用幅度调制的啁啾声。

>>> signal = chirp(t, 20.0, t[-1], 100.0)
>>> signal *= (1.0 + 0.5 * np.sin(2.0*np.pi*3.0*t) ) 

幅度包络由解析信号的幅度给出。通过将即时相位相对于时间进行微分,即时频率可以获得。即时相位对应于解析信号的相位角。

>>> analytic_signal = hilbert(signal)
>>> amplitude_envelope = np.abs(analytic_signal)
>>> instantaneous_phase = np.unwrap(np.angle(analytic_signal))
>>> instantaneous_frequency = (np.diff(instantaneous_phase) /
...                            (2.0*np.pi) * fs) 
>>> fig, (ax0, ax1) = plt.subplots(nrows=2)
>>> ax0.plot(t, signal, label='signal')
>>> ax0.plot(t, amplitude_envelope, label='envelope')
>>> ax0.set_xlabel("time in seconds")
>>> ax0.legend()
>>> ax1.plot(t[1:], instantaneous_frequency)
>>> ax1.set_xlabel("time in seconds")
>>> ax1.set_ylim(0.0, 120.0)
>>> fig.tight_layout() 

../../_images/scipy-signal-hilbert-1.png

scipy.signal.hilbert2

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.hilbert2.html#scipy.signal.hilbert2

scipy.signal.hilbert2(x, N=None)

计算 x 的‘2-D’ 解析信号

参数:

xarray_like

二维信号数据。

Nint 或两个 int 的元组,可选

傅里叶分量的数量。默认为 x.shape

返回:

xandarray

沿轴(0,1)取 x 的解析信号。

参考资料

[1]

维基百科,“解析信号”,en.wikipedia.org/wiki/Analytic_signal

scipy.signal.decimate

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.decimate.html#scipy.signal.decimate

scipy.signal.decimate(x, q, n=None, ftype='iir', axis=-1, zero_phase=True)

在应用抗混叠滤波器后对信号进行降采样。

默认情况下,使用阶数为 8 的 Chebyshev I 型滤波器。如果ftype为‘fir’,则使用 30 点 Hamming 窗口的 FIR 滤波器。

参数:

xarray_like

要降采样的信号,作为 N 维数组。

qint

下采样因子。当使用 IIR 下采样时,建议对高于 13 的下采样因子多次调用decimate

nint,可选

滤波器的阶数(对于‘fir’来说是长度减 1)。对于‘iir’默认为 8,对于‘fir’是下采样因子的 20 倍。

ftypestr {‘iir’,‘fir’}或dlti实例,可选

如果是‘iir’或‘fir’,则指定低通滤波器的类型。如果是dlti对象的实例,则使用该对象在降采样之前进行滤波。

axisint,可选

要降采样的轴。

zero_phasebool,可选

当使用 IIR 滤波器时,通过使用filtfilt而不是lfilter进行滤波,并将输出向后移动滤波器的群延迟来防止相位移动。通常建议使用默认值True,因为通常不希望出现相位移动。

在 0.18.0 版本中新增。

返回:

yndarray

降采样信号。

参见

resample

使用 FFT 方法上下采样。

resample_poly

使用多相滤波和 FIR 滤波器重采样。

注意

zero_phase关键字在 0.18.0 版本中添加。允许使用dlti实例作为ftype在 0.18.0 版本中添加。

示例

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

定义波参数。

>>> wave_duration = 3
>>> sample_rate = 100
>>> freq = 2
>>> q = 5 

计算样本数。

>>> samples = wave_duration*sample_rate
>>> samples_decimated = int(samples/q) 

创建余弦波。

>>> x = np.linspace(0, wave_duration, samples, endpoint=False)
>>> y = np.cos(x*np.pi*freq*2) 

降采样余弦波。

>>> ydem = signal.decimate(y, q)
>>> xnew = np.linspace(0, wave_duration, samples_decimated, endpoint=False) 

绘制原始波和降采样波。

>>> plt.plot(x, y, '.-', xnew, ydem, 'o-')
>>> plt.xlabel('Time, Seconds')
>>> plt.legend(['data', 'decimated'], loc='best')
>>> plt.show() 

../../_images/scipy-signal-decimate-1.png

scipy.signal.detrend

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.detrend.html#scipy.signal.detrend

scipy.signal.detrend(data, axis=-1, type='linear', bp=0, overwrite_data=False)

从数据中去除沿轴的线性趋势。

参数:

data:数组样式

输入数据。

axis:整数,可选

数据去趋势的轴。默认为最后一个轴(-1)。

type:{‘linear’, ‘constant’},可选

去趋势的类型。如果type == 'linear'(默认),则从data中减去线性最小二乘拟合的结果。如果type == 'constant',则仅减去data的平均值。

bp:整数数组,可选

断点序列。如果指定,则在data中每个部分之间执行单独的线性拟合。断点被指定为data的索引。当type == 'linear'时,此参数才会生效。

overwrite_data:布尔值,可选

如果为 True,则执行就地去趋势并避免复制。默认为 False。

返回:

ret:ndarray

去趋势后的输入数据。

示例

>>> import numpy as np
>>> from scipy import signal
>>> rng = np.random.default_rng()
>>> npoints = 1000
>>> noise = rng.standard_normal(npoints)
>>> x = 3 + 2*np.linspace(0, 1, npoints) + noise
>>> (signal.detrend(x) - noise).max()
0.06  # random 

scipy.signal.resample

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.resample.html#scipy.signal.resample

scipy.signal.resample(x, num, t=None, axis=0, window=None, domain='time')

使用傅立叶方法沿给定轴将 x 重采样为 num 个样本。

重采样信号从与 x 相同的值开始,但采样间隔为 len(x) / num * (spacing of x)。由于使用了傅立叶方法,信号被假定为周期性的。

参数:

x 数组

要重采样的数据。

num 整数

重采样信号中的样本数。

t 数组,可选

如果给定 t,则假定它是与 x 中信号数据相关联的等间隔采样位置。

axis 整数,可选

被重采样的 x 的轴。默认为 0。

window 数组、可调用对象、字符串、浮点数或元组,可选

指定应用于信号的傅立叶域中的窗口。详情见下文。

domain 字符串,可选

指示输入 x 的域的字符串:time 将输入 x 视为时域(默认),freq 将输入 x 视为频域。

返回:

resampled_x 或 (resampled_x, resampled_t)

要么是重采样后的数组,要么(如果给定了 t)是一个包含重采样后的数组和相应重采样位置的元组。

另请参见

decimate

在应用 FIR 或 IIR 滤波器后对信号进行下采样。

resample_poly

使用多相滤波和 FIR 滤波器进行重采样。

注释

参数 window 控制傅立叶域窗口,在零填充前锐化傅立叶频谱,以减轻对未意图作为带限信号解释的采样信号的响应。

如果 window 是一个函数,则调用它并传入一个指示频率区间的输入向量(即 fftfreq(x.shape[axis]))。

如果 window 是与 x.shape[axis] 长度相同的数组,则假定它是要直接在傅立叶域中应用的窗口(带有直流分量和低频率优先)。

对于任何其他类型的 window,将调用函数 scipy.signal.get_window 来生成窗口。

返回向量的第一个样本与输入向量的第一个样本相同。样本之间的间距从 dx 变为 dx * len(x) / num

如果 t 不为 None,则仅用于计算重采样位置 resampled_t

如前所述,resample 使用 FFT 变换,如果输入或输出样本数较大且为质数,则速度可能会非常慢;参见 scipy.fft.fft

示例

注意,重采样数据的末尾上升以满足下一个周期的第一个样本:

>>> import numpy as np
>>> from scipy import signal 
>>> x = np.linspace(0, 10, 20, endpoint=False)
>>> y = np.cos(-x**2/6.0)
>>> f = signal.resample(y, 100)
>>> xnew = np.linspace(0, 10, 100, endpoint=False) 
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'go-', xnew, f, '.-', 10, y[0], 'ro')
>>> plt.legend(['data', 'resampled'], loc='best')
>>> plt.show() 

../../_images/scipy-signal-resample-1.png

scipy.signal.resample_poly

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.resample_poly.html#scipy.signal.resample_poly

scipy.signal.resample_poly(x, up, down, axis=0, window=('kaiser', 5.0), padtype='constant', cval=None)

使用多相滤波器沿给定轴对x进行重新采样。

信号x通过因子up上采样,然后应用零相位低通 FIR 滤波器,并通过因子down进行下采样。结果的采样率为原始采样率的up / down倍。在滤波步骤期间,默认情况下假设信号边界外的值为零。

参数:

x类数组

要重新采样的数据。

up整数

上采样因子。

down整数

下采样因子。

axis整数,可选

被重新采样的x的轴。默认为 0。

window字符串、元组或类数组,可选

用于设计低通滤波器的期望窗口,或用于使用的 FIR 滤波器系数。详细信息见下文。

padtype字符串,可选

constant, line, mean, median, maximum, minimum 或其他由 scipy.signal.upfirdn 支持的信号扩展模式。更改对边界外值的假设。如果是 constant,假设为 cval(默认为零)。如果是 line,则假设为由第一个和最后一个点定义的线性趋势。meanmedianmaximumminimum 的工作方式与 np.pad 中相同,并假设沿轴的数组边界外的值分别为数组的平均值、中位数、最大值或最小值。

新版本 1.4.0 中新增。

cval浮点数,可选

如果padtype='constant',则使用的值。默认为零。

新版本 1.4.0 中新增。

返回:

resampled_x数组

重新采样后的数组。

另请参阅

decimate

在应用 FIR 或 IIR 滤波器后对信号进行下采样。

resample

使用 FFT 方法上或下采样。

注意

当样本数较大且为质数时,或者当样本数较大且updown具有较大的最大公约数时,这种多相方法可能比 Fourier 方法更快。所使用的 FIR 滤波器的长度将取决于max(up, down) // gcd(up, down),并且多相滤波过程中的操作次数将取决于滤波器长度和down(详见scipy.signal.upfirdn)。

参数window指定了 FIR 低通滤波器的设计。

如果window是一个类似数组,则假定它是 FIR 滤波器系数。请注意,FIR 滤波器应用在上采样步骤之后,因此它应设计用于在原始信号的采样频率上比原始频率高*up//gcd(up, down)*倍。此函数的输出将与此数组相对于中心,因此如果希望得到零相位滤波器(通常情况),最好传递具有奇数样本数的对称滤波器。

对于任何其他类型的窗口,函数scipy.signal.get_windowscipy.signal.firwin被调用以生成适当的滤波器系数。

返回向量的第一个样本与输入向量的第一个样本相同。样本之间的间距从dx变为dx * down / float(up)

示例

默认情况下,用于 FFT 方法的重采样数据末端上升以满足下一个周期的第一个样本,并且对于多相方法,接近零:

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt 
>>> x = np.linspace(0, 10, 20, endpoint=False)
>>> y = np.cos(-x**2/6.0)
>>> f_fft = signal.resample(y, 100)
>>> f_poly = signal.resample_poly(y, 100, 20)
>>> xnew = np.linspace(0, 10, 100, endpoint=False) 
>>> plt.plot(xnew, f_fft, 'b.-', xnew, f_poly, 'r.-')
>>> plt.plot(x, y, 'ko-')
>>> plt.plot(10, y[0], 'bo', 10, 0., 'ro')  # boundaries
>>> plt.legend(['resample', 'resamp_poly', 'data'], loc='best')
>>> plt.show() 

../../_images/scipy-signal-resample_poly-1_00_00.png

默认行为可以通过使用padtype选项进行更改:

>>> N = 5
>>> x = np.linspace(0, 1, N, endpoint=False)
>>> y = 2 + x**2 - 1.7*np.sin(x) + .2*np.cos(11*x)
>>> y2 = 1 + x**3 + 0.1*np.sin(x) + .1*np.cos(11*x)
>>> Y = np.stack([y, y2], axis=-1)
>>> up = 4
>>> xr = np.linspace(0, 1, N*up, endpoint=False) 
>>> y2 = signal.resample_poly(Y, up, 1, padtype='constant')
>>> y3 = signal.resample_poly(Y, up, 1, padtype='mean')
>>> y4 = signal.resample_poly(Y, up, 1, padtype='line') 
>>> for i in [0,1]:
...     plt.figure()
...     plt.plot(xr, y4[:,i], 'g.', label='line')
...     plt.plot(xr, y3[:,i], 'y.', label='mean')
...     plt.plot(xr, y2[:,i], 'r.', label='constant')
...     plt.plot(x, Y[:,i], 'k-')
...     plt.legend()
>>> plt.show() 

../../_images/scipy-signal-resample_poly-1_01_00.png../../_images/scipy-signal-resample_poly-1_01_01.png

scipy.signal.upfirdn

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.upfirdn.html#scipy.signal.upfirdn

scipy.signal.upfirdn(h, x, up=1, down=1, axis=-1, mode='constant', cval=0)

上采样、FIR 滤波和下采样。

参数:

harray_like

1-D FIR(有限冲激响应)滤波器系数。

xarray_like

输入信号数组。

upint,可选

采样率上采样。默认为 1。

downint,可选

降采样率。默认为 1。

axisint,可选

应用线性滤波器的输入数据数组的轴。该滤波器应用于沿此轴的每个子数组。默认为 -1。

modestr,可选

要使用的信号扩展模式。集合 {"constant", "symmetric", "reflect", "edge", "wrap"} 对应于 numpy.pad 提供的模式。"smooth" 根据数组末端的最后两个点的斜率进行平滑扩展。"antireflect""antisymmetric""reflect""symmetric" 的反对称版本。模式 “line” 基于沿 axis 定义的线性趋势扩展信号。

新版本 1.4.0 中新增。

cvalfloat,可选

mode == "constant" 时使用的常数值。

新版本 1.4.0 中新增。

返回:

yndarray

输出信号数组。除了 axis 外,维度将与 x 相同,axis 的大小将根据 hupdown 参数变化。

注释

该算法是基于 Vaidyanathan 文本第 129 页所示的块图的实现 [1](图 4.3-8d)。

通过零插入对 P 的因子上采样、长度为 N 的 FIR 滤波和 Q 的因子下采样的直接方法为每个输出样本的复杂度为 O(N*Q)。此处使用的多相实现的复杂度为 O(N/P)。

新版本 0.18 中新增。

参考文献

[1]

P. P. Vaidyanathan,《Multirate Systems and Filter Banks》,Prentice Hall,1993 年。

示例

简单操作:

>>> import numpy as np
>>> from scipy.signal import upfirdn
>>> upfirdn([1, 1, 1], [1, 1, 1])   # FIR filter
array([ 1.,  2.,  3.,  2.,  1.])
>>> upfirdn([1], [1, 2, 3], 3)  # upsampling with zeros insertion
array([ 1.,  0.,  0.,  2.,  0.,  0.,  3.])
>>> upfirdn([1, 1, 1], [1, 2, 3], 3)  # upsampling with sample-and-hold
array([ 1.,  1.,  1.,  2.,  2.,  2.,  3.,  3.,  3.])
>>> upfirdn([.5, 1, .5], [1, 1, 1], 2)  # linear interpolation
array([ 0.5,  1\. ,  1\. ,  1\. ,  1\. ,  1\. ,  0.5])
>>> upfirdn([1], np.arange(10), 1, 3)  # decimation by 3
array([ 0.,  3.,  6.,  9.])
>>> upfirdn([.5, 1, .5], np.arange(10), 2, 3)  # linear interp, rate 2/3
array([ 0\. ,  1\. ,  2.5,  4\. ,  5.5,  7\. ,  8.5]) 

对多个信号应用单个滤波器:

>>> x = np.reshape(np.arange(8), (4, 2))
>>> x
array([[0, 1],
 [2, 3],
 [4, 5],
 [6, 7]]) 

应用于 x 的最后一个维度:

>>> h = [1, 1]
>>> upfirdn(h, x, 2)
array([[ 0.,  0.,  1.,  1.],
 [ 2.,  2.,  3.,  3.],
 [ 4.,  4.,  5.,  5.],
 [ 6.,  6.,  7.,  7.]]) 

应用于 x 的第 0 维度:

>>> upfirdn(h, x, 2, axis=0)
array([[ 0.,  1.],
 [ 0.,  1.],
 [ 2.,  3.],
 [ 2.,  3.],
 [ 4.,  5.],
 [ 4.,  5.],
 [ 6.,  7.],
 [ 6.,  7.]]) 

scipy.signal.bilinear

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.bilinear.html#scipy.signal.bilinear

scipy.signal.bilinear(b, a, fs=1.0)

使用双线性变换从模拟滤波器返回数字 IIR 滤波器。

将一组极点和零点从模拟 s 平面转换到数字 z 平面,使用 Tustin 方法,其中替换s2*fs*(z-1) / (z+1),保持频率响应的形状。

参数:

  • barray_like

模拟滤波器传递函数的分子。

  • aarray_like

模拟滤波器传递函数的分母。

  • fsfloat

采样率,作为普通频率(例如赫兹)。此函数中不进行预弯曲。

返回:

  • bndarray

转换后的数字滤波器传递函数的分子。

  • andarray

转换后的数字滤波器传递函数的分母。

参见

lp2lp, lp2hp, lp2bp, lp2bs

bilinear_zpk

示例

>>> from scipy import signal
>>> import matplotlib.pyplot as plt
>>> import numpy as np 
>>> fs = 100
>>> bf = 2 * np.pi * np.array([7, 13])
>>> filts = signal.lti(*signal.butter(4, bf, btype='bandpass',
...                                   analog=True))
>>> filtz = signal.lti(*signal.bilinear(filts.num, filts.den, fs))
>>> wz, hz = signal.freqz(filtz.num, filtz.den)
>>> ws, hs = signal.freqs(filts.num, filts.den, worN=fs*wz) 
>>> plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hz).clip(1e-15)),
...              label=r'$|H_z(e^{j \omega})|$')
>>> plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hs).clip(1e-15)),
...              label=r'$|H(j \omega)|$')
>>> plt.legend()
>>> plt.xlabel('Frequency [Hz]')
>>> plt.ylabel('Magnitude [dB]')
>>> plt.grid(True) 

../../_images/scipy-signal-bilinear-1.png

scipy.signal.bilinear_zpk

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.bilinear_zpk.html#scipy.signal.bilinear_zpk

scipy.signal.bilinear_zpk(z, p, k, fs)

使用双线性变换从模拟滤波器转换为数字 IIR 滤波器。

将一组模拟 s 平面的极点和零点转换为数字 z 平面,使用 Tustin 方法,用2*fs*(z-1) / (z+1)替换s,保持频率响应的形状。

Parameters:

zarray_like

模拟滤波器传递函数的零点。

parray_like

模拟滤波器传递函数的极点。

kfloat

System gain of the analog filter transfer function.

fsfloat

采样率,作为普通频率(例如赫兹)。此函数中不进行预变形。

返回:

zndarray

Zeros of the transformed digital filter transfer function.

pndarray

Poles of the transformed digital filter transfer function.

kfloat

转换后数字滤波器的系统增益。

See also

lp2lp_zpk, lp2hp_zpk, lp2bp_zpk, lp2bs_zpk

bilinear

Notes

New in version 1.1.0.

Examples

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt 
>>> fs = 100
>>> bf = 2 * np.pi * np.array([7, 13])
>>> filts = signal.lti(*signal.butter(4, bf, btype='bandpass', analog=True,
...                                   output='zpk'))
>>> filtz = signal.lti(*signal.bilinear_zpk(filts.zeros, filts.poles,
...                                         filts.gain, fs))
>>> wz, hz = signal.freqz_zpk(filtz.zeros, filtz.poles, filtz.gain)
>>> ws, hs = signal.freqs_zpk(filts.zeros, filts.poles, filts.gain,
...                           worN=fs*wz)
>>> plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hz).clip(1e-15)),
...              label=r'$|H_z(e^{j \omega})|$')
>>> plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hs).clip(1e-15)),
...              label=r'$|H(j \omega)|$')
>>> plt.legend()
>>> plt.xlabel('Frequency [Hz]')
>>> plt.ylabel('Magnitude [dB]')
>>> plt.grid(True) 

../../_images/scipy-signal-bilinear_zpk-1.png

scipy.signal.findfreqs

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.findfreqs.html#scipy.signal.findfreqs

scipy.signal.findfreqs(num, den, N, kind='ba')

找到用于计算模拟滤波器响应的频率数组。

参数:

num, denarray_like, 1-D

滤波器或 LTI 系统传递函数的分子和分母的多项式系数,系数按从高到低的顺序排列。或者传递函数分子和分母的根(即零点和极点)。

Nint

要计算的数组长度。

kindstr {‘ba’, ‘zp’}, 可选

指定分子和分母是否由它们的多项式系数(‘ba’)或它们的根(‘zp’)指定。

返回:

w(N,) ndarray

一个频率的一维数组,对数间隔。

示例

找到跨越滤波器传递函数“有趣部分”的九个频率集合。

H(s) = s / (s² + 8s + 25)

>>> from scipy import signal
>>> signal.findfreqs([1, 0], [1, 8, 25], N=9)
array([  1.00000000e-02,   3.16227766e-02,   1.00000000e-01,
 3.16227766e-01,   1.00000000e+00,   3.16227766e+00,
 1.00000000e+01,   3.16227766e+01,   1.00000000e+02]) 

scipy.signal.firls

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.signal.firls.html#scipy.signal.firls

scipy.signal.firls(numtaps, bands, desired, *, weight=None, nyq=<object object>, fs=None)

使用最小二乘误差最小化的 FIR 滤波器设计。

计算线性相位有限脉冲响应(FIR)滤波器的滤波器系数,其在最小二乘意义上对bandsdesired中描述的期望频率响应的最佳逼近(即,在指定的带内加权均方误差的积分最小化)。

参数:

numtaps整数

FIR 滤波器的阶数。numtaps必须为奇数。

bands类数组

一个单调非递减的序列,其中包含 Hz 中的带边。所有元素必须非负且小于或等于nyq给定的奈奎斯特频率。带被指定为频率对,因此,如果使用 1D 数组,则其长度必须为偶数,例如np.array([0, 1, 2, 3, 4, 5])。或者,带可以作为大小为 nx2 的 2D 数组指定,其中 n 是带的数量,例如np.array([[0, 1], [2, 3], [4, 5]])

desired类数组

bands大小相同的序列,其中包含每个带的起始点和终点处的期望增益。

weight类数组,可选

在解最小二乘问题时,给每个带区域分配的相对权重。weight的大小必须是bands的一半。

nyq浮点数,可选,已弃用

这是奈奎斯特频率。bands中的每个频率必须介于 0 和nyq(包括)之间。默认为 1。

自 1.0.0 版起已弃用:firls关键字参数nyq已弃用,推荐使用fs,并将在 SciPy 1.14.0 中移除。

fs浮点数,可选

信号的采样频率。bands中的每个频率必须介于 0 和fs/2(包括)之间。默认为 2。

返回:

coeffsndarray

最优(在最小二乘意义上)FIR 滤波器的系数。

另请参见

firwin

firwin2

minimum_phase

remez

注释

此实现遵循[1]中给出的算法。如该文指出,最小二乘设计具有多个优点:

  1. 最小二乘意义上的最优。
  2. 简单的非迭代方法。
  3. 通过解线性方程组获得一般解决方案。
  4. 允许使用频率依赖的加权函数。

此函数构造一个 Type I 线性相位 FIR 滤波器,包含满足以下条件的奇数个coeffs,对于(n < numtaps):

[coeffs(n) = coeffs(numtaps - 1 - n)]

系数的奇数和滤波器的对称性避免了在奈奎斯特频率和 0 频率处可能发生的边界条件(例如,对于 II 型、III 型或 IV 型变体)。

从版本 0.18 开始的新功能。

参考文献

[1]

Ivan Selesnick,最小二乘线性相位 FIR 滤波器设计。OpenStax CNX。2005 年 8 月 9 日。cnx.org/contents/eb1ecb35-03a9-4610-ba87-41cd771c95f2@7

示例

我们希望构建一个带通滤波器。请注意,在我们的阻带和通带之间的频率范围中的行为是未指定的,因此可能会根据我们滤波器的参数而超调:

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt
>>> fig, axs = plt.subplots(2)
>>> fs = 10.0  # Hz
>>> desired = (0, 0, 1, 1, 0, 0)
>>> for bi, bands in enumerate(((0, 1, 2, 3, 4, 5), (0, 1, 2, 4, 4.5, 5))):
...     fir_firls = signal.firls(73, bands, desired, fs=fs)
...     fir_remez = signal.remez(73, bands, desired[::2], fs=fs)
...     fir_firwin2 = signal.firwin2(73, bands, desired, fs=fs)
...     hs = list()
...     ax = axs[bi]
...     for fir in (fir_firls, fir_remez, fir_firwin2):
...         freq, response = signal.freqz(fir)
...         hs.append(ax.semilogy(0.5*fs*freq/np.pi, np.abs(response))[0])
...     for band, gains in zip(zip(bands[::2], bands[1::2]),
...                            zip(desired[::2], desired[1::2])):
...         ax.semilogy(band, np.maximum(gains, 1e-7), 'k--', linewidth=2)
...     if bi == 0:
...         ax.legend(hs, ('firls', 'remez', 'firwin2'),
...                   loc='lower center', frameon=False)
...     else:
...         ax.set_xlabel('Frequency (Hz)')
...     ax.grid(True)
...     ax.set(title='Band-pass %d-%d Hz' % bands[2:4], ylabel='Magnitude')
...
>>> fig.tight_layout()
>>> plt.show() 

../../_images/scipy-signal-firls-1.png