关于时间序列:信号增强算法

Signal enhancing algorithm

我需要一种算法(在帕斯卡语言中更可取,但最终并不重要),它会使左边的"信号"(实际上是一系列数据点)看起来像右边的那个。signal enhancing

信号来源:信号由机器产生。过于简单化的解释是,这台机器正在测量流经透明管的液体的密度。因此,信号与电信号(音频/无线电频率)完全不同。数据点可以如下所示:[1,2,1,3,4,5,4,3,2,1,13,14,15,18,23,19,17,15,15,15,14,11,9,4,1,1,2,2,1,2]

我需要的是:我需要准确地检测"峰值"。对于这一点,我已经有了一段代码,但是它并没有像下图所示那样处理糟糕的信号。我想我们可以看到,这是一个意外通过低通滤波器的信号,现在我想恢复它。

笔记:共有4个信号,但它们是分开的,因此可以单独分析。所以,只考虑其中一个问题就足够了。

在一个峰值之后,如果信号下降得不够快,我们可以考虑存在多个峰值(您最好在系列末尾的"红色"信号中看到这一点)。氧化镁

优点是整个系列都是可用的(所以信号不是实时的,它已经存储在文件中)!

[由spektre编辑]我从图像中提取红色采样点

1
2
3
float f0[]={ 73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,72,71,69,68,66,64,62,58,54,49,41,33,25,17,13,15,21,30,39,47,54,59,62,64,66,67,68,69,70,71,71,72,72,72,71,71,70,69,68,67,66,65,63,62,60,56,51,45,37,29,22,18,18,22,28,33,35,36,35,32,26,20,15,12,15,20,26,31,35,37,36,34,30,25,22,22,27,33,41,48,55,60,63,66,67,68,69,70,71,72,72,73,73,73,73,73,73,72,71,70,69,67,65,63,60,55,49,40,30,21,13, 7,10,17,27,36,45,52,56,59,60,61,62,62,62,62,61,61,59,57,53,47,40,32,24,18,15,18,23,28,32,33,31,28,23,16,10, 6, 8,13,20,27,31,32,31,28,22,15,10, 6,10,16,23,30,34,36,36,34,29,24,20,19,24,30,37,44,51,56,59,61,62,63,64,64,64,65,64,64,62,60,57,53,48,43,38,36,39,43,49,54,59,63,66,68,69,70,71,72,72,73,73,73,73,73,73,73,73,73,73,73,73,73,73 };
float f1[]={ 55,58,60,62,64,66,67,68,68,69,69,70,71,72,72,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,73,73,73,72,72,72,72,71,71,71,71,71,71,70,70,69,68,67,66,64,63,61,60,59,57,55,52,49,46,43,40,37,35,34,33,32,32,33,34,36,37,39,41,43,45,47,50,52,55,57,59,60,61,61,62,62,62,62,61,61,60,58,57,55,53,51,49,48,46,44,42,40,38,35,32,30,29,28,27,27,26,26,26,25,25,24,23,23,23,24,24,25,25,26,26,26,27,28,29,31,33,35,38,40,41,43,44,46,48,50,53,55,57,59,60,61,62,63,64,64,65,65,64,63,61,59,57,54,52,50,47,45,42,39,37,34,32,31,30,30,30,31,32,34,36,37,39,40,41,42,43,44,44,44,44,43,42,41,40,38,36,34,32,30,28,26,25,24,23,22,21,20,18,17,17,17,17,18,18,18,18,18,18,18,18,18,18,19,19,19,19,20,20,21,23,24,25,26,26,26,27,28,29,31,34,36,37,38,40,41,43,45,47,48,49,50,51,51,51,50,49,49,48,48,47,47,47,47,47,47,48,60 };
const int n=sizeof(f0)/sizeof(f0[0]);

所有的值都需要转换:

1
2
f0[i] = 73.0-f0[i];
f1[i] = 73.0-f1[i];

从图像向后偏移…f0为原始红色信号,f1为畸变黄色信号。

氧化镁

这是我最接近的一阶FIR滤波器:

氧化镁

