【问题标题】:How to find the frequencies of impulses?如何找到脉冲的频率?
【发布时间】:2020-04-20 02:03:53
【问题描述】:

我目前面临关于脉冲频率检测的问题。我有一个程序以这种方式记录设备的网络活动。

"device": {
  "mac": "b8:27:eb:5c:27:13",
  "activity": [
    {
      "ip" : "224.0.0.251",
      "port" : "5353",
      "history" : [
        {
          "timestamp" : "2019-09-23T09:34:30.898836",
          "pktsSent" : 6,
          "pktsReceived" : 0,
          "duration" : "3.972347"
        },
        ...
      ]
    }
  ]    
}

我目前正在尝试实现的是使用其历史来检测活动的频率(如果不是周期性的,则不检测)。想起我的工程学习课程,我想到了 FFT。这是我目前在 Python 中所拥有的:

import numpy as np
import dateutil.parser as dateutil

class FrequencyAnalyzer:
  ...

  def analyze(self, device_mac, activity) -> int:

    if not 'history' in activity:
      raise FrequencyAnalyzerError("No history could be found for the device '%s' and its activity '%s:%s'" %(device_mac, activity['ip'], activity['port']))

    start = int(dateutil.parse(activity['history'][0]['timestamp']).timestamp())
    stop = int(dateutil.parse(activity['history'][-1]['timestamp']).timestamp())
    size = stop - start

    # Array of timestamps 
    timestamps = np.fromiter( [dateutil.parse(history['timestamp']).timestamp() for history in activity['history'] ], int)

    # Array of data, setting 1 if there was an activity at this timestamp, else 0
    data = np.fromiter( [ 1 if x in timestamps and x != start else 0 for x in range(start, stop)], int)

    # Framerate of 1Hz
    frate = 1

    fft = np.fft.fft(data)

    freqs = np.fft.fftfreq(len(fft))
    print(freqs.min(), freqs.max())

    # Find the peak in the coefficients
    idx = np.argmax(np.abs(fft))
    freq = freqs[idx]
    freq_in_hertz = abs(freq * frate)
    print("Freq in Hz = %s" %str(freq_in_hertz))

精度并不那么重要。目前我已将其固定为 1 秒,但也可能是 1 分钟。

在我正在测试的活动中,每 3 分钟和其他时间戳有一个 mDNS 活动。我想返回所有相关的频率,但现在我想得到 1 个正确的频率。

找到的频率始终为零。我记得使用 FFT 分析诸如音频之类的信号,但不适用于脉冲。不应该是同一个方信号(谐波分解)吗?

这是我使用上述程序的信号表示:

我想知道这是否是正确的方法。因为它应该在嵌入式系统中运行,所以我不希望使用像 SciPy 这样有点重的框架。

有什么建议吗?

【问题讨论】:

    标签: python numpy signal-processing fft


    【解决方案1】:

    0-Hz 峰值是平均值。由于您的冲动只是积极的,因此平均值也是积极的。所以你应该忽略那个频率。

    另一个问题是您在执行 FFT 之前没有将任何 window function 应用于您的数据。这将导致看起来非常嘈杂的频谱。窗函数将权衡光谱灵敏度(基本上,峰有多窄)以提高信噪比。一个有效且易于实现的窗口是Hann function

    另外需要注意的是,如果您希望能够检测一个周期为 1 秒的 1 Hz 信号,您需要在数十秒内执行 FFT 以获得围绕该频率的合理频谱分辨率。如果你想检测每 3 分钟发生一次的事情,那么你应该对大约一小时的数据进行 FFT。

    如果您认为 SciPy 对于您的嵌入式设备来说已经太重了,那么您应该考虑将您的程序移植到 C 或 C++,并完全摆脱 Python。另一个问题是您的日志显然是 JSON 格式,编码和解码可能需要相当长的时间,而且它不是最紧凑的格式。考虑使用像MessagePack 这样的二进制格式,或者只是以pcap 格式存储数据包日志并直接在峰值检测器程序中处理它。许多编程语言都有处理这些格式的库。

    【讨论】:

    • 不仅信号的长度很重要,采样频率也很重要。
    • ^ 反过来又决定了你应该使用的 FFT 大小。根据经验,我会采用涵盖大约 10-100 个脉冲的 FFT 大小。
    猜你喜欢
    • 2013-06-06
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多