Причина, по которой вы не хотите повторно вызывать функцию plt.specgram
внутри анимации, - это производительность.После N циклов у вас есть N изображений на вашей фигуре, что делает рисование все более и более дорогим.
Конечно, возможное решение состоит в том, чтобы удалить предыдущее изображение в каждой итерации, например, с помощью дескриптора (im.remove()
) или через список изображений (ax.images[0].remove()
).
Тем не менее, вы правы, что более желательным решением является не воссоздание какого-либо изображения вообще, а только изменение данных изображения.
В этом случае вы захотите позвонить matplotlib.mlab.specgram
, чтобы получить спектр в виде массива numpy и использовать метод set_array()
изображения для обновления изображения в анимации.
Обратите внимание, однако, что для этого может потребоваться обновить ограничения цветатакже изображения, если разные спектры имеют разные минимальные или максимальные амплитуды.
Поскольку изображение, показанное plt.specgram
, не является непосредственно спектрограммой, возвращенной mlab.specgram
, вам может потребоваться установитьнекоторые параметры вручную.В частности, по умолчанию изображение отображается в масштабе дБ.
Я думаю, что эквивалент
Fs = rate
NFFT = 256
noverlap= 128
spec, freqs, t, im = plt.specgram(sound, Fs=Fs, NFFT=NFFT, noverlap=noverlap)
будет
spec, freqs, t = plt.mlab.specgram(sound, Fs=rate, NFFT=NFFT, noverlap=noverlap)
pad_xextent = (NFFT-noverlap) / Fs / 2
xmin, xmax = np.min(t) - pad_xextent, np.max(t) + pad_xextent
extent = xmin, xmax, freqs[0], freqs[-1]
im = plt.imshow(np.flipud(10. * np.log10(spec)), extent=extent, aspect="auto")