我尝试将使用频谱图函数的 matlab 脚本转换为 matplot lib 频谱函数。 一旦转换为频谱图灰度图像,输出图像相似,但功率谱密度矩阵形状不同
Matlab代码:
[~,~,~,P] = spectrogram(X, Fs/N, 0, N, Fs, 'centered');
和:
频谱图(x,窗口,noverlap,nfft,频谱类型)
FS = 50 * 10 ** 6
nfft = 500
在这种情况下,P 的形状是 500 x 500
Python代码:
P, freq , t, img = plt.specgram(x, NFFT=nfft , Fs=Fs, Fc=Fc, noverlap=0, window = np.hanning(nfft ))
在这种情况下,P 的形状是 500 x 100000
看起来 matlab 中的窗口参数允许将信号分成段,并且与 plt.specgram 的窗口参数无关(实际上按照文档;))
我的问题是:如何使用 plt.specgram 生成 500x500 矩阵? 有什么想法吗? 谢谢!
在 MATLAB 中 - 我们通过窗口大小和重叠显式定义段数。
spectrogram(x, windowSize, overlap, nfft, Fs, 'yaxis');
在 python 中 - 段数由输入信号的长度和 NFFT 参数决定
以此为参考...我们需要调整输入信号长度和 NFFT 参数。
Fs = 50 * 10**6
N = 500
desired_segments = 500
和
f, t, Sxx = signal.spectrogram(x, fs=Fs, nperseg=N, noverlap=0, nfft=N,
return_onesided=False, scaling='density')
最终代码
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
Fs = 50 * 10**6
N = 500
desired_segments = 500
t = np.linspace(0, 1, Fs, endpoint=False)
x = np.sin(2*np.pi*1e6*t) + 0.5*np.sin(2*np.pi*2e6*t)
signal_length = N * desired_segments
if len(x) > signal_length:
x = x[:signal_length]
else:
x = np.pad(x, (0, signal_length - len(x)), mode='constant')
f, t, Sxx = signal.spectrogram(x, fs=Fs, nperseg=N, noverlap=0, nfft=N,
return_onesided=False, scaling='density')
Sxx = np.fft.fftshift(Sxx, axes=0)
f = np.fft.fftshift(f)
plt.figure(figsize=(10, 8))
plt.pcolormesh(t, f, 10 * np.log10(Sxx), shading='gouraud')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.title('Spectrogram')
plt.colorbar(label='Power/Frequency [dB/Hz]')
plt.show()