如何有效地生成和连接频谱图
Posted
技术标签:
【中文标题】如何有效地生成和连接频谱图【英文标题】:How to generate and concatenate spectrograms efficiently 【发布时间】:2021-04-03 05:41:02 【问题描述】:我正在研究与信号处理相关的问题。我有一个超过 2000 个 EEG 信号的数据集。每个 EEG 信号由一个 2D Numpy 数组 (19 x 30000
) 表示。阵列的每一行都是信号的通道之一。我要做的是在这些单独的通道(行)上找到频谱图并将它们垂直连接起来。这是我目前写的代码。
raw = np.load('class_1_ar/'+filename)
images = []
for i in range(19):
print(i,end=" ")
spec,freq,t,im = plt.specgram(raw[i],Fs=100,NFFT=100,noverlap=50)
plt.axis('off')
figure = plt.gcf()
figure.set_size_inches(12, 1)
figure.canvas.draw()
img = np.array(figure.canvas.buffer_rgba())
img = cv2.cvtColor(img, cv2.COLOR_RGBA2BGRA)
b = figure.axes[0].get_window_extent()
img = np.array(figure.canvas.buffer_rgba())
img = img[int(b.y0):int(b.y1),int(b.x0):int(b.x1),:]
img = cv2.cvtColor(img, cv2.COLOR_RGBA2BGRA)
images.append(img)
base = cv2.vconcat(images)
cv2.imwrite('class_1_sp/'+filename[:-4]+'.png',base)
c -= 1
print(c)
这是我的输出:
但是,该过程需要花费太多时间来处理。前 200 个样本的处理耗时近 8 小时。
我的问题是,我该怎么做才能让它更快?
【问题讨论】:
您是否分析了您的代码以查看哪个部分花费的时间最多?看起来你绘制了一个频谱图,然后从屏幕上抓取图像?这似乎是一种相当迂回的做事方式...... 假设每个 EEG 的生成相互独立,您可以使用 Python 多处理并行化您的代码。此外,正如 Cris Luengo 所指出的,可能有一种更快的方法将数字存储到 Numpy 数组中。此外,请注意 matplotlib 通常很慢。可能有更快的软件包可以做到这一点(请看一下 scipy)。 谢谢。并行化它起作用了。现在速度更快了 【参考方案1】:正如其他人所说,通过 matplotlib 的开销可能会减慢速度。最好用scipy.signal.spectrogram 计算(而不是绘制)频谱图。此函数直接将频谱图作为 2D numpy 数组返回,因此您无需将其从画布中取出。请注意,这确实意味着您必须自己将频谱图输出映射到像素强度。在此过程中,请注意 scipy.signal.spectrogram
将频谱图返回为功率,而不是分贝,因此您可能希望对结果执行 10*np.log10(Sxx)
(另请参阅 scipy.signal.spectrogram compared to matplotlib.pyplot.specgram)。
撇开绘图不谈,计算频谱图的瓶颈操作是 FFT。不是使用 100 个样本的变换大小,而是 128 或 2 的某个其他幂更有效。对于scipy.signal.spectrogram
,这是通过设置nfft=128
来完成的。请注意,您可以设置 nperseg=100
和 nfft=128
以便每个段仍使用 100 个样本,但在执行 FFT 之前将零填充到 128。另一种想法:如果 raw
是 64 位浮点数,则将其转换为 32 位可能会有所帮助:raw = np.load(...).astype(np.float32)
。
【讨论】:
以上是关于如何有效地生成和连接频谱图的主要内容,如果未能解决你的问题,请参考以下文章