I was using imshow
to plot an array with a custom colormap and boundarynorm. However, this is going to be an automated script and I want to save the image produced by imshow
without the axes. So I wasn't sure imshow
was the best way to do this since its going to be running in the background. Is there an alternative where I can just set the colormap and boundarynorm and produce a rgba array that I can give to imsave
? Or am I just left with hacking the image that imshow
produce and saving that?
Asked
Active
Viewed 4,074 times
1
-
Take a look at this thread: http://stackoverflow.com/questions/9622163/save-plot-to-image-file-instead-of-displaying-it-using-matplotlib-so-it-can-be . Hope it helps, – antonioduarte Jul 13 '15 at 22:58
-
How about `plt.axis('off')`? – tom10 Jul 14 '15 at 00:25
-
@tom10 yea, that was the other option, use imshow and turn off axis and a few other tweaks to get just the image. i guess wanted a little more control, and wish i could just get the raw rbga array. – Vinh Jul 14 '15 at 01:13
-
I decided to just use pypng and create the png from a numpy array that i was working with, since it had more control in creating the png. i could just use the palette and transform the ndarray to the palette's indexes – Vinh Jul 14 '15 at 20:04
2 Answers
4
You can use as_rgba_str
to get the image data from the image. Here's an example:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2, 1000)
X, Y = np.meshgrid(x, x)
data = np.sin((X-2)**3 + Y**4)
im = plt.imshow(data)
x = im.make_image()
h, w, d = x.as_rgba_str()
n = np.fromstring(d, dtype=np.uint8).reshape(h, w, 4)
plt.figure()
plt.imshow(n[:,:,0], cmap="gray", origin='lower')
plt.show()
The original image:
The R channel from the RGBA data (note all the blue sections are black since these have no red in them):

tom10
- 67,082
- 10
- 127
- 137
1
matplotlib.colors.Colormap.__call__
performs the cmap and returns the RGBA array.
https://matplotlib.org/3.3.1/api/_as_gen/matplotlib.colors.Colormap.html#matplotlib.colors.Colormap.__call__
# created using numpy 1.18.5 and matplotlib 3.2.2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm, colors
x = np.linspace(0, 2, 1000)
X, Y = np.meshgrid(x, x)
data = np.sin((X-2)**3 + Y**4)
print(f"data.shape: {data.shape}")
print(f"data.dtype: {data.dtype}")
cmap: colors.Colormap = cm.get_cmap("rainbow")
norm: colors.Normalize = colors.Normalize()
# set min and max values from data
norm.autoscale(data)
# move scalar values to range [0, 1]
# can skip and pass directly to cmap if data already [0, 1]
normalised = norm(data)
# create a RBGA array
# bytes=True gives a uint8 array (Unsigned integer 0 to 255)
data_rgba = cmap(normalised, bytes=True)
print(f"data_rgba.shape: {data_rgba.shape}")
print(f"data_rgba.dtype: {data_rgba.dtype}")
# pass RBGA array to imsave and set origin to upper or lower
plt.imsave("my_data.png", data_rgba, origin="lower")
Should also be possible in one step using matplotlib.cm.ScalarMappable.to_rgba
but I haven't tried that.
https://matplotlib.org/3.3.1/api/cm_api.html#matplotlib.cm.ScalarMappable.to_rgba

Robin Carter
- 139
- 9