在线检测波幅的方法

机器算法验证 时间序列 信号处理 在线算法
2022-04-20 13:01:14

我想在线测量嘈杂的时间序列中的波幅。我有一个模拟噪声波函数的时间序列,它会发生幅度变化。例如,说这样的事情:

set.seed <- 1001
x <- abs(sin(seq(from = 0, t = 100, by = 0.1)))
x <- x + (runif(1001, 0, 1) / 5)
x <- x * c(rep(1.0, 500), rep(2.0, 501))

结果数据如下所示:

> head(x, n = 30)
 [1] 0.1581530 0.1329728 0.3911897 0.4104984 0.4774424 0.5118123 0.6499325
 [8] 0.6837706 0.8520770 0.8625692 0.8441520 0.9960601 1.1119514 1.1414032
[15] 1.1153601 1.1456799 1.0843497 1.1141201 1.1290904 0.9906415 0.9836052
[22] 0.9369836 0.9493608 0.7484588 0.7588435 0.6467422 0.5787302 0.4665009
[29] 0.4643982 0.3398427
> plot(x)
> lines(x)

波浪图

如您所见,由于序列中的噪声,数据不会在波的波谷和波峰之间单调增加。

我正在寻找一种方法来以计算上不费力的方式在线估计每个波峰值的幅度。 我可能可以找到一种方法来测量噪声项的最大幅度。我不确定波的频率是否恒定,所以我会对假设恒定(已知)波频率或可变波频率的答案感兴趣。真实数据也是正弦的。

我确信这是众所周知的解决方案的常见问题,但我对此很陌生,以至于我什至不知道要搜索哪些术语。另外,如果这个问题更适合stackoverflow,我很抱歉,我可以在那里询问是否首选。

2个回答

这不仅仅是一个完整的解决方案,这意味着一系列关于如何使用 FFT 实现一个非常粗略的“提示”,可能有更好的方法,但是,如果它有效......

首先让我们生成具有不同频率和幅度的波

  freqs <- c(0.2, 0.05, 0.1)
  x <- NULL
  y <- NULL
  for (n in 1:length(freqs))
      {
      tmpx <- seq(n*100, (n+1)*100, 0.1)
      x <- c(x, tmpx)
      y <- c(y, sin(freqs[n] * 2*pi*tmpx))
      }

  y <- y * c(rep(1:5, each=(length(x)/5)))
  y <- y + rnorm(length(x), 0, 0.2)
  plot(x, y, "l")

这给了我们这个

测试波

现在,如果我们使用计算波的 FFTfft并绘制它(我使用了我在此处plotFFT发布的函数),我们得到:

波的全局 FFT

请注意,我对生成数据所用的 3 个频率(0.05、0.1 和 0.2)进行了过度绘制。由于数据是正弦的,FFT 在检索它们方面做得非常好。请注意,当 y 值以 0 为中心时,此方法效果最佳。

现在让我们做一个窗口为 50 的滑动 FFT,我们得到

窗口化 FFT

正如预期的那样,一开始我们只得到 0.2 频率(前 2 个图,所以在 0 和 100 之间),随着我们继续我们得到 0.05 频率(100-200),最后 0.1 频率出现(200-300) .

FFT 函数的功率与波的幅度成正比。事实上,如果我们写下每个窗口中的最大值,我们会得到:

1 Max frequency:  0.2  - power:  254
2 Max frequency:  0.2  - power:  452
3 Max frequency:  0.04  - power:  478
4 Max frequency:  0.04  - power:  606
5 Max frequency:  0.1  - power:  1053
6 Max frequency:  0.1  - power:  1253 

===

这也可以使用 STFT(短时傅立叶变换)来实现,这与我之前向您展示的基本相同,但窗口重叠。这例如通过包的evolfft功能来实现RSEIS

它会给你:

stft <- evolfft(y, dt=0.1, Nfft=2048, Ns=100, Nov=90, fl=0, fh=0.5)
plotevol(stft) 

STFT

然而,这可能更难以分析,尤其是在线分析。

希望这会有所帮助

在回答这个论坛上的另一个问题时,我将 OP 提到了这个站点,其中有一个名为 HT_PERIOD 的函数的开源代码,用于测量时间序列的瞬时周期。还有称为 HT_PHASE、HT_PHASOR 和 HT_SINE 的函数分别测量正弦波/循环分量的相位、相量分量并提取时间序列的正弦波本身(在 -1 和 1 之间缩放)。由于这些函数中的计算是因果关系,因此它们适用于随着新数据进入而更新的在线函数。这些函数的代码可能对您有所帮助。