即使应用了低通滤波器,为什么会有直流偏移?

信息处理 matlab 过滤器设计 低通滤波器
2022-02-05 03:10:04

我需要平滑一些数据段,我正在试验的技术之一是低通滤波器。所以我在 matlab 中设计了一个低通滤波器并将其应用于我的信号。这是其中两个发生的事情。

在此处输入图像描述

面板 A 是用其滤波信号绘制的数据段之一。这看起来不错的样子。这是我所期望的,面板 B 是它的有符号残差,即滤波后的信号减去原始信号。我看到没有直流偏移和线性趋势,所以我很高兴。

面板 C 是另一个用过滤结果绘制的数据段,两者之间有明显的偏移。过滤后的信号“没有穿过”信号,就像我认为的那样。面板 D 是它的残差,我们确认平均值不为零。有时(此处未显示)我在残差中也看到了线性趋势。

所以我的问题是这里发生了什么?应该如何解释这一点?我正在使用低通滤波,因此应包含直流分量,因此残差的平均值应接近于零。这是否说明了高频功率,例如高频功率“过多”?有泄漏的东西还是从零通道向其他相邻频率泄漏的东西?也许我做错了什么?有没有什么办法解决这一问题?我需要确保所有残差都像面板 B 一样,没有线性趋势,平均值大约为零。

更大的重点是查看平滑信号(低通滤波信号)和残差,重点是残差。如果可以解决这个问题,那么很好,否则我会在像这样过滤后考虑,然后从残差中减去最小二乘拟合直线。然后将带符号的残差添加到原始信号中以获得“通过”信号的平滑版本。

是的,我知道大家一般来说低通和减法并不是一个好主意。但说来话长,我别无选择。正如您在代码中看到的,数据段的长度均为 41,节奏为 30 秒,因此频率步长为 0.000813,这当然也是零通道之后的第一个 bin。所以我想要做的是摆脱零通道中的功率,然后查看所有其他(更高)频率箱,换句话说,去趋势(因此我的截止频率为 9mHz)。问题是我需要信号的平滑版本以及去趋势信号。据我所知,要么低通然后减去......要么......高通然后加。

谢谢大家。

这是我的代码


% Filter Design
Fpass = 1e-09;   % Passband Frequency
Fstop = 0.009;   % Stopband Frequency
Apass = 1;       % Passband Ripple (dB)
Astop = 60;      % Stopband Attenuation (dB)
Fs    = 1/30;    % Sampling Frequency
h = fdesign.lowpass('fp,fst,ap,ast', Fpass, Fstop, Apass, Astop, Fs);
Hd = design(h, 'equiripple', ...
        'MinOrder', 'any', ...
        'StopbandShape', 'flat');
xavg = filtfilt(Hd.numerator,1,x);
yavg = filtfilt(Hd.numerator,1,y);
xdelta = xavg - x;
ydelta = yavg - y;

t=1:41;

figure
subplot(2,2,1)
plot(t,x,'o',t,xavg)
legend('x','Filtered x')
title('Panel A - Signal x and Filtered Signal x')
subplot(2,2,3)
plot(t,y,'o',t,yavg)
legend('y','Filtered y')
title('Panel C - Signal y and Filtered Signal y')

subplot(2,2,2)
plot(t,xdelta)
title('Panel B - Signed Residual - Filtered x minus x')
subplot(2,2,4)
plot(t,ydelta)
title('Panel B - Signed Residual - Filtered y minus y')

编辑:我之前没有看到评论。我现在才看到它们,并检查了 geometrikal 指出的内容。这是图片 在此处输入图像描述 不同的数据集但相同的想法。我找不到我使用的原始数字,所以只取了另一组数字。所以在这里我只绘制两个信号,没有残差。调用给出更大偏移的顶部 X 和底部 Y。因此,对于这两个信号,我用各种滤波方法的结果绘制信号。这是显示我在做什么的代码。


% Just normal filtering
xfilt = filtfilt(Hd.numerator,1,x);
yfilt = filtfilt(Hd.numerator,1,y);

% Filtering by subtracting the mean and then adding it
xfiltmean = filtfilt(Hd.numerator,1,x-mean(x))+mean(x);
yfiltmean = filtfilt(Hd.numerator,1,y-mean(y))+mean(y);

% The scaled filter
sc = mean(filtfilt(Hd.numerator,1,ones(1,41)));
xfiltsc = xfilt/sc;
yfiltsc = yfilt/sc;

是的,如图所示,过滤器的总和不等于一。sum(Hd.numerator)=0.9546 那么这两者中的哪一个是问题所在?这是什么意思?是零填充还是缩放?因为单独应用这两个修复似乎都有效,或者至少它们给出了大致相同的答案。两人这样在一起


(filtfilt(Hd.numerator,1,x-mean(x))+mean(x))/sc;

不起作用,因为现在过滤后的信号显然太大了(并用我的数据验证了这一点)。即使我这样做,数据的大小似乎也不重要


x = x+1000;

我得到相同的结果。两个过滤器几乎相同。那么我应该应用哪个修复?去除平均值或缩放?

谢谢大家的帮助。

2个回答

直流偏移只是所有样本的平均值。你应该先计算,减去它,然后运行你的过滤器。

我认为这里发生的事情是您的数据在左右两侧都填充了零,因此您实际上是在用一堆额外的零来平均您的真实数据。(我不知道matlab,所以我可能对此非常错误。)所以你现在得到的DC值是很的(因为你的数据都是大而正的,所以很低。)

这可能是几件事。

输入信号的零填充:

一些滤波操作在将信号与滤波器内核卷积之前用零填充信号的末尾。我不认为filtfilt这样做。

过滤器总和不等于 1:

假设您有一个全为 1 的离散信号。低通滤波也应该返回全 1。因为您正在对离散信号进行操作,所以即使滤波器设计得当,通过离散化产生的误差也会导致滤波器给出不同的值。例如,将离散高斯内核与下面的采样高斯内核进行比较(图片取自维基百科,更多信息位于http://en.wikipedia.org/wiki/Sampled_Gaussian_kernel)。我认为这是最可能的解释。您可以将过滤器输出缩放为粗略的修复。

在此处输入图像描述

高斯核通常用于低通平滑,因为它会生成一个尺度空间。在实践中,这意味着平滑不会在信号中产生任何新的特征,并且更平滑的信号将始终与不太平滑的信号具有相同或更少的细节。如果你还没有,我会试试的。