I have a simple problem, but I cannot find a good solution to it.
I want to take a NumPy 2D array which represents a grayscale image, and convert it to an RGB PIL image while applying some of the matplotlib colormaps.
I can get a reasonable PNG output by using the pyplot.figure.figimage
command:
dpi = 100.0w, h = myarray.shape[1]/dpi, myarray.shape[0]/dpifig = plt.figure(figsize=(w,h), dpi=dpi)fig.figimage(sub, cmap=cm.gist_earth)plt.savefig('out.png')
Although I could adapt this to get what I want (probably using StringIO do get the PIL image), I wonder if there is not a simpler way to do that, since it seems to be a very natural problem of image visualization. Let's say, something like this:
colored_PIL_image = magic_function(array, cmap)
Best Answer
Quite a busy one-liner, but here it is:
- First ensure your NumPy array,
myarray
, is normalised with the max value at1.0
. - Apply the colormap directly to
myarray
. - Rescale to the
0-255
range. - Convert to integers, using
np.uint8()
. - Use
Image.fromarray()
.
And you're done:
from PIL import Imagefrom matplotlib import cmim = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))
with plt.savefig()
:
with im.save()
:
input = numpy_image
np.uint8 -> converts to integers
convert('RGB') -> converts to RGB
Image.fromarray -> returns an image object
from PIL import Imageimport numpy as npPIL_image = Image.fromarray(np.uint8(numpy_image)).convert('RGB')PIL_image = Image.fromarray(numpy_image.astype('uint8'), 'RGB')
The method described in the accepted answer didn't work for me even after applying changes mentioned in its comments. But the below simple code worked:
import matplotlib.pyplot as pltplt.imsave(filename, np_array, cmap='Greys')
np_array could be either a 2D array with values from 0..1 floats o2 0..255 uint8, and in that case it needs cmap. For 3D arrays, cmap will be ignored.