信号增强算法

时间:2016-07-12 13:26:25

标签: algorithm time-series signal-processing data-analysis

我需要一个算法(最好是类似Pascal的语言,但最终并不重要)会使左边的“信号”(实际上是一系列数据点)看起来像右边的那个。 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个信号,但它们是分开的,因此可以单独分析。因此,只考虑如何处理其中一个就足够了。

在达到峰值后,如果信号没有足够快地下降,我们可以认为有多个峰值(最好在系列末尾的“红色”信号中看到)。
enter image description here

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

[Spektre编辑]我从图片中提取红色样本点

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]);

所有值都需要转换:

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

要从图像偏移... f0是原始的红色信号,f1是扭曲的黄色信号。

plot

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

FIR filter

上半部分是使用FIR滤波器权重的图(可通过鼠标编辑,因此FIR是手绘的,用于快速权重查找...)。波纹是信号图:

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

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

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 };

因此,要么有更高程度的FIR,要么需要调整一些权重。无论如何,这应该足以进行反卷积和/或拟合......顺便说一下FIR滤波器如下:

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];

1 个答案:

答案 0 :(得分:2)

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

让我们假设管的行为可以用线性时不变系统(例如线性低通滤波器)来表征。这绝不是保证,而是一种有价值的方法(至少在它失败之前:))。对于非线性和/或时变系统采用相同的方法变得非常复杂,你需要专业的帮助才能做到这一点。

如果我正确理解您的描述,您可以访问管的输入和输出信号。如果我错了并且你不知道输入信号,你可能首先应用一些校准信号,你知道它们的特性,并记录输出信号。了解输入和输出信号是以下方法的先决条件。如果没有这两个信号,则无法估计管道的脉冲响应h。在计算了h的近似值之后,我们可以设计一个名为ge的逆编码器,并最终从输出信号中重建输入。

这是通过h描述的输入信号x [n]的信号流,产生输出信号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×1,X = N×N且h = N×1 您可以通过计算

来计算脉冲响应的最小二乘逼近

他= inv(X&#39; * X)* X&#39; * y

其中X&#39;描述了transpose和inv()X的矩阵逆。他代表了我们通过 1-D deconvolution 获得的管的脉冲响应的列向量。您可以通过计算估计系统的输出来检查识别的工作情况,

ye = X *他

并通过比较你和y。现在,我们尝试从y和他重建x。重建的输入向量xr由

计算

xr = Ge * y

其中Ge = inv(He),He是他的N×N卷积矩阵。 这是一些Octave代码。将两个函数复制到自己的专用文件(reconstruct.m和getConvolutionMatrix.m)中,然后键入&#34; reconstruct.m&#34;进入Octave命令行来检查示例的输出。请注意,示例代码仅适用于奇数长度的向量(N为奇数)。玩你的向量的大小N.这可能有助于逼近精度。

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