在FFT图中检测峰值

编程入门 行业动态 更新时间:2024-10-16 00:20:23
本文介绍了在FFT图中检测峰值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想知道如何在Python中检测FFT图中的新峰值.假设我有一个简单的图:我想自动测量嘈杂信号中的相似度"或峰值位置,我曾尝试使用余弦相似度,但是我的真实信号太嘈杂,即使我向信号中添加了新峰值,我保持余弦为0.9,因为它只是一个峰值.这是我的真实信号的一个例子,我也有一个问题,就是我的信号可以在测量范围内被遮盖,因此我无法获得一个稳定的频率阵列,它们可以在+/- 100 Hz的窗口内:这是用于第一个Plot的代码:

将numpy导入为np从pylab导入*导入scipy.fftpack#采样点数N = 600#样本间距T = 1.0/800.0x = np.linspace(0.0,N * T,N)y1 = np.sin(50.0 * 2.0 * np.pi * x)+ 0.5 * np.sin(80.0 * 2.0 * np.pi * x)+ 0.7 * np.sin(30.0 * 2.0 * np.pi * x)+ 0.5 * np.sin(10.0 * 2.0 * np.pi * x)y2 = np.sin(50.0 * 2.0 * np.pi * x)+ 0.5 * np.sin(80.0 * 2.0 * np.pi * x)+ 0.2 * np.sin(60.0 * 2.0 * np.pi * x)+ 0.4 * np.sin(40.0 * 2.0 * np.pi * x)yf1 = scipy.fftpack.fft(y1)yf2 = scipy.fftpack.fft(y2)xf = np.linspace(0.0,1.0/(2.0 * T),N/2)无花果,ax = plt.subplots()情节(xf,2.0/N * np.abs(yf1 [:N/2]))情节(xf,2.0/N * np.abs(yf2 [:N/2]))xlabel('Freq(Hz)',fontsize = 16,weight ='bold')ylabel('| Y(freq)|',fontsize = 16,weight ='bold')斧= gca()字体大小= 14对于ax.xaxis.get_major_ticks()中的刻度:tick.label1.set_fontsize(fontsize)tick.label1.set_fontweight('bold')对于ax.yaxis.get_major_ticks()中的刻度:tick.label1.set_fontsize(fontsize)tick.label1.set_fontweight('bold')格(真)表演()def cosine_similarity(v1,v2):计算v1与v2的余弦相似度:(v1点v2)/{|| v1 || ** || v2 ||)"sumxx,sumxy,sumyy = 0、0、0对于范围内的我(len(v1)):x = v1 [i];y = v2 [i]sumxx + = x * xsumyy + = y * ysumxy + = x * y返回sumxy/math.sqrt(sumxx * sumyy)打印'余弦相似度',余弦相似度(2.0/N * np.abs(yf1 [:N/2]),2.0/N * np.abs(yf2 [:N/2]))

尽管我也要设置一个阈值,但是有时真实信号中的峰值可能小于预定义的阈值.有什么想法吗?

解决方案

有很多方法可以找到峰,甚至可以插值子样本的位置.达到峰值后,只需检查是否找到新的峰值即可.

您可以使用

I was wondering how is it possible to detect new peaks within an FFT plot in Python. let's say i have this simple Plot: And i want to automatically measure the 'Similarity' or the Peaks location within a noisy Signal, i have tried to use the cosine Similarity but my real Signal is way too noisy, and with even if i add a new peak to the signal, i keep getting a Cosine of 0.9 since it's only one peak. This is an example of my real signal, and i also have the problem that my signal can be shiffted within the measures, so i can't get a stable frequency array they can be within a window of +/- 100 Hz : This the code that used for the first Plot :

