改进波检测算法

时间:2013-10-12 13:35:45

标签: python algorithm

我是python和编程的新手,并且在我的样条曲线插值图上研究波峰检测算法。我使用了此链接上提供的代码:https://gist.github.com/endolith/250860。我必须使这个算法适用于任何类型的波形,即低和高振幅,基线未对齐等。目标是计算图中的波数。但是我的峰值检测计算出“无效”峰值,因此给出了错误的答案。 “无效”峰值意味着如果在波峰处有两个彼此靠近的凹口,则程序检测到2个峰值,即实际上只有1个波浪时检测到2个波峰。我已经尝试更改链接上给出的峰值检测功能中定义的“delta”参数,但这并不能解决我正在进行的泛化目标。请建议对算法或任何其他方法的任何改进我应该是使用。欢迎任何形式的帮助。提前谢谢。

P.S。我无法上传错误的峰值检测波形图的图像。我希望我的解释足够...... 代码如下

wave = f1(xnew)/(max(f1(xnew))) ##interpolated wave
maxtab1, mintab1 = peakdet(wave,.005) 
maxi = max(maxtab1[:,1])
for i in range(len(maxtab1)):
    if maxtab1[i,1] > (.55 * maxi) : ## Thresholding
        maxtab.append((maxtab1[i,0],maxtab1[i,1]))
arr_maxtab = np.array(maxtab)
dist = 1500 ## Threshold defined for minimum distance between two notches to be considered as two separate waves
mtdiff = diff(arr_maxtabrr[:,0])
final_maxtab = []
new_arr = []
for i in range(len(mtdiff)):
if mtdiff[i] < dist :
            new_arr.append((arr_maxtab[i+1,0],arr_maxtab[i+1,1])) 
for i in range(len(arr_maxtab)):
if  not arr_maxtab[i,0] in new_arr[:,0]:
    final_maxtab.append((arr_maxtab[i,0], arr_maxtab[i,1]))
else:
final_maxtab = maxtab

1 个答案:

答案 0 :(得分:3)

区分缺口和真峰的能力意味着峰之间存在基本间距。换句话说,您希望运行峰值检测搜索的最小频率分辨率。如果你放大一个比噪声底板窄的信号,你会发现每隔几个样本看起来“达到峰值”的曲折。

您想要做的是以下内容:

  1. 平滑信号。
  2. 找到'真正的'峰值。
  3. 或者更准确地说,

    1. 通过低通滤波器运行信号。
    2. 在可接受的峰宽范围内找到具有足够信噪比的峰值。
    3. 第1步:低通滤波

      要执行第1步,我建议您使用scipy提供的signal processing tools

      我改编为this cookbook entry,它展示了如何使用FIR滤波器来使用scipy来低通信号。

      from numpy import cos, sin, pi, absolute, arange, arange
      from scipy.signal import kaiserord, lfilter, firwin, freqz, find_peaks_cwt
      from pylab import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show, scatter
      
      #------------------------------------------------
      # Create a signal. Using wave for the signal name.
      #------------------------------------------------
      
      sample_rate = 100.0
      nsamples = 400
      t = arange(nsamples) / sample_rate
      wave = cos(2*pi*0.5*t) + 0.2*sin(2*pi*2.5*t+0.1) + \
              0.2*sin(2*pi*15.3*t) + 0.1*sin(2*pi*16.7*t + 0.1) + \
                  0.1*sin(2*pi*23.45*t+.8)
      
      
      #------------------------------------------------
      # Create a FIR filter and apply it to wave.
      #------------------------------------------------
      
      # The Nyquist rate of the signal.
      nyq_rate = sample_rate / 2.0
      
      # The desired width of the transition from pass to stop,
      # relative to the Nyquist rate.  We'll design the filter
      # with a 5 Hz transition width.
      width = 5.0/nyq_rate
      
      # The desired attenuation in the stop band, in dB.
      ripple_db = 60.0
      
      # Compute the order and Kaiser parameter for the FIR filter.
      N, beta = kaiserord(ripple_db, width)
      
      # The cutoff frequency of the filter.
      cutoff_hz = 10.0
      
      # Use firwin with a Kaiser window to create a lowpass FIR filter.
      taps = firwin(N, cutoff_hz/nyq_rate, window=('kaiser', beta))
      
      # Use lfilter to filter x with the FIR filter.
      filtered_x = lfilter(taps, 1.0, wave)
      

      enter image description here

      第2步:寻找峰值

      对于第2步,我建议您使用scipy提供的wavelet transformation peak finder。您必须提供过滤信号和从最小可能峰值宽度到最大可能峰值宽度的矢量作为输入。该向量将用作小波变换的基础。

      #------------------------------------------------
      # Step 2: Find the peaks
      #------------------------------------------------
      
      figure(4)
      plot(t[N-1:]-delay, filtered_x[N-1:], 'g', linewidth=1)
      
      peakind = find_peaks_cwt(filtered_x, arange(3,20))
      scatter([t[i] - delay for i in peakind], [filtered_x[i] for i in peakind], color="red")
      for i in peakind:
          print t[i] + delay
      
      xlabel('t')
      grid(True)
      
      show()
      

      enter image description here