帮助过滤逻辑电平信号而不降低转换

信息处理 过滤器 噪音
2022-02-20 17:07:05

我有一个嘈杂的“低”或嘈杂的“高”信号,例如:

    ######     (high)
####      #### (low)
-------------- (zero)

我想准确地及时找到从低到高的过渡。

然而,噪音正在以某种方式出现:

  • 我不能简单地使用低通滤波器(失去转换精度)
  • 我不能简单地使用导数(HF 噪声被放大)

我想一定有一个众所周知的算法,我只是不知道它的名字......

编辑:

下面是“好”嘈杂步骤以及“不太好,但可解决”步骤的示例。

信号图

编辑: 下面是原始信号(橙色)和中值滤波器(蓝色)。

因为原始信号在高频下是周期性的,所以中值滤波器会产生一个斜坡的伪影,我希望在其中看到一个阶跃函数(或可能两个)。

在此处输入图像描述

1个回答

我已经做了很多这样的工作,希望以下内容会有所帮助:

由于您已经注意到不必实时执行计算,因此这为您提供了很多选择。一个自然的选择,我看到有人已经建议它,将是一个中值过滤器。只要您适当地选择窗口长度,这通常效果很好。在您展示的示例中,您可能需要增加窗口大小(尽管很难说出您有多少样本)。中值滤波器的主要吸引力在于它们不会涂抹边缘,只要您选择适当的窗口大小即可;大多数标准的平滑方法都会。

如果您被过度采样,一个合理的选择是降低您的采样率,看看这会让您的噪音变得明智。

存在其他平滑方法,但它们通常会涂抹您的边缘,并破坏您想要进行的任何边缘/时钟检测。由于您有无限的计算时间,因此中值滤波器可能是您在这个领域的最佳选择。

另一个检查选项是 Savizky-Golay 过滤器。这是另一种数据平滑技术,但它尝试使用多项式对信号进行建模。MATLAB 有一个运行良好的内置程序:

MATLAB 中的 Savitzky-Golay 滤波

我已经在不同类型的噪声信号上使用了这种方法,如果您不受限于实时运行,您当然可以调整参数并希望找到适合您的组合。

一旦你的数据平滑了,我想一个简单的阈值就可以了。您可以根据平滑信号的平均值统计设置此阈值(此方法假定噪声相当平稳)。另一种方法是边缘检测滤波器,例如高斯的一阶导数或其他方法。您可以将此滤波器与平滑信号进行卷积,然后使用一些峰值拾取算法来获取转换的开始/停止;由于它隐含地应用了权重,这将比仅使用某种微分过滤器更强大一些。您可以通过输入:diff(gausswin(sz,alpha)) 在 MATLAB 中获取过滤器,自然将参数替换为最适合您的 size 和 alpha。

另一个可以通过正确实现放弃平滑的选项是某种类型的滞后阈值,其中内置了“保持”功能,因为您对不存在脉冲时的值有一些了解或期望。这将涉及具有双重阈值,并创建一些逻辑来确定哪些值高于和哪些值低于。传统滞后阈值之上的额外位是您需要指定某种保持机制,即一个段仅在它超过 X 多个样本的最高阈值时才有效,并且仅在它打破时才无效Y 个样本的下限阈值。这个选项可能是最有效的,因为(根据经验,我最近为自己的工作编写了这个代码)它需要 100 行左右的 MATLAB 代码来实现。设置这些阈值自然是这里的挑战。我发现统计方法通常足够强大,可以工作。

最后但同样重要的是,如果您能够仅表征信号的噪声分量,并且所述噪声信号是平稳的,您可以尝试进行某种自适应滤波。如果您能够通过辅助传感器或一些巧妙的高通滤波仅捕获信号中的噪声,则可以使用 Wiener-Hopf 方法来清理信号。这是一个例子: wienerhopf_example

通过统计表征噪声方差(在这种情况下不是协方差,因为我们只有一个辅助信号)和互相关,我们能够提出一个自适应权重来消除噪声。有关这方面的一些背景理论,请参阅维纳滤波器

现在信号已全部清除,一个简单的阈值将为您提供边缘。

如果您的噪音不是静止的,您可以通过称为时间分割的过程强制它在小窗口中静止。不过,这有点涉及,希望您不需要这样的东西。

生成该图的 MATLAB 代码如下:

up_s = zeros(1,250)+3;
d_s  = zeros(1,500)+3;
u_s  = ones(1,500)*10;
s = [up_s,repmat([d_s,u_s],[1,50])];
t = linspace(0,1,numel(s));
% set up the noisy signal
nz = sin(2*pi*500*(t));
snz = s+ nz;

% w = R^-1 r, from wiener-hopf method
% zero mean assumed for covariance and correlation; 
% k terms cancel and are excluded
w = inv(nz*nz') * nz*snz';
% apply the weight to the signal
w_sig = snz - w'.*nz;

figure;
ax1 = subplot(2,1,1);
plot(snz);
title('Original Signal');
xlabel('Sample'); ylabel('Magnitude');
xlim([1 numel(snz)]);

ax2 = subplot(2,1,2);
plot(w_sig);
title('Signal Cleaned with Wiener-Hopf Filtering');
xlabel('Sample'); ylabel('Magnitude');
xlim([1 numel(snz)]);

linkaxes([ax1 ax2],'x');

tl; dr:中值滤波很棒,您只需要为您的采样率选择适当的参数。Savitzky-Golay 过滤也将获得良好的结果,前提是您获得正确的参数,这可能具有挑战性。使用任何平滑方法,您都可以预期边缘会出现一些拖尾,但中值滤波器确实可以最大限度地减少这种情况。

如果您只能表征信号的噪声,则可以使用诸如 Wiener-Hopf 方法之类的自适应滤波器技术;此方法假定噪声是静止的,因此需要牢记这一点。使用这种方法,您将基本上获得时钟边沿的零拖尾。