1

I want to get a matplotlib figure as a 3 dimensional RGBA array. I'm using the following code to do the conversion:

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np

canvas = np.zeros((20, 20))

img = plt.imshow(canvas, interpolation='none').make_image()
h, w, d = img.as_rgba_str()
print(h,w)
rgba_array = np.fromstring(d, dtype=np.uint8).reshape(h, w, 4)

plt.imshow(rgba_array)

Out[1]: (249, 373)
<matplotlib.image.AxesImage at 0x111fa8b10>

output from cell

Why the aspect ratio changes from the original square array? Is there any parameter that I can specify or an alternative method to get the figure's rgba array in its original shape?

prl900
  • 4,029
  • 4
  • 33
  • 40

3 Answers3

1

I think you can get there using this answer: https://stackoverflow.com/a/35362787/1072212, but instead of canvas.tostring_rgb() use canvas.tostring_argb() (not ..._rgba()), and

width, height = map(int, fig.get_size_inches() * fig.get_dpi())
image = image.reshape(height, width, 4)
image = np.roll(image, -1, 2)

later you might want

img = Image.fromarray(image, 'RGBA')
img.save('my.png')
img.show()
Terry Brown
  • 1,300
  • 14
  • 13
0

when I execute your code in pycharm (353, 497) when I execute your code in pycharm line by line (353, 353) when I execute your code in ipython (from command shell) (385, 497)

I suppose the

img = plt.imshow(canvas, interpolation='none').make_image()
h, w, d = img.as_rgba_str()

make_image() is actually not transforming the values, BUT one value for each pixel in the axes. So if your axes are shown as a square on the screen it picks a square at a higher resolution. Otherwise just some rectangle, depending on your backend and screen resolution.

cattt84
  • 941
  • 1
  • 10
  • 17
0

I've found an alternative method which doesn't make use of the .imshow() function and that preserves size ratio:

%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

canvas = np.zeros((20, 20))
img = Image.fromarray(np.uint8(plt.cm.gist_earth(canvas)*255))
rgba_array = np.array(img.getdata(), np.uint8).reshape(img.size[1], img.size[0], 4)
print(rgba_array.shape)

plt.imshow(rgba_array)

Out[1]: (20, 20, 4)
<matplotlib.image.AxesImage at 0x112a71710>

enter image description here

prl900
  • 4,029
  • 4
  • 33
  • 40