Signal enhancing algorithm
我需要一种算法(在帕斯卡语言中更可取,但最终并不重要),它会使左边的"信号"(实际上是一系列数据点)看起来像右边的那个。。
信号来源:信号由机器产生。过于简单化的解释是,这台机器正在测量流经透明管的液体的密度。因此,信号与电信号(音频/无线电频率)完全不同。数据点可以如下所示:[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]; |
号
从图像向后偏移…
氧化镁
这是我最接近的一阶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 |