Как сохранить график спектрограммы Librosa как изображение определенного размера? - PullRequest
0 голосов
/ 22 июня 2019

Итак, я хочу передать изображения спектрограмм в сверточную нейронную сеть, чтобы попытаться классифицировать различные звуки. Я хочу, чтобы каждое изображение было точно 384x128 пикселей. Однако, когда я на самом деле сохраняю изображение, оно составляет всего 297х98. Вот мой код:

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)

У кого-нибудь есть указания, как мне это исправить? Я также пытался сделать это без подзаговора, но когда я это делаю, он все равно сохраняет неправильный размер И имеет пробел / фон.

1 Ответ

0 голосов
/ 25 июля 2019

Графики предназначены для просмотра людьми и содержат такие вещи, как маркеры осей, метки и т. Д., Которые бесполезны для машинного обучения. Чтобы снабдить модель «изображением» спектрограммы, нужно выводить только данные. Эти данные хранятся в любом формате, но если вы хотите использовать стандартный формат изображения, то следует использовать PNG. Сжатие с потерями, например JPEG, вводит артефакты сжатия.

Здесь приведен рабочий пример кода для сохранения спектрограммы. Обратите внимание, что для получения изображения с фиксированным размером код извлекает окно аудиосигнала с фиксированной длиной. Разделение аудиопотока на такие окна анализа фиксированной длины является стандартной практикой.

Пример кода

import librosa
import numpy
import skimage

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)

выход

Spectrogram stored as PNG image

...