|
python时域信号处理Demo:fft psd 自相关分析
- import numpy as np
- import matplotlib.pyplot as plt
- # python时域信号处理Demo:fft psd 自相关分析
- N = 200 # 采样个数
- f_s = 50 # 采样频率
- t = np.linspace(0.0, N/f_s, N)
- print("4秒内多少个采样点:", len(t))
- signal1 = 2 * np.sin(2 * 1 * np.pi * t) # f=1
- signal2 = np.sin(2 * 5 * np.pi * t) # f=5
- # 时域信号合成
- signal = signal1 + signal2
- def get_values(y_values, N, f_s):
- f_values = np.linspace(0.0, N/f_s, N)
- return f_values, y_values
- plt.figure(figsize=(16, 12))
- plt.subplot(231)
- f_values, signal_values = get_values(signal1, N, f_s)
- plt.plot(f_values, signal_values, linestyle='-', color='blue')
- plt.xlabel('Time [sec]', fontsize=16)
- # Amplitude 振幅
- plt.ylabel('Amplitude', fontsize=16)
- plt.title("Time domain of the signal1(f=1)", fontsize=16)
- # plt.show()
- plt.subplot(232)
- f_values, signal_values = get_values(signal2, N, f_s)
- plt.plot(f_values, signal_values, linestyle='-', color='blue')
- plt.xlabel('Time [sec]', fontsize=16)
- plt.ylabel('Amplitude', fontsize=16)
- plt.title("Time domain of the signal2(f=5)", fontsize=16)
- # plt.show()
- plt.subplot(233)
- f_values, signal_values = get_values(signal, N, f_s)
- plt.plot(f_values, signal_values, linestyle='-', color='blue')
- plt.xlabel('Time [sec]', fontsize=16)
- plt.ylabel('Amplitude', fontsize=16)
- plt.title("Time domain of the signal", fontsize=16)
- # plt.show()
- from scipy.fftpack import fft
- def get_fft_values(y_values, N, f_s):
- # 信号频率不会大于采样频率的一半
- f_values = np.linspace(0.0, f_s / 2.0, N // 2)
- fft_values_ = fft(y_values)
- print("原始信号数据经过fft后:", len(fft_values_))
- # 对称性 求模(振幅谱) 归一化(为什么乘以2.0)
- fft_values = 2.0 / N * np.abs(fft_values_[0:N // 2])
- print("单边振幅谱(归一化) 为什么乘以2.0???")
- print("绝对值就是求模,归一化后的fft值:", len(fft_values), fft_values[:5])
- return f_values, fft_values
- plt.subplot(234)
- f_values, fft_values = get_fft_values(signal, N, f_s)
- plt.plot(f_values, fft_values, linestyle='-', color='blue')
- plt.xlabel('Frequency [Hz]', fontsize=16)
- plt.ylabel('Amplitude', fontsize=16)
- plt.title("The FFT of our composite signal", fontsize=16)
- # plt.show()
- from scipy.signal import welch
- def get_psd_values(y_values, N, f_s):
- # 用韦尔奇方法估计功率谱密度
- f_values, psd_values = welch(y_values, fs=f_s)
- return f_values, psd_values
- plt.subplot(235)
- # PSD英文全称Power Spectral Density,即功率谱密度,它和FFT一样,反映的是信号在频域上的信息。
- # 其中PSD频谱图脉冲下方的面积表示信号在该频率上的能量分布。
- f_values, psd_values = get_psd_values(signal, N, f_s)
- plt.plot(f_values, psd_values, linestyle='-', color='blue')
- plt.xlabel('Frequency [Hz]', fontsize=16)
- plt.ylabel('PSD [V**2 / Hz]', fontsize=16)
- plt.title("The PSD of our composite signal", fontsize=16)
- def autocorr(x):
- # numpy互相关函数np.correlate
- # 《Python 数字信号处理应用》这本书上刚好看到过,题主想要用的应该是np.corrcoef这个方法,np.corrlated,是信号处理领域的自相关算法,
- # 【使用的非相关的标准化版定义,随着时滞变大,两个信号之间重叠点数减少,所以相关幅度降低了】,这是书上原话,
- # 我的理解是由于np.corrlated在有限范围内计算信号自相关,也就是错位相乘,随着时延增加重叠的点就会减少,计算的自相关也会变小,
- # 相比np.corrcoef,自相关函数的幅值明显有下降,需要除以N/2的长度这样可以获得与np.corrcoef几乎相同的结果
- result = np.correlate(x, x, mode='full')
- return result[len(result) // 2:]
- def get_autocorr_values(y_values, N, f_s):
- autocorr_values = autocorr(y_values)
- # 细节信息
- x_values = np.array([1.0 * jj / f_s for jj in range(0, N)])
- return x_values, autocorr_values
- plt.subplot(236)
- # Autocorrelation是自相关的意思,它可以求出信号的自相关性,即信号经过一个时延后与自身的相似性
- # 有趣的是Autocorrelation与PSD是一组FFT变换对,对Autocorrelation作FFT变换可得到PSD,对PSD作IFFT(快速傅里叶逆变换)可得到Autocorrelation
- t_values, autocorr_values = get_autocorr_values(signal, N, f_s)
- plt.plot(t_values, autocorr_values, linestyle='-', color='blue')
- plt.xlabel('time delay [s]', fontsize=16)
- plt.ylabel('Autocorrelation amplitude', fontsize=16)
- plt.title("The autocorrelation of signal.", fontsize=16)
- # plt.savefig('fft_psd_corr.png', dpi=200)
- plt.show()
复制代码
|
|