-1

in my code - which is actually longer that what I show here - I'm calculating a magnitude spectrogram of an audio signal. Afterwards, I'm plotting a pcolormesh plot. When I view the spectrogram with matplotlib.pyplot.show(), almost immediately the plot pops up (see below). I measured this with time.time() and the reaction is very quick.

The issue is the following: I need to take this matplotlib.pyplot.pcolormesh and convert it to numpy array image for the purpose of sending it through SpoutGL. I've tried rendering the plot onto a canvas with FigureCanvasAgg. While this does work, it takes too long (around 0.6 sec for HD dimensions - my goal is max 0.05 sec). I've also tried get_array(). This is very fast, but it completely destroys the spectrogram plot into a confusing mix of pixels (see below).

Since the plt.show() reaction is so fast and it does show the pcolormesh as... well, essentially an image, I figured there must be a way to use this and convert the plot somewhat "directly" into a numpy array to be sent through SpoutGL. But I have no idea how. The get_array() failed so far. Is there a way to make get_array() work? Or is there another way? I'd very much appreciate any help. This has been bugging me for days and days (especially since the plt.show() is so quick).

# Calculating and plotting the spectrogram
frequencies, times, magnitude_spectrogram = spectrogram(audio_signal, fs=44100, window=hann, nperseg=2000, noverlap=int(nperseg / 1.2))

spectrogram_fig = matplotlib.pyplot.figure(figsize=(12.8, 7.2), frameon=False)
matplotlib.pyplot.pcolormesh(times, frequencies, 10 * np.log10(magnitude_spectrogram), shading='gouraud', cmap="inferno", vmin=-100, vmax=-30)

matplotlib.pyplot.show()

# Here I need to convert the plot to numpy array

# Sending through SpoutGL
SpoutGL.SpoutSender().sendImage(spectrogram_plot_to_image, 1280, 720, GL.GL_RGB, False, 0)

the spectrogram plot shown with show()

get_array() image result

OndBoc
  • 9
  • 2
  • Do these answers help you? https://stackoverflow.com/a/67956006/8310295 (using canvas.tostring_rgb()) or https://stackoverflow.com/questions/34840366/matplotlib-pcolormesh-get-array-returns-flattened-array-how-to-get-2d-dat (pcolormesh flattens the array) – K.Cl Aug 27 '23 at 12:15
  • @K.Cl the canvas solution does work, but it is too slow. As I've said above, it takes about 0.6sec (too much for me). Now, the thing is that my spec_plot generation is in a loop. The canvas solution might work if it was possible to put some of the canvas processing outside the loop (hence it would be initiated just once out of dozens maybe hundreds of loops). Unfortunately I haven't managed to split the canvas processing in this way. It seems it has to be wholly processed each loop. I'll check the other link. Thanks ^^ – OndBoc Aug 27 '23 at 12:29

0 Answers0