我该如何将Librosa频谱图保存为指定尺寸的图片?

14

我想将频谱图像作为卷积神经网络的输入,以尝试分类不同的声音。我希望每个图像都恰好是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)

有人能给我一些指针,告诉我如何修复这个问题吗?我也尝试过不使用subplot进行操作,但是这样保存的图片仍然大小错误,并且带有白色空白背景。


你确认你的dpi是128而不是接近100吗?否则,我认为这篇帖子有很好的答案 https://dev59.com/BGYr5IYBdhLWcg3wYpUg - user11563547
为什么不直接对 db 进行pickle处理,将原始数据作为CNN的输入呢?使用图像(特别是带有有损JPEG压缩的图像)很可能无法得到您想要的结果。 - Hendrik
你是怎么用这张图片来训练卷积神经网络的?我也在做同样的事情,但卡在了将已保存的图片传入模型的步骤。 - Deep
1个回答

29

图表是供人类查看的,其中包含轴标记、标签等对机器学习没有用处的内容。为了给模型提供频谱图像,应该只输出数据。这些数据可以以任何格式存储,但如果想要使用标准的图像格式,则应使用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)

输出

以PNG图像格式存储的频谱图


属性错误:模块“skimage”没有属性“io”。您需要直接导入skimage.io:import skimage.io。 - John Seales
我不知道...可能只是Imgur的一个问题,但在我的浏览器中,你的图片宽度为385像素。 - gboffi
Imgur 可能会重新压缩该图像,这有时会导致大小错误。如果有人能在本地重现这个问题,那么就是一个 bug。 - Jon Nordby
1
能否通过 .png 图像重构(或至少估计)出原始的 .wav 文件?谢谢!@jonnor - obar
1
@obar 是的,重建是可能的。不过相位重建往往会使其变得非常嘈杂。请参见 https://librosa.org/doc/main/generated/librosa.feature.inverse.mel_to_audio.html。 - Jon Nordby
1
如何为图像添加色彩?这是可能的吗? - Javad Shirkhani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接