如何将 Librosa 频谱图保存为特定尺寸的图像?

Posted

技术标签:

【中文标题】如何将 Librosa 频谱图保存为特定尺寸的图像?【英文标题】:How can I save a Librosa spectrogram plot as a specific sized image? 【发布时间】:2019-11-05 05:33:32 【问题描述】:

所以我想将频谱图图像输入卷积神经网络,以尝试对各种声音进行分类。我希望每张图像都是 384x128 像素。但是,当我实际保存图像时,它只有 297x98。这是我的代码:

def save_spectrogram(num):
  dpi = 128
  x_pixels = 384
  y_pixels = 128
  samples, sr = load_wave(num)
  stft = np.absolute(librosa.stft(samples))
  db = librosa.amplitude_to_db(stft, ref=np.max)
  fig = plt.figure(figsize=(x_pixels//dpi, y_pixels//dpi), dpi=dpi, frameon=False)
  ax = fig.add_subplot(111)
  ax.axes.get_xaxis().set_visible(False)
  ax.axes.get_yaxis().set_visible(False)
  ax.set_frame_on(False)
  librosa.display.specshow(db, y_axis='linear')
  plt.savefig(TRAIN_IMG+str(num)+'.jpg', bbox_inches='tight', pad_inches=0, dpi=dpi)

有人对我如何解决这个问题有任何指示吗?我也尝试过不使用子图,但是当我这样做时,它仍然保存为错误的大小并且有空白/背景。

【问题讨论】:

您是否确认您的 dpi 为 128,而不是接近 100?否则,我认为这篇文章有很好的答案***.com/questions/13714454/… 您为什么不简单地腌制db 并将原始数据用作CNN 的输入?使用图像(尤其是有损 JPEG 压缩)不太可能给您想要的结果。 你是如何将这张图片用于 CNN 的?我正在做同样的事情并坚持将保存的图像保存到模型中。 【参考方案1】:

绘图供人类查看,包含轴标记、标签等对机器学习无用的内容。要为模型提供频谱图的“图像”,应该只输出数据。此数据可以任何格式存储,但如果您想使用标准图像格式,则应使用 PNG。 JPEG 等有损压缩会引入压缩伪影。

以下是保存频谱图的工作示例代码。请注意,要获得固定大小的图像输出,代码会提取音频信号的固定长度窗口。将音频流划分为此类固定长度的分析窗口是标准做法。

示例代码

import librosa
import numpy
import skimage.io

def scale_minmax(X, min=0.0, max=1.0):
    X_std = (X - X.min()) / (X.max() - X.min())
    X_scaled = X_std * (max - min) + min
    return X_scaled

def spectrogram_image(y, sr, out, hop_length, n_mels):
    # use log-melspectrogram
    mels = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels,
                                            n_fft=hop_length*2, hop_length=hop_length)
    mels = numpy.log(mels + 1e-9) # add small number to avoid log(0)

    # min-max scale to fit inside 8-bit range
    img = scale_minmax(mels, 0, 255).astype(numpy.uint8)
    img = numpy.flip(img, axis=0) # put low frequencies at the bottom in image
    img = 255-img # invert. make black==more energy

    # save as PNG
    skimage.io.imsave(out, img)


if __name__ == '__main__':
    # settings
    hop_length = 512 # number of samples per time-step in spectrogram
    n_mels = 128 # number of bins in spectrogram. Height of image
    time_steps = 384 # number of time-steps. Width of image

    # load audio. Using example from librosa
    path = librosa.util.example_audio_file()
    y, sr = librosa.load(path, offset=1.0, duration=10.0, sr=22050)
    out = 'out.png'

    # extract a fixed length window
    start_sample = 0 # starting at beginning
    length_samples = time_steps*hop_length
    window = y[start_sample:start_sample+length_samples]
    
    # convert to PNG
    spectrogram_image(window, sr=sr, out=out, hop_length=hop_length, n_mels=n_mels)
    print('wrote file', out)

输出

【讨论】:

AttributeError: 模块 'skimage' 没有属性 'io'。需要直接导入skimage.io:import skimage.io 我不知道……可能它只是一个 Imgur 人工制品,但在我的浏览器中,您的图像是 385 像素宽。 Imgur 可能会重新压缩图像,这有时会因一个尺寸错误而泄露。如果有人可以在本地重现,那将是一个错误 在给定 .png 图像的情况下,是否可以重建(或至少估计)原始 .wav?谢谢! @jonnor @obar 是的,重建是可能的。尽管相位重建往往会使它变得非常嘈杂。见librosa.org/doc/main/generated/…

以上是关于如何将 Librosa 频谱图保存为特定尺寸的图像?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 librosa 库中的频谱图具有不同的实际音轨持续时间?

在 MATLAB 中将频谱图另存为图像

MATLAB中如何将imshow后的图片保存成原始大小的?

librosa音频处理教程

有没有办法直接将频谱图转换为 MFCC?

如何将 matplotlib 频谱图图像转换为火炬张量