FFT索引与指定频率通道的匹配筛选问题
FFT索引与指定频率通道的匹配筛选问题
嘿,这个问题核心就是把目标频率对应的通道范围映射到FFT的索引区间,再筛选出符合条件的峰值索引,我给你拆解成一步步的实操方案,附代码示例,很容易上手:
第一步:明确每个目标频率对应的通道频率范围
每个通道是10KHz宽,中心频率就是你给出的freqs数组里的值,所以每个通道的范围是中心频率±5KHz(比如165KHz对应160-170KHz,205KHz对应200-210KHz)。先把每个目标频率的上下限算出来:
# 目标频率数组 freqs = [165, 205] # 计算每个目标频率对应的通道上下限(左闭右开区间,适配后续索引筛选) channel_ranges = [(f - 5, f + 5) for f in freqs]
第二步:把频率范围映射到FFT的索引区间
你的FFT频率数组f是单调递增的(从148.8到250.196),不用遍历整个数组,用numpy的二分查找函数np.searchsorted就能快速定位每个频率范围对应的左右索引边界,效率很高:
import numpy as np # 假设你的FFT频率数组已经生成完毕 f = np.fft.fftshift(np.fft.fftfreq(102, 1/102.4)) + 200 # 存储每个通道对应的索引区间 index_ranges = [] for low, high in channel_ranges: # 找到第一个 >= 通道下限的索引 left_idx = np.searchsorted(f, low, side='left') # 找到第一个 >= 通道上限的索引,形成[left_idx, right_idx)的索引区间 right_idx = np.searchsorted(f, high, side='left') index_ranges.append((left_idx, right_idx))
就像你例子里说的,160-170KHz会对应大概10-20的索引区间,200-210KHz对应50-60的区间,完全匹配预期。
第三步:筛选符合条件的峰值索引
现在有了所有目标通道的索引区间,只需要遍历峰值数组,检查每个索引是否落在任意一个区间里即可:
peaks = [13, 54, 33, 42] filtered_peaks = [] for idx in peaks: # 检查当前索引是否在任意一个目标索引区间内 for left, right in index_ranges: if left <= idx < right: filtered_peaks.append(idx) break # 只要符合一个区间就不用再检查其他的了 print(filtered_peaks) # 输出:[13, 54]
额外优化:处理大数量峰值的高效筛选
如果你的峰值数量很大,还可以用布尔掩码做向量化筛选,速度更快:
# 生成掩码:所有属于目标区间的索引标记为True mask = np.zeros(len(f), dtype=bool) for left, right in index_ranges: mask[left:right] = True # 直接筛选符合条件的峰值 filtered_peaks = [idx for idx in peaks if mask[idx]]
至于你提到的FFT bins不一定刚好落在通道边界的问题,np.searchsorted会自动帮我们找到最接近的边界索引,确保覆盖整个通道的频率范围,完全不用纠结细节~
内容来源于stack exchange
相关产品推荐
相关产品推荐

