# How to convert a NumPy array to PIL image applying matplotlib colormap

375,247

## Solution 1

Quite a busy one-liner, but here it is:

1. First ensure your NumPy array, myarray, is normalised with the max value at 1.0.
2. Apply the colormap directly to myarray.
3. Rescale to the 0-255 range.
4. Convert to integers, using np.uint8().
5. Use Image.fromarray().

And you're done:

from PIL import Image
from matplotlib import cm
im = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))

with plt.savefig():

with im.save():

## Solution 2

• input = numpy_image
• np.unit8 -> converts to integers
• convert('RGB') -> converts to RGB
• Image.fromarray -> returns an image object

from PIL import Image
import numpy as np

PIL_image = Image.fromarray(np.uint8(numpy_image)).convert('RGB')

PIL_image = Image.fromarray(numpy_image.astype('uint8'), 'RGB')

## Solution 3

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 plt
plt.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.

Share:
375,247

Author by

### heltonbiker

I am an ex-physician, have studied mechanical engineering for a while, and have a master degree in product design. Now I work designing diagnostic equipment (surface EMG, posturography, pedobarography), dealing with system requirements, data visualization, and GUI design, and the like. I am also a die-hard cyclist, be it trails (not much nowadays), off-road, commuting, touring or randonneuring. Besides, I have deep interests in bike design and mechanics.

Updated on June 07, 2020

• heltonbiker over 3 years

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.0
w, h = myarray.shape[1]/dpi, myarray.shape[0]/dpi
fig = 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)

• heltonbiker over 11 years
The "Apply the colormap directly to myarray" part cut straight to the heart! I didn't knew it was possible, thank you!
• heltonbiker over 11 years
Studying the docs about LinearSegmentedColormap (from which cm.gist_earth is an instance), I discovered that it's possible to call it with a "bytes" argument which already converts it to uint8. Then, the one-liner gets a lot quieter: im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
• Ciprian Tomoiagă almost 7 years
@heltonbiker what shape should myarray have ? I'm trying to get a wider image
• heltonbiker almost 7 years
@CiprianTomoiaga, the shape of the array should be the image dimensions you want. For example, a VGA image would be generated from an array with shape (1024,768). You should notice this applies for monochrome images. This is important because usually when you convert an RGB image to an array, its shape is, for example, (1024,768,3), since it has three channels.
• Ciprian Tomoiagă almost 7 years
Awesome! To generate a legend from a colormap I chained repeat and reshape like this: legegend_arry = plt.get_cmap(cmap_name)(np.linspace(0,1,legend_h).repeat(leg‌​end_w).reshape(legen‌​d_h,legend_w), bytes=True). Calling frombytes on legend_arry gives a PIL image of size (legend_h, legend_w). Thanks for the reference !
I am getting error NameError: name 'cm' is not defined
@mso from matplotlib import cm
• Aaron over 4 years
Also for a different colour map use im = Image.fromarray(np.uint8(cm.get_cmap('inferno')(myarray)*255‌​))
• Jaimil Patel over 3 years
Hope It will solve issue but please add explanation of your code with it so user will get perfect understanding which he/she really wants.
• Catalina Chircu over 3 years
Good, updated answer. The previous ones are from several years ago.
• Hyelin almost 3 years
Is there a reason for applying cm.gist_earth to myarray? I just thought I'd multiply 255 right away.