4. 频域分析:傅里叶变换基础、频谱图绘制、功率谱密度估计

聊到海豚声波信号处理,频域分析是绕不开的核心。说白了,时域信号就像一段录音,你能听到声音大小变化,但很难直接看出里面藏着哪些频率成分。而频域分析,就是帮我们把信号「拆开」,看看海豚到底发出了哪些频率的声音。

我个人习惯把频域分析比作「声音的指纹提取」。海豚的叫声、回声定位信号,在时域里看着乱糟糟的,一转到频域,特征就清清楚楚了。好,咱们直接进入正题。

4.1 傅里叶变换基础

傅里叶变换,简单说就是把时域信号变成频域信号。数学公式长这样:

X(f) = ∫ x(t) · e^(-j2πft) dt

别被公式吓到。你只要记住:每个信号都可以分解成不同频率的正弦波之和。海豚发出的咔嗒声,其实是由很多频率成分叠加而成的。

在实际项目中,我们处理的是离散采样信号,所以要用离散傅里叶变换(DFT)。Python里最常用的是FFT(快速傅里叶变换),它是DFT的高效算法实现。

核心要点:

  • 采样率决定了你能分析的最高频率(奈奎斯特频率 = 采样率/2)
  • FFT点数决定了频率分辨率(Δf = 采样率 / FFT点数)
  • 海豚声波频率范围通常在1kHz到150kHz之间,采样率至少300kHz起步

我记得刚入行时,有一次采集海豚回声定位信号,采样率设了200kHz。结果分析时发现高频部分有混叠,后来才意识到海豚的咔嗒声能到120kHz以上。嗯,从那以后我采样率都至少设300kHz。

4.2 频谱图绘制

频谱图就是把FFT结果画出来。横轴是频率,纵轴是幅度(或功率)。看频谱图,你能直观知道信号里哪些频率能量强。

咱们直接上代码。假设你有一段海豚声波信号 signal,采样率 fs

import numpy as np
import matplotlib.pyplot as plt

def plot_spectrum(signal, fs):
    """
    绘制单边幅度频谱
    signal: 输入信号数组
    fs: 采样率 (Hz)
    """
    N = len(signal)
    # 做FFT
    fft_vals = np.fft.fft(signal)
    # 取单边频谱(正频率部分)
    fft_vals = fft_vals[:N//2] * 2 / N
    # 频率轴
    freqs = np.fft.fftfreq(N, 1/fs)[:N//2]
    
    plt.figure(figsize=(10, 5))
    plt.plot(freqs/1000, np.abs(fft_vals))
    plt.xlabel('频率 (kHz)')
    plt.ylabel('幅度')
    plt.title('海豚声波频谱图')
    plt.grid(True, alpha=0.3)
    plt.show()

# 使用示例
# plot_spectrum(dolphin_signal, fs=320000)

实用技巧:

绘制频谱时,我建议用np.abs()取幅度,然后转成dB单位:20 * np.log10(amplitude)。这样能更好显示微弱信号。海豚的某些谐波成分可能比主频低40dB,线性坐标下根本看不见。

你想想看,海豚的叫声通常包含基频和多次谐波。基频可能在5-20kHz,谐波能延伸到100kHz以上。频谱图上一眼就能看出这些结构。

4.3 功率谱密度估计

功率谱密度(PSD)和频谱图不太一样。频谱图显示的是每个频率成分的幅度,而PSD显示的是单位频率上的功率分布。说白了,PSD告诉你信号的能量在频率轴上是怎么分配的。

实际项目中,我更常用PSD来分析海豚声波。为什么?因为海豚信号往往是非平稳的,PSD能给出更稳定的统计特性。

Python里做PSD估计,我推荐两种方法:

方法 特点 适用场景
Welch法 分段平均,方差小,谱线平滑 连续叫声、背景噪声分析
周期图法 直接FFT,分辨率高但方差大 短时咔嗒声、瞬态信号

Welch法是我用得最多的。它把信号分成多段,每段加窗,然后做FFT再平均。这样能有效降低噪声引起的谱估计波动。

from scipy import signal

def estimate_psd_welch(signal, fs):
    """
    使用Welch法估计功率谱密度
    """
    # 分段参数:每段1024点,重叠50%,用汉宁窗
    f, Pxx = signal.welch(
        signal, 
        fs=fs,
        nperseg=1024,
        noverlap=512,
        window='hann'
    )
    
    plt.figure(figsize=(10, 5))
    plt.semilogy(f/1000, Pxx)
    plt.xlabel('频率 (kHz)')
    plt.ylabel('功率谱密度 (dB/Hz)')
    plt.title('海豚声波功率谱密度 (Welch法)')
    plt.grid(True, alpha=0.3)
    plt.show()
    
    return f, Pxx

# 使用示例
# f, Pxx = estimate_psd_welch(dolphin_signal, fs=320000)

避坑指南:

我曾经在分析一段海豚回声定位信号时,直接用周期图法做PSD,结果谱线抖动得厉害,根本看不出主频。后来改用Welch法,分段数设了8段,谱线一下就清晰了。记住:分段数越多,谱估计越稳定,但频率分辨率会下降。需要根据信号长度和需求做权衡。

4.4 知识体系梳理

为了让你更直观理解本章的知识结构,我画了一张流程图:

频域分析知识体系 时域信号 x(t) FFT 傅里叶变换基础 频谱图绘制 功率谱密度估计 DFT原理 · FFT算法 · 频率分辨率 幅度谱 · 相位谱 · dB转换 Welch法 · 周期图法 · 窗函数 应用:海豚声波特征提取 · 频率识别 · 噪声分析

这张图把本章的三个核心内容串起来了。从时域信号出发,经过FFT变换,你可以选择做频谱图看幅度分布,也可以做PSD看能量分布。实际项目中,我通常两种都做——频谱图看细节,PSD看整体趋势。

实战建议:

处理海豚声波时,先画频谱图快速浏览频率范围,再用Welch法做PSD提取稳定特征。如果发现某个频段能量异常,可能就是海豚在发特定信号了。

好了,频域分析的基础就这些。记住:FFT是工具,频谱图和PSD是表达方式。关键是要理解海豚声波在频域里长什么样,这样才能做后续的识别和分类。


公众号:蓝海资料掘金营,微信deep3321