上半部分是使用的FIR过滤器权重图(可通过鼠标编辑,以便手动绘制FIR以快速找到权重…)。以下是信号图:

  • 红色原始(理想)信号f0
  • 深绿色测量信号f1
  • 浅绿色FIR滤波理想信号f2

    FIR滤波器只是卷积,其中零偏移量元素是最后一个,这里的权重值是:

  • 小精灵

    1
    float fir[35] = { 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.0007506932, 0.003784107, 0.007575874, 0.01060929, 0.01591776, 0.02198459, 0.03032647, 0.04170178, 0.05686884, 0.06445237, 0.06900249, 0.07203591, 0.07203591, 0.0705192, 0.06900249, 0.06672744, 0.06217732, 0.05611049, 0.04928531, 0.04170178, 0.03335989, 0.02653471, 0.02046788, 0.01515941, 0.009850933, 0.005300813, 0.0007506932 };

    所以要么还有更高程度的杉木,要么重量需要调整更多。无论如何,这应该足够反褶积和/或拟合…btw FIR滤波器的工作如下:

    1
    2
    3
    4
    5
    6
    7
    const int fir_n=35;     // size (exposure time) [samples]
    const int fir_x=fir_n-1;    // zero offset element [samples]
    int x,y,i,j,ii;
    float a,f2[n];
    for (i=0;i<n;i++)
     for (f2[i]=0.0,ii=i-fir_x,j=0;j<fir_n;j++,ii++)
      if ((ii>=0)&&(ii<n)) f2[i]+=fir[j]*f0[ii];


    在我看来,你应该从一个非常简单的系统识别和连续信号重建开始。另外,我建议首先在Matlab(商业许可证)或Octave(免费→https://www.gnu.org/software/octave/download.html)等数学原型工具中实现您的算法。这些工具提供了一个简单的信号处理,没有任何编程语言,如Pascal或Java可以提供,无论你使用什么图书馆。在用matlab或octave成功地设计了算法之后,再考虑如何用pascal实现它。

    假设管的行为可由线性时不变系统(例如线性低通滤波器)表征。这不是保证,而是一种有价值的方法(至少在失败之前是这样)。对于非线性和/或时变系统,遵循同样的方法会变得相当复杂,我想您需要专业人员的帮助才能做到这一点。

    如果我正确理解了你的描述,你就可以同时获得电子管的输入和输出信号。如果我错了,你不知道输入信号,你可以先应用一些校准信号,你知道它的特性,然后记录输出信号。了解输入和输出信号是以下方法的先决条件。如果没有这两个信号,你就不能估计出管子的脉冲响应h。在计算h的近似值后,我们可以设计一个称为ge的逆滤波器,并最终从输出信号中重建输入。

    这里是输入信号x[n]通过试管的信号流,由h描述,产生输出信号y[n]。取y[n]并应用GE描述的反滤波操作,得到xr[n]

    X[N]→H→Y[N]→GE→xr[N]

    取长度为n的输入向量x和相同长度的对应向量y。现在,您将输出y表示为输入卷积矩阵x的卷积(参见下面的代码实现),其中包含系统的未知脉冲响应,即。

    Y=X*H

    向量和矩阵大小y=n x 1,x=n x n,h=n x 1你可以通过计算脉冲响应的最小二乘近似值

    他=投资(x'*x)*x'*y

    其中x'表示转置,inv()表示x的矩阵倒数。它表示通过一维反卷积得到的确定的管脉冲响应的列向量。您可以通过计算估计系统的输出来检查标识的工作情况,

    叶=X*He

    通过比较Ye和Y,我们试图从Y和He中重建X。重建输入矢量xr的计算公式如下:

    xr=ge*y

    其中,ge=inv(he),he是he的n x n卷积矩阵。这是一些八度音阶的代码。将这两个函数都复制到它们自己的专用文件(reform.m和getconvolutionmatrix.m)中,并在八度命令行中键入"reform.m",以检查示例的输出。请注意,示例代码仅适用于奇数长度的向量(n是奇数)。玩弄你的向量的大小。这可能有助于近似精度。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    function [Ge] = reconstruct ()
        x = [1 2 3]';            # input signal
        # h = [1 3 2]';          # unknown impulse response
        y = [5 11 13]';          # output signal
        y = y + 0.001*randn(length(y),1)  # add noise to output signal

        Xm = getConvolutionMatrix(x)
        Xps = inv(Xm'*Xm)*Xm';
        he = Xps * y
        He = getConvolutionMatrix(he);
        Ge = inv(He);
        # reconstructed impulse signal
        xr = Ge*y
    endfunction

    function [mH] = getConvolutionMatrix(h)
        h = h(:)';
        hlen = length(h);
        Nc = (hlen-1)/2;

        mH= zeros(hlen, hlen);
        hp = [zeros(1,Nc) h zeros(1,Nc)];

        for c=1:hlen
          for r=1:hlen
            mH(r,c) = hp(r+hlen-c);
          end
        end
    endfunction