Matlab 频谱分析 (Spectral Analysis)

文章目录

    • [1. 信号预处理 - 去直流分量](#1. 信号预处理 - 去直流分量)
    • [2. 快速傅里叶变换(FFT)](#2. 快速傅里叶变换(FFT))
    • [3. 功率谱密度(PSD)计算](#3. 功率谱密度(PSD)计算)
    • [4. 主频率检测](#4. 主频率检测)
    • [5. 谱质心计算](#5. 谱质心计算)
    • [6. 对数谱显示](#6. 对数谱显示)
    • 完整的信号处理流程
    • 实际应用示例

1. 信号预处理 - 去直流分量

matlab 复制代码
data = data - mean(data);

数学原理:

去除信号的直流分量(DC offset),即:
x c e n t e r e d n = x n − μ x_{centered}n = xn - \mu xcenteredn=xn−μ

其中:

  • μ = 1 N ∑ n = 0 N − 1 x n \mu = \frac{1}{N}\sum_{n=0}^{N-1} xn μ=N1∑n=0N−1xn 是信号均值
  • N N N 是信号长度

作用: 去除0Hz分量,避免在频谱图中出现很大的直流峰值,影响其他频率成分的观察。

2. 快速傅里叶变换(FFT)

matlab 复制代码
Y = fft(data, nfft);
f = (0:nfft-1) * fs / nfft;

数学原理:

离散傅里叶变换(DFT)公式:
X k = ∑ n = 0 N − 1 x n ⋅ e − j 2 π k n / N Xk = \sum_{n=0}^{N-1} xn \cdot e^{-j2\pi kn/N} Xk=n=0∑N−1xn⋅e−j2πkn/N

其中:

  • k = 0 , 1 , . . . , N − 1 k = 0, 1, ..., N-1 k=0,1,...,N−1 是频率索引
  • N = n f f t = 2 12 = 4096 N = nfft = 2^{12} = 4096 N=nfft=212=4096 是FFT点数

频率分辨率:
Δ f = f s n f f t \Delta f = \frac{f_s}{nfft} Δf=nfftfs

频率向量计算:
f k = k ⋅ f s n f f t , k = 0 , 1 , . . . , n f f t − 1 fk = k \cdot \frac{f_s}{nfft}, \quad k = 0, 1, ..., nfft-1 fk=k⋅nfftfs,k=0,1,...,nfft−1

3. 功率谱密度(PSD)计算

matlab 复制代码
PSD = abs(Y).^2 / (fs * nfft);
PSD = PSD(1:nfft/2+1);
f = f(1:nfft/2+1);
PSD(2:end-1) = 2 * PSD(2:end-1);

数学原理:

Step 1: 计算功率谱
P S D k = ∣ X k ∣ 2 f s ⋅ N PSDk = \frac{|Xk|^2}{f_s \cdot N} PSDk=fs⋅N∣Xk∣2

这里除以 f s ⋅ N f_s \cdot N fs⋅N 是为了得到功率谱密度(单位:功率/Hz)。

Step 2: 单边谱转换

由于实信号的FFT结果具有共轭对称性:
X k = X ∗ N − k Xk = X^*N-k Xk=X∗N−k

所以只需要保留前一半频率(0到 f s / 2 f_s/2 fs/2),但要将功率翻倍(除了0Hz和Nyquist频率):

matlab 复制代码
PSD(2:end-1) = 2 * PSD(2:end-1);

数学表达:
P S D s i n g l e k = { P S D k , k = 0 或 k = N / 2 2 ⋅ P S D k , 1 ≤ k < N / 2 PSD_{single}k = \begin{cases} PSDk, & k = 0 \text{ 或 } k = N/2 \\ 2 \cdot PSDk, & 1 \leq k < N/2 \end{cases} PSDsinglek={PSDk,2⋅PSDk,k=0 或 k=N/21≤k<N/2

4. 主频率检测

matlab 复制代码
[~, peak_idx] = max(PSD(2:end));
main_freq = f(peak_idx + 1);

数学原理:

找到功率谱密度的最大值对应的频率:
f m a i n = arg ⁡ max ⁡ f > 0 P S D ( f ) f_{main} = \arg\max_{f > 0} PSD(f) fmain=argf>0maxPSD(f)

注意:从索引2开始是为了排除直流分量(0Hz)。

5. 谱质心计算

matlab 复制代码
centroid = sum(f_col .* PSD_col) / sum(PSD_col);

数学原理:

谱质心(Spectral Centroid)是频谱的"重心":
f c e n t r o i d = ∑ k = 0 N / 2 f k ⋅ P S D k ∑ k = 0 N / 2 P S D k f_{centroid} = \frac{\sum_{k=0}^{N/2} fk \cdot PSDk}{\sum_{k=0}^{N/2} PSDk} fcentroid=∑k=0N/2PSDk∑k=0N/2fk⋅PSDk

这是一个加权平均,权重是各频率的功率。

物理意义:

  • 谱质心反映了信号能量在频域的分布中心
  • 值越大,说明高频成分越多
  • 常用于音频信号分析中表征音色"明亮度"

6. 对数谱显示

matlab 复制代码
semilogx(f, 10*log10(PSD));

数学原理:

将功率谱密度转换为分贝(dB)单位:
P S D d B = 10 log ⁡ 10 ( P S D ) PSD_{dB} = 10 \log_{10}(PSD) PSDdB=10log10(PSD)

使用对数坐标的原因:

  1. 人耳对频率的感知是对数的
  2. 可以同时显示大范围的幅值差异
  3. 更容易观察低幅值的频率成分

完整的信号处理流程

复制代码
原始信号 x[n]
    ↓ (去直流)
中心化信号 x_c[n] = x[n] - μ
    ↓ (FFT)
频域信号 X[k]
    ↓ (功率计算)
双边功率谱 |X[k]|²/(fs·N)
    ↓ (单边谱转换)
单边功率谱密度 PSD[k]
    ↓ (特征提取)
主频率 + 谱质心

实际应用示例

假设采样率 fs = 1000 Hz,信号包含50Hz和120Hz两个正弦波:

matlab 复制代码
t = 0:1/fs:1;
x = sin(2*pi*50*t) + 0.5*sin(2*pi*120*t);

经过上述处理后:

  • 主频率将是 50 Hz(因为其幅度更大)
  • 谱质心将在 50-120 Hz 之间,偏向50Hz
相关推荐
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁4 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
孙启超4 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int4 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++
CoderYanger4 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读4 天前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json
CCCCCCCCharlie4 天前
Linux进程控制四大核心操作
linux·开发语言
Brilliantwxx4 天前
【STM32】 SPI Flash 驱动开发实战:阻塞模式驱动 W25Q64(含工程代码)
开发语言·stm32·单片机·嵌入式硬件