SciPy 1.12 中文文档(二十八)
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
注意事项
当输入的数据类型为uint8、float32或float64时,此方法比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()
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
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,则 a 和 b 都将被 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()
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)。
另请参见
lfilter,lfilter_zi
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
滤波器的初始状态。
参见
注意事项
具有阶数 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 输入的响应是一个常数。
给定滤波器系数 a 和 b,用于线性滤波器的转置直接形式 II 实现的状态空间矩阵,即 scipy.signal.lfilter 使用的实现方式如下:
A = scipy.linalg.companion(a).T
B = b[1:] - a[1:]*b[0]
假设 a[0] 为 1.0;如果 a[0] 不是 1,a 和 b 首先将被除以 a[0]。
示例
下面的代码创建一个低通 Butterworth 滤波器。然后将该滤波器应用于一个所有值均为 1.0 的数组;输出也全部为 1.0,符合低通滤波器的预期行为。如果未提供 lfilter 的 zi 参数,输出将显示瞬态信号。
>>> 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])
注意,lfilter 的 zi 参数是通过 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,则 a 和 b 都将被 a[0] 归一化。
xarray_like
需要过滤的数据数组。
axisint, 可选
要应用滤波器的 x 的轴。默认为 -1。
padtypestr 或 None, 可选
必须是 'odd', 'even', 'constant' 或 None。这决定了要应用滤波器的填充信号的扩展类型。如果 padtype 是 None,则不使用填充。默认值为 'odd'。
padlenint 或 None, 可选
在 x 的两端的 axis 扩展元素的数量。此值必须小于 x.shape[axis] - 1。 padlen=0 表示不填充。默认值为 3 * max(len(a), len(b))。
methodstr, 可选
决定信号边缘处理方法的方法,可以是 “pad” 或 “gust”。当 method 是 “pad” 时,信号被填充;填充的类型由 padtype 和 padlen 决定,irlen 被忽略。当 method 是 “gust” 时,使用 Gustafsson 方法,padtype 和 padlen 被忽略。
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()
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 参数。y1 和 y2 之间的差异很小。对于长信号,使用 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
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
scipy.signal.deconvolve(signal, divisor)
使用逆滤波器将signal中的divisor去卷积出来。
返回商和余数,使得signal = convolve(divisor, quotient) + remainder
参数:
signal(N,) 数组型
信号数据,通常是记录的信号。
divisor(N,) 数组型
除数数据,通常是应用于原始信号的冲激响应或滤波器
返回:
quotientndarray
商,通常是恢复的原始信号。
remainderndarray
余数
另请参阅
执行多项式除法(相同操作,但也接受 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 或未给出,则假定初始休息(即全部为零)。请注意,这些初始条件与 lfiltic 或 lfilter_zi 给出的初始条件不同。
返回:
y 数组
数字滤波器的输出。
zf 数组,可选
如果 zi 为 None,则不返回,否则 zf 保存最终的滤波器延迟值。
另请参阅:
zpk2sos, sos2zpk, sosfilt_zi, sosfiltfilt, sosfreqz
注意事项
该滤波器函数实现为直接 II 转置结构的多个二阶滤波器的序列。它旨在减少高阶滤波器的数值精度误差。
0.16.0 版本的新功能。
示例:
使用 lfilter 和 sosfilt 绘制一个 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()
scipy.signal.sosfilt_zi
scipy.signal.sosfilt_zi(sos)
为阶跃响应稳态的sosfilt构造初始条件。
计算sosfilt函数的初始状态zi,该状态对应于阶跃响应的稳态。
该函数的典型用法是设置初始状态,使滤波器的输出与要滤波信号的第一个元素的值相同。
参数:
sos数组样式
第二阶滤波器系数数组,必须具有形状(n_sections, 6)。参见sosfilt以获取 SOS 滤波器格式规范。
返回:
zi数组
适用于与sosfilt一起使用的初始条件,形状为(n_sections, 2)。
另请参阅
注释
自 0.16.0 版新增。
示例
对 0 时刻开始的矩形脉冲进行滤波,使用和不使用scipy.signal.sosfilt的zi参数。
>>> 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()
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] - 1。padlen=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()
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是单位阶跃函数,y是x的希尔伯特变换。[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()
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
降采样信号。
参见
使用 FFT 方法上下采样。
使用多相滤波和 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()
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()
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,则假设为由第一个和最后一个点定义的线性趋势。mean、median、maximum 和 minimum 的工作方式与 np.pad 中相同,并假设沿轴的数组边界外的值分别为数组的平均值、中位数、最大值或最小值。
新版本 1.4.0 中新增。
cval浮点数,可选
如果padtype='constant',则使用的值。默认为零。
新版本 1.4.0 中新增。
返回:
resampled_x数组
重新采样后的数组。
另请参阅
在应用 FIR 或 IIR 滤波器后对信号进行下采样。
使用 FFT 方法上或下采样。
注意
当样本数较大且为质数时,或者当样本数较大且up和down具有较大的最大公约数时,这种多相方法可能比 Fourier 方法更快。所使用的 FIR 滤波器的长度将取决于max(up, down) // gcd(up, down),并且多相滤波过程中的操作次数将取决于滤波器长度和down(详见scipy.signal.upfirdn)。
参数window指定了 FIR 低通滤波器的设计。
如果window是一个类似数组,则假定它是 FIR 滤波器系数。请注意,FIR 滤波器应用在上采样步骤之后,因此它应设计用于在原始信号的采样频率上比原始频率高*up//gcd(up, down)*倍。此函数的输出将与此数组相对于中心,因此如果希望得到零相位滤波器(通常情况),最好传递具有奇数样本数的对称滤波器。
对于任何其他类型的窗口,函数scipy.signal.get_window和scipy.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()
默认行为可以通过使用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()
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 的大小将根据 h、up 和 down 参数变化。
注释
该算法是基于 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 方法,其中替换s为2*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)
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
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)
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)滤波器的滤波器系数,其在最小二乘意义上对bands和desired中描述的期望频率响应的最佳逼近(即,在指定的带内加权均方误差的积分最小化)。
参数:
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]中给出的算法。如该文指出,最小二乘设计具有多个优点:
- 最小二乘意义上的最优。
- 简单的非迭代方法。
- 通过解线性方程组获得一般解决方案。
- 允许使用频率依赖的加权函数。
此函数构造一个 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()