从信号中去除阶跃函数,如噪声,知道阶跃函数何时发生

信息处理 matlab 离散信号 信号分析
2022-02-22 12:41:02

所以我目前有一个适合非常短时间测量的系统。然而,只要测量时间较长,就需要不断更新参考,每次都会在信号上产生小的阶跃函数噪声。该问题在以下段落中进行了解释,但总而言之,我要去除的噪声由一系列阶跃函数组成,我确切知道何时发生,但不知道幅度。

作为参考,请参见以下图片。

这是理想的情况,或者我们可能希望在最好的情况下实现的情况(蓝色)。 红色是正在检测的物理信号。

每当我们更新它时,我们都会累积任何先前的错误。如果我们打电话sxy^在时刻 y 的测量,相对于在时刻 x 采取的一些参考,在时刻 0 开始测量并在时刻 3 停止,在 2 上进行更新将表示以下内容

s01^=s01+n01
s02^=s02+n02
更新!!
s03^=(s23+s02)+n02+n23

从现在开始,术语$n_{02$将始终以阶跃函数的形式污染信号,并将作为 1/f 噪声传播。(见图3)

因此,实际测量结果如下所示:

理想测量(橙色)和实际测量(蓝色)的比较

显然,我们确切地知道信号何时更新,并且我们可以以某种方式控制它(更新更多或更少,并进行一些权衡)。问题是是否有任何方法通过后处理来估计阶跃函数噪声(如下图所示),只使用真正的获取和更新发生时间的知识。(在给定的代码中,这将是 sig_total 和 refUpdates)。

更新引起的噪声,或者我们试图发现或近似的函数以对我们的信号进行去噪

理想情况下,我们希望能够仅使用这些信息来做到这一点。

此处介绍的基本模拟的 Matlab 代码:

nsamp = 1000; %number of samples
t = 1:nsamp;
[s,sraw,nraw,sig_total,noise_update,refUpdates] = simulate1fnoise(nsamp,4,0.01,0.85);


refUpdates(refUpdates == 0) = NaN;
figure, subplot(1,2,1), plot(t,sraw,t,s(1,:),'r'), 
        title('Signal with only additive noise, no updates'),
        xlabel('time')
        legend({'ideal measurement (short measurements)','physical signal'})
             subplot(1,2,2), loglog(t./nsamp,abs(fft(sraw))),
        xlim([0,0.5]),
        xlabel('frequency')

figure,subplot(1,2,1),plot(t,noise_update),       title('Update noise')
        hold on, stem(refUpdates.*noise_update),
        xlabel('time'), 
        subplot(1,2,2), loglog(t./nsamp,abs(fft(noise_update))),
        xlim([0,0.5]),
        xlabel('frequency')

figure,subplot(1,2,1)
        plot(t,sig_total',t,sraw,t,noise_update,'r'),       title('Measured signal'), xlabel('time')
        legend({'real measurement', 'ideal measurement (short measurements)','noise due to updates'})
        subplot(1,2,2), loglog(t./nsamp,abs(fft(sig_total))),xlim([0,0.5]),xlabel('frequency'), hold on
        loglog(t./nsamp,abs(fft(sraw))),xlim([0,0.5]),xlabel('frequency')



function [signal,acquisition_noUpdates,noise,acquisition,noise_update,refUpdates] = simulate1fnoise(nsamp,amp,freq,probabilityUpdate)
% nsamp -> number of samples
% amp   -> perturbation amplitude
% freq   -> frequency of perturbation
% probabilityUpdate -> starting probability of no update, decreases 5%
%                       every time it does not update
%
% Outputs: signal -> physical signal we want to measure
%          acquisition_noUpdates -> measurement in the case of no updates
%                                  (ideal case)
%          noise -> additive, unavoidable noise
%          acquisition -> data obtained from a typical measurement (with
%                         updates)
%          noise_update -> noise due to the updates (essentially, what we
%                          would want to find out from acqusition and refUpdates)
%          refUpdates   -> Vector signaling when there was an update.

nWindows =1;
t = 1:nsamp;
signal = amp*sin(2*pi*freq*t).*[zeros(1,250) hamming(nsamp-500)' zeros(1,250)] ;
noise = randn(nWindows,nsamp);
acquisition_noUpdates = signal + noise; % isto e o que se mediria sem actualizar a referencia

noise_update = zeros(nWindows,nsamp); % isto e o ruido resultante das actualizaçoes de referencia                           % (isto e o que queremos descobrir)
acquisition = zeros(nWindows,nsamp); % isto e o ruido que medimos com updates de referencia

refUpdates = zeros(nWindows,nsamp);

for wnd = 1:nWindows
    updateError = 0;
    countNoUpdates = -1;
    for idx = 1:nsamp
        countNoUpdates = countNoUpdates+1;
        acquisition(wnd,idx) = acquisition_noUpdates(wnd,idx) + updateError;
        noise_update(wnd,idx) = updateError;
        if rand > probabilityUpdate-(countNoUpdates*0.05)
            refUpdates(wnd,idx) = 1;
            updateError = updateError+noise(wnd,idx);
            countNoUpdates = 0;
        end
    end
end

end

编辑:补充一点,我尝试过的一些事情已经包括微分和中值滤波(然后对信号进行积分),在存在如此低的信噪比的情况下,这并没有多大用处。我也尝试过这种仅限于更新点的方法,但特定情况下的更新密度非常高(这是最坏的情况。在现实生活中,更新可能更不频繁。)

编辑我也一直在尝试使用多个传感器做一些事情。这意味着,具有多个冗余信号,其中更新(阶跃函数)不一定在同一时间。但是,即使在那种情况下,我也无法纠正我的信号。这并不理想,因为它意味着传感器冗余,但如果它是唯一可能的解决方案,那就是一个足够好的折衷方案。目前,我试图用未更新的传感器测量值的平均值来平均有更新的点,但由于某种原因,它最终比简单地平均实际情况下的信号更糟糕,这并不好足够。如果有人感兴趣,我可以发布一些模拟。在这种情况下(假设 5 个传感器,测量相同的信号,具有独立更新),结果将如下所示。显然,我可以平均它们。

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

编辑正如 Peter K. 所建议的那样,我尝试使用递归 DC 阻断器。虽然它确实通过衰减极低频分量在视觉上改善了信号,但它似乎也对信号幅度产生了相当大的影响。我在帖子中没有提到的一点是,我们可能对更低频率的信号或更高频率、更小的幅度感兴趣。因此,通常假设信号的频率信息的 FIR 或 IIR 的常规滤波并不是我想要的。相反,我正在考虑以一种比简单平均更有效的方式探索导致 1/f 噪声的瞬时知识,以及潜在的测量冗余以减少带内噪声。

这些结果是使用下页中提供的滤波器获得的,R 常数为 0.95:DC Blocker 在此处输入图像描述

生成类似数据的代码:代码

编辑 好吧,我有这个想法,但也许我需要一些帮助来进一步开发它。捎带 Peter K. 使用 DC 阻断器的想法,我想也许我可以只将它应用到更新点。这样,希望我能最大限度地减少信号的衰减。

for p = 1:(nsamp-1)
    for wnd = 1:nWindows
        if refUpdates(wnd,p) == 1
                expectedval = corrected_measurement(wnd,p+1) - corrected_measurement(wnd,p) + R*corrected_measurement(wnd,p);              
            error = expectedval-corrected_measurement(wnd,p+1);

            corrected_measurement(wnd,p+1:end) = corrected_measurement(wnd,p+1:end)+error;

同时,我正在尝试一些可能更具适应性的东西,因为这是一个递归过滤器。例如,如果我对每个样本都有一系列连续更新(最坏的情况),那么强烈使用 DC 阻断器可能是个坏主意,因为它会吞噬信号。所以我认为 R 可能取决于自上一步以来的样本数量。(比方说,如果最后一步是在前一个样本上,则 R 从 1 开始,然后每个样本减少 0.01)。

在此处输入图像描述

现在,它似乎确实有所改善,但确实会影响信号。然而,在 10 个冗余传感器的情况下,平均时似乎有相当大的改进。关于这一点,我尝试的另一件事是在 DC 阻断器过滤器中使用该术语乘以 R每个传感器相互校正)。我不确定我的实现有多好,或者这些假设是否根本不聪明,但我得到了以下结果。 在此处输入图像描述

请记住,这些来自更冗长的模拟,用于更现实的方法(1khz 采样率,10 秒采集,1 Hz 扰动)

到目前为止,这种使用其他传感器冗余信息来纠正“更新”阶跃噪声的想法似乎是避免破坏低频响应的最有希望的解决方案。我想知道是否有任何额外的想法。

编辑

好的,我现在正在研究的是使用 10 个传感器冗余来改进测量。在未更新的传感器处进行平均测量,以及更新后传感器的一小部分点的平均值应该能够进行某种校正。在我看来,假设步长的平均水平的估计是完美的(它不会是完美的),那么具有 9 个良好传感器测量的平均值将产生一个幅度误差9=3小倍。平均应该不是一个大问题,因为我们非常过采样(1kHz 采样,对高达 20hz 的扰动感兴趣),尽管在补偿上会有一些依赖于信号的偏差。我想知道这种方法是否还有其他缺点。模拟时,在某些情况下似乎取得了很小的改进,而在其他情况下则没有任何改进,所以我根本不相信这种方法。

2个回答

好的,这仍然不完美,但我建议首先使用陷波滤波器进行过滤:

function [ y ] = notch_filter(alpha,  omega, x )
%notch_filter Notch filter

b = [1 -2*cos(omega) 1];
a = [1 -2*alpha*cos(omega) alpha*alpha];

y = filter(b, a, x);

end

其次是直流阻滞剂:

function [ y ] = dc_blocker( alpha, x )
%dc_blocker BLock DC using coefficient alpha.

y = filter([1 -alpha], [1 -1], x);

end

像这样:

processed = notch_filter(alpha_notch, fc, acquisition_signal(1,:));
processed = dc_blocker(alpha_dc, processed);

其中,对于下面的单个示例,我选择了alpha_notch = alpha_dc = 0.999;

绿色是经过处理的。

在这里,我添加了processed绿色的情节,覆盖pure_signal在顶部情节中。这个例子是更好的例子之一。还有一些不是很好。我会更多地考虑这个问题,看看是否还有其他想法。

我无法访问 matlab,但我建议一个滑动窗口,其长度为您感兴趣的最低频率的几个周期。在这个窗口中,计算平均值并从中心样本中减去该值。当我有时间时,我可以在 python 中尝试一下。