import numpy as np from pylab import * import scipy.fftpack # Number of samplepoints N = 600 # sample spacing T = 1.0 / 800.0 x = np.linspace(0.0, N*T, N) y1 = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)+ 0.7*np.sin(30.0 * 2.0*np.pi*x)+ 0.5*np.sin(10.0 * 2.0*np.pi*x) y2 = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)+ 0.2*np.sin(60.0 * 2.0*np.pi*x)+ 0.4*np.sin(40.0 * 2.0*np.pi*x) yf1 = scipy.fftpack.fft(y1) yf2 = scipy.fftpack.fft(y2) xf = np.linspace(0.0, 1.0/(2.0*T), N/2) fig, ax = plt.subplots() plot(xf, 2.0/N * np.abs(yf1[:N/2])) plot(xf, 2.0/N * np.abs(yf2[:N/2])) xlabel('Freq (Hz)',fontsize=16,weight='bold') ylabel('|Y(freq)|',fontsize=16,weight='bold') ax = gca() fontsize = 14 for tick in ax.xaxis.get_major_ticks(): tick.label1.set_fontsize(fontsize) tick.label1.set_fontweight('bold') for tick in ax.yaxis.get_major_ticks(): tick.label1.set_fontsize(fontsize) tick.label1.set_fontweight('bold') grid(True) show() def cosine_similarity(v1,v2): "compute cosine similarity of v1 to v2: (v1 dot v2)/{||v1||*||v2||)" sumxx, sumxy, sumyy = 0, 0, 0 for i in range(len(v1)): x = v1[i]; y = v2[i] sumxx += x*x sumyy += y*y sumxy += x*y return sumxy/math.sqrt(sumxx*sumyy) print 'Cosine Similarity', cosine_similarity(2.0/N * np.abs(yf1[:N/2]),2.0/N * np.abs(yf2[:N/2]))

I have also though of setting a threshold, but sometime the peaks within the real signal can be smaller than the pre-defined Threshold. Any ideas ?

解决方案

There are many ways to find peaks, and even to interpolate their sub-sample location. Once you have the peaks, just check if you find a new one.

You can use the peakutils package to find the peaks. You can set there the threshold and minimum distance between peaks.

import numpy as np from pylab import * import scipy.fftpack # Number of samplepoints N = 600 # sample spacing T = 1.0 / 800.0 x = np.linspace(0.0, N*T, N) y1 = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)+ 0.7*np.sin(30.0 * 2.0*np.pi*x)+ 0.5*np.sin(10.0 * 2.0*np.pi*x) y2 = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)+ 0.2*np.sin(60.0 * 2.0*np.pi*x)+ 0.4*np.sin(40.0 * 2.0*np.pi*x) yf1 = scipy.fftpack.fft(y1) yf2 = scipy.fftpack.fft(y2) xf = np.linspace(0.0, 1.0/(2.0*T), N/2) v1 = 2.0/N * np.abs(yf1[:N/2]) v2 = 2.0/N * np.abs(yf2[:N/2]) # Find peaks import peakutils peaks_ind1 = peakutils.indexes(v1, thres=0.2, min_dist=5) peaks_ind2 = peakutils.indexes(v2, thres=0.2, min_dist=5) dist_th_for_new_peaks = 3 new_peaks = [] for p in peaks_ind2: found_new_peak = np.all(np.abs(p - peaks_ind1) > dist_th_for_new_peaks) if found_new_peak: new_peaks.append(p) print("New Peak!! - %d" % p) fig, ax = plt.subplots() plot(xf, v1, color='blue') plot(xf, v2, color='green') for p in peaks_ind1: ax.scatter(xf[p], v1[p], s=40, marker='s', color='blue', label='v1') for p in peaks_ind2: ax.scatter(xf[p], v2[p], s=40, marker='s', color='green', label='v2') for p in new_peaks: ax.scatter(xf[p], v2[p], s=40, marker='s', color='red', label='new peaks') xlabel('Freq (Hz)',fontsize=16,weight='bold') ylabel('|Y(freq)|',fontsize=16,weight='bold') ax = gca() fontsize = 14 for tick in ax.xaxis.get_major_ticks(): tick.label1.set_fontsize(fontsize) tick.label1.set_fontweight('bold') for tick in ax.yaxis.get_major_ticks(): tick.label1.set_fontsize(fontsize) tick.label1.set_fontweight('bold') ax.set_xlim([0,400]) ax.set_ylim([0,0.8]) grid(True) show()

The red squares are the new peaks that were found in the green signal:

更多推荐

在FFT图中检测峰值

本文发布于:2023-11-29 19:55:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1647469.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:峰值   图中   FFT

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!