MATLAB zp2sos 和 python zpk2sos 函数之间的区别

信息处理 matlab 过滤器 scipy 巴特沃思
2022-02-08 00:05:08

我正在尝试将一些代码从 MATLAB 移植到 python。目标是使用 Butterworth 滤波器(四阶,带通)API 并将其转换为二阶部分。对于 Butterworth 滤波器系数,我在 MATLAB 和 python 之间得到相同的输出,但对于zp2sos/却没有zpk2sos

使用 MATLAB R2019b、python 3.7、scipy 1.6.3。

下面是带有输出的 MATLAB 代码:

fs = 8000;
f1 = 200;
f2 = 400;

[z,p,k] = butter(4, [f1/(fs/2) f2/(fs/2)]);
[sos,gain] = zp2sos(z,p,k);

MATLAB 输出

z = 1 1 1 1 -1 -1 -1 -1

p = 0.9173+0.2885i  0.9173-0.2885i 0.8934+0.2214i 0.8934-0.2214i
    0.9237+0.1704i  0.9237-0.1704i 0.9671+0.1555i 0.9671-0.1555i

k = 3.1239e-05

sos = 1.0000    2.0000    1.0000    1.0000   -1.7867    0.8471
      1.0000    2.0000    1.0000    1.0000   -1.8475    0.8823
      1.0000   -2.0000    1.0000    1.0000   -1.8345    0.9246
      1.0000   -2.0000    1.0000    1.0000   -1.9341    0.9594

我的 python 代码如下所示:

from scipy import signal

fs = 8000
f1 = 200
f2 = 400

z, p, k = signal.butter(4, [f1/(fs/2), f2/(fs/2)], 'bandpass', output='zpk')
sos = signal.zpk2sos(z, p, k)

蟒蛇输出:

z= [ 1.+0.j  1.+0.j  1.+0.j  1.+0.j -1.+0.j -1.+0.j -1.+0.j -1.+0.j]

p = [0.967057-0.15545929j   0.92374003-0.17042575j  0.92374003+0.17042575j 0.967057+0.15545929j 
     0.91727345+0.28846481j 0.89335425+0.22144318j  0.89335425-0.22144318j 0.91727345-0.28846481j]

'p' 的输出排序与 MATLAB 不同,但所有值都考虑在内。不确定这是否重要?

k = 3.123897691708261e-05

sos=
[[ 3.12389769e-05  6.24779538e-05  3.12389769e-05  1.00000000e+00 -1.78670849e+00  8.47118894e-01]
 [ 1.00000000e+00  2.00000000e+00  1.00000000e+00  1.00000000e+00 -1.84748005e+00  8.82340575e-01]
 [ 1.00000000e+00 -2.00000000e+00  1.00000000e+00  1.00000000e+00 -1.83454690e+00  9.24602526e-01]
 [ 1.00000000e+00 -2.00000000e+00  1.00000000e+00  1.00000000e+00 -1.93411400e+00  9.59366836e-01]]

我不确定为什么 python 中的前 3 个系数总是与 MATLAB 不同。我尝试了几种不同的输入。不幸的是,我没有使用 DSP 或 scipy 的经验来理解这意味着什么或如何调试它。我无法更改 MATLAB 代码,但需要 python 中的等效代码。任何帮助表示赞赏。

1个回答

我不确定为什么 python 中的前 3 个系数总是与 MATLAB 不同。

这只是一个缩放。如果您在zp2sos没有第二个输出参数的情况下调用 Matlab,您将获得与 Python 相同的三个值。如果您需要 Python 来匹配 Matlab,请使用 sos 的第一个值作为“k”,并将 sos 中的前三个值除以 k(在您的示例中,这会产生1 2 1)。

'p' 的输出排序与 MATLAB 不同,但所有值都考虑在内。不确定这是否重要?

根据您的应用程序,它确实很重要。出于相当复杂的原因,Python 更好,并且在大多数情况下会产生更少的数字噪声,而且通常如此。