Numpy系列(八):实战解析FFT在信号处理中的核心应用
1. 从声音到频谱FFT如何揭开信号的神秘面纱假设你正在用麦克风录制一段吉他弹奏。麦克风捕捉到的声音波形看起来就像一团杂乱无章的上下波动曲线——这就是典型的时域信号。但人类的耳朵真正感知的却是不同音高的组合这时候就需要傅里叶变换来解密了。Numpy的fft.fft()函数就像个神奇的翻译官它能将时域信号转换为频域表示。我曾在处理一段混杂着50Hz电路噪声的音频时通过下面这段代码快速定位到了问题频率import numpy as np import matplotlib.pyplot as plt # 模拟含噪声的音频信号440Hz正弦波50Hz噪声 sample_rate 44100 # 采样率 duration 1.0 # 持续时间 t np.linspace(0, duration, int(sample_rate * duration), endpointFalse) signal 0.5 * np.sin(2 * np.pi * 440 * t) 0.2 * np.sin(2 * np.pi * 50 * t) # 执行FFT fft_result np.fft.fft(signal) frequencies np.fft.fftfreq(len(fft_result), 1/sample_rate) # 绘制频谱图 plt.plot(frequencies[:len(frequencies)//2], np.abs(fft_result[:len(fft_result)//2])) plt.xlabel(频率 (Hz)) plt.ylabel(振幅) plt.show()运行后会看到两个明显的峰一个在440Hz我们的主音另一个在50Hz讨厌的噪声。这种可视化正是信号处理工程师的X光机能一眼看穿信号的内部结构。2. 实战音频降噪从理论到代码的完整流程去年我参与了一个语音助手的项目需要滤除环境中的风扇噪声。下面这个真实案例展示了如何用Numpy实现频域滤波采集样本先录制一段纯噪声只有风扇声分析噪声特征通过FFT找到噪声的基频和谐波设计滤波器在频域将这些频率成分清零def remove_noise(audio, sample_rate, noise_freqs): 频域降噪函数 :param audio: 原始音频信号 :param sample_rate: 采样率 :param noise_freqs: 需要滤除的频率列表(Hz) fft_data np.fft.fft(audio) freqs np.fft.fftfreq(len(fft_data), 1/sample_rate) # 创建滤波器掩码 mask np.ones(len(fft_data), dtypebool) for freq in noise_freqs: # 找到目标频率附近的索引 idx np.where(np.abs(freqs - freq) 5)[0] # ±5Hz范围 mask[idx] False # 应用滤波器 filtered_fft fft_data * mask return np.fft.ifft(filtered_fft).real # 使用示例 noisy_audio np.load(noisy_recording.npy) # 加载含噪声音频 clean_audio remove_noise(noisy_audio, 44100, [50, 100, 150]) # 滤除50Hz及其谐波重要提示实际项目中我们会用更精细的带阻滤波器而非简单置零这里为演示做了简化。保存处理前后的频谱对比图能直观展示滤波效果。3. 机械振动分析FFT在工业检测中的高阶应用在汽轮机振动监测项目中我们通过加速度传感器采集振动信号。健康的设备频谱会有特定的特征峰而当轴承磨损时会在特定频率出现新的谐波。这个案例展示了如何用fft.rfft()专为实数信号优化的FFT进行分析def analyze_vibration(signal, sample_rate, rpm): 旋转机械振动分析 :param signal: 振动传感器信号 :param sample_rate: 采样率(Hz) :param rpm: 设备转速(转/分钟) # 计算转频及其谐波 base_freq rpm / 60 # 转/分钟 → Hz harmonics [base_freq * i for i in [1, 2, 3, 4]] # 分析前4阶谐波 # 执行实数FFT更高效 fft_data np.fft.rfft(signal) freqs np.fft.rfftfreq(len(signal), 1/sample_rate) # 提取关键频率成分 results {} for h in harmonics: idx np.argmin(np.abs(freqs - h)) results[f{h:.1f}Hz] np.abs(fft_data[idx]) / len(signal) * 2 # 计算真实振幅 return results # 示例检测到异常的三倍频振动 vibration_data np.load(bearing_signal.npy) analysis analyze_vibration(vibration_data, 5000, 1800) # 1800rpm设备 print(analysis) # 输出{30.0Hz: 0.12, 60.0Hz: 0.05, 90.0Hz: 0.23, 120.0Hz: 0.02}当三倍频(90Hz)振幅显著增加时往往提示轴承存在不对中故障。这种分析方法已成功应用于风电设备的预测性维护。4. 图像频域处理FFT2在视觉增强中的妙用没想到吧FFT还能处理图像我最近用fft2()给博物馆修复了一批老照片。二维FFT将图像分解为不同方向的条纹模式低频对应大块颜色区域高频则包含边缘细节。这个例子展示如何增强图像锐度def sharpen_image(image, factor2.0): 频域图像锐化 :param image: 输入图像(灰度) :param factor: 锐化强度 # 二维FFT fft_img np.fft.fft2(image) fft_shifted np.fft.fftshift(fft_img) # 低频移到中心 # 创建高通滤波器 rows, cols image.shape crow, ccol rows//2, cols//2 mask np.ones((rows, cols)) radius 30 mask[crow-radius:crowradius, ccol-radius:ccolradius] 0 # 增强高频成分 filtered fft_shifted * (1 mask * factor) # 逆变换 fft_ishift np.fft.ifftshift(filtered) img_back np.fft.ifft2(fft_ishift) return np.abs(img_back) # 使用示例 from skimage import data, io moon data.moon() # 加载示例图像 sharp_moon sharpen_image(moon, 1.5) io.imshow(np.hstack([moon, sharp_moon]))处理前后的对比会显示右侧图像的地表细节更加清晰。同样的原理还可用于去除周期性噪声如扫描文档的网纹只需在频域抹除对应的频率点即可。