python 使用signal.stft与plt.specgram时频图绘制的对比

问题:发现了这两个函数画时频图的区别就对应于matlab的spectrogram函数加不加“centered”参数

plt.specgram 对应于加“centered”参数的spectrogram函数
signal.stft 对应于不加“centered”参数的spectrogram函数

1、使用plt.specgram画时频图

matplotlib.pyplot.specgram(x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, noverlap=None, cmap=None, xextent=None, pad_to=None, sides=None, scale_by_freq=None, mode=None, scale=None, vmin=None, vmax=None, *, data=None, **kwargs)

详细参数含义查看官网:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.specgram.html

1)入口参数

x : 一维数组或序列
Fs : 采样频率, default: 2
window : 长度为NFFT的函数或向量。参见 scipy.signal.get_window, default: window_hanning
sides : {‘default’, ‘onesided’, ‘twosided’}, 返回光谱的哪一边。 对于默认数据,“默认”为单面;对于复杂数据,“默认”为单面。 “单面”强制返回单侧频谱,而“单面”强制双向。
noverlap : 块之间的重叠点数。 default: 128。
NFFT : 每个块中用于FFT的数据点数。 幂2是最有效的。 不应将其用于填充零,否则结果的缩放比例将不正确; 使用pad_to代替。default: 256
mode: {‘default’, ‘psd’, ‘magnitude’, ‘angle’, ‘phase’}
使用哪种频谱。 默认值为“ psd”,它采用功率谱密度。 “magnitude”返回幅度谱。 “angle”返回相位光谱而无需展开。 'phase’返回展开的相位谱。

2) 返回参数

spectrum:2-D array,列是连续段的周期图。
freqs:1-D array, 对应于频谱中各行的频率。
t:1-D array, 与段的中点相对应的时间(即频谱中的列)。
im:由imshow创建的包含频谱图的图像。

3)画指定像素大小的时频图,取消显示坐标轴以及四周白色空隙

写得太乱了orz

from scipy import io as spio
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import math
from PIL import Image

# plt.specgram

my_dpi = 10
plt.figure(figsize=(416/my_dpi, 416/my_dpi), dpi=my_dpi)

Pxx, freqs, bins, im = plt.specgram(ds_y, NFFT=128, Fs=20000000, noverlap=126,window = signal.get_window(('kaiser', 18.0), 128))

# plt.xlim((0, 0.001))
# plt.ylim((-10000000, 10000000))
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, hspace = 0, wspace = 0)
plt.margins(0,0)        
# 取消显示坐标轴
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig('./example1.jpg',pad_inches=0)

python 使用signal.stft与plt.specgram时频图绘制的对比_第1张图片

2、使用signal.stft画时频图

计算短时傅立叶变换(STFT)。

STFT可用作量化非平稳信号的频率和相位含量随时间变化的一种方式。

scipy.signal.stft(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None, detrend=False, return_onesided=True, boundary='zeros', padded=True, axis=- 1)

详细参数参考官网https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html

1)入口参数

x :测量值的时间序列
fs :x时间序列的采样频率。 默认为1.0。
window :需要使用的窗口。 如果window是字符串或元组,则将其传递到get_window以生成窗口值,默认情况下,该值是DFT-even。 有关窗口和必需参数的列表,请参见get_window。 如果window是array_like,则它将直接用作窗口,并且其长度必须为nperseg。 默认为Hann窗口。https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.get_window.html#scipy.signal.get_window
nperseg : 每个段的长度。 默认值为256。
noverlap : 段之间重叠的点数。 如果为None,则noverlap = nperseg // 2.默认为None。 指定后,必须满足COLA约束(请参阅官网的注释)。
nfft : 如果需要零填充的FFT,则使用的FFT的长度。 如果为None,则FFT长度为nperseg。 默认为无。
return_onesided : 如果为True,则返回单边频谱以获取真实数据。 如果为False,则返回两侧频谱。 默认值为True,但对于复杂数据,始终返回一个双边频谱。
padded : 指定输入信号的末尾是否为零填充,以使信号完全适合整数个窗口段,以便所有信号都包含在输出中。 默认为True。 如果边界不为None(无),并且填充为True(默认值),则填充会在边界扩展之后发生。
axis : 计算STFT的轴; 默认值位于最后一个轴上(即axis = -1)。

2)返回参数

f : ndarray,采样频率数组。
t : ndarray,采样时间数组。
Zxx : ndarray,x的STFT。 默认情况下,Zxx的最后一个轴对应于段时间。

from scipy import io as spio
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import math
from PIL import Image

# signal.stft
f, t, X = signal.stft(ds_y, fs=20000000, window='hann', nperseg=256, noverlap=255, 
                      nfft=416,return_onesided=False, padded=True, detrend = False)
size_x =416
size_y = 416
aa = np.abs(X) * 255
aa_max = max(map(max,aa))
beishu = math.floor(255/aa_max)
spectrum_matrix = np.flipud(np.floor(aa*beishu))
im = Image.fromarray(spectrum_matrix)     # 矩阵转为图像
im = im.convert('RGB')
im = im.resize((size_x, size_y))
# 这里一定记得加quality = 100,按照默认值生成的图像质量不够好
im.save("./example2.jpg",quality = 100)

python 使用signal.stft与plt.specgram时频图绘制的对比_第2张图片
疑问:
1、为什么这里要加np.flipud,对列元素的元素进行倒序,如果去掉,图下如下所示

可以画LTE的导频图来验证python 使用signal.stft与plt.specgram时频图绘制的对比_第3张图片
2、为什么图像画出来是黑白滴?能不能转化成彩色的呢?

你可能感兴趣的:(python 使用signal.stft与plt.specgram时频图绘制的对比)