You need a properly sized numpy array, meaning a HxWx3 array with integers. I tested it with the following code and input, seems to work as expected.

import os.path
import numpy as np
from PIL import Image


def pil2numpy(img: Image = None) -> np.ndarray:
    """
    Convert an HxW pixels RGB Image into an HxWx3 numpy ndarray
    """

    if img is None:
        img = Image.open('amsterdam_190x150.jpg'))

    np_array = np.asarray(img)
    return np_array


def numpy2pil(np_array: np.ndarray) -> Image:
    """
    Convert an HxWx3 numpy array into an RGB Image
    """

    assert_msg = 'Input shall be a HxWx3 ndarray'
    assert isinstance(np_array, np.ndarray), assert_msg
    assert len(np_array.shape) == 3, assert_msg
    assert np_array.shape[2] == 3, assert_msg

    img = Image.fromarray(np_array, 'RGB')
    return img


if __name__ == '__main__':
    data = pil2numpy()
    img = numpy2pil(data)
    img.show()

I am using:

  • Python 3.6.3
  • numpy 1.14.2
  • Pillow 4.3.0
Answer from physicalattraction on Stack Overflow
🌐
Reddit
reddit.com › r/learnpython › how to convert rgb array to image?
r/learnpython on Reddit: How to convert RGB array to image?
May 6, 2023 -

So I tried to convert a raw RGB array to an image with this simple code:

import numpy as np

from PIL import Image

Canvas = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 0], [0, 0, 0]])

img = Image.fromarray(Canvas, 'RGB')

img = img.save("canvas.png")

I have no idea how to set the size of the image as a resolution of 2x2 because this code does not create the correct resolution

The first pixel in Canvas should be red, second pixel should be green, the third and fourth pixels should be black

All I want is a 2x2 resolution image where the top-left pixel is red and the top-right pixel is green, then both bottom pixels should be black, but my code is just producing the wrong image resolution with the wrong pixel locations. What is the issue?

🌐
Finxter
blog.finxter.com › home › learn python blog › 5 best ways to convert a python numpy array to an rgb image
5 Best Ways to Convert a Python NumPy Array to an RGB Image - Be on the Right Side of Change
February 20, 2024 - The Python Imaging Library (Pillow) is a versatile library designed specifically for opening, manipulating, and saving many different image file formats. To convert a NumPy array to an RGB image, you can utilize the Image.fromarray() function ...
🌐
Reddit
reddit.com › r/learnprogramming › convert a numpy array to rgb (or animating a set of images)
r/learnprogramming on Reddit: Convert a numpy array to rgb (or animating a set of images)
May 19, 2017 - I have an array of 0s and 1s (integers, not boolen) that I'd like to convert to an rgb matrix. Now using PIL, this isn't too hard. I'd do something like: from PIL import Image import numpy as np rand_array = np.uint8(255*np.random.rand(600,600)) im = Image.fromarray(rand_array) im.show()
Top answer
1 of 2
4

In your comment you specify that the red_arr, etc. are arrays of the range -4000 to 4000.

But if we take a look at the specifications of the Image.from_array modes, then we see that it expects a matrix of three bytes (values from zero to 255).

This is however not per se a problem: we can perform:

def rescale(arr):
    arr_min = arr.min()
    arr_max = arr.max()
    return (arr - arr_min) / (arr_max - arr_min)

red_arr_b = 255.0 * rescale(red_arr)
green_arr_b = 255.0 * rescale(green_arr)
blue_arr_b = 255.0 * rescale(blue_arr)

arr[:,:,0] = red_arr_b
arr[:,:,1] = green_arr_b
arr[:,:,2] = blue_arr_b

img = Image.fromarray(arr.astype(int), 'RGB')

So first we rescale to a range 0 to 255, and then we feed that array to the PIL.

It is also possible that we want to scale red, green and blue the same way. In that case we can use:

def rescale(arr):
    arr_min = arr.min()
    arr_max = arr.max()
    return (arr - arr_min) / (arr_max - arr_min)

arr[:,:,0] = red_arr
arr[:,:,1] = green_arr
arr[:,:,2] = blue_arr

arr = 255.0 * rescale(arr)

img = Image.fromarray(arr.astype(int), 'RGB')
2 of 2
4

Your np array should have data type as uint8:

arr = np.zeros((len(x), len(z), 3),dtype='uint8')

Essentially, PIL calls tobytes function on each strides of your arr and if they are of type int, extra bytes will be generated.

Here are the result of following piece of code with different data type.

import numpy as np
from PIL import Image

size=241

arr = np.zeros((size,size,3))

arr[:,:,0] = [[255]*size]*size
arr[:,:,1] = [[255]*size]*size
arr[:,:,2] = [[0]*size]*size

img = Image.fromarray(arr.astype(int), 'RGB')

import numpy as np
from PIL import Image

size=241

arr = np.zeros((size,size,3))

arr[:,:,0] = [[255]*size]*size
arr[:,:,1] = [[255]*size]*size
arr[:,:,2] = [[0]*size]*size

img = Image.fromarray(arr.astype('uint8'), 'RGB')

As suggested by others, if your original input are not in range (0,255), you will need to rescale them as well.

Top answer
1 of 1
4

It seems to me that there are 3 aspects to your question:

  • creating a colormap, or LUT "Lookup Table"
  • scaling your pixels to a standard range
  • applying a colormap to an image without matplotlib.

So, to create a colormap, we need a list of 256 RGB values in which we can lookup any greyscale value and find the colour we want to show it as. I understand you can't use matplotlib in production, but you can grab a colormap or two from there on some other machine and copy it to your production machine. So, let's do that. We'll take the viridis colormap:

#!/usr/bin/env python3

import numpy as np
from matplotlib import cm

# Get 256 entries from "viridis" or any other Matplotlib colormap
colmap = cm.get_cmap('viridis', 256)

# Make a Numpy array of the 256 RGB values
# Each line corresponds to an RGB colour for a greyscale level
np.savetxt('cmap.csv', (colmap.colors[...,0:3]*255).astype(np.uint8), fmt='%d', delimiter=',')

If we look at that file "cmap.csv", it has 256 lines and starts like this:

68,1,84
68,2,85
68,3,87
69,5,88
69,6,90
69,8,91
70,9,92
...
...

That means anywhere we see 0 in the greyscale image, we actually colour the pixel rgb(68,1,86). Anywhere we see 1 in the greyscale it maps to rgb(68,2,85). Presumably you can copy that file to your production machine and you can choose any one of Matplotlibs colormaps.


Regarding scaling, you have posted an 8-bit PNG image with a range of 0..117 rather than a 16-bit TIFF image with a range of 17..317, so that is not most helpful. Also, you have not said how you plan to read a TIFF on a system that doesn't have OpenCV or matplotlib, so I don't know whether you have PIL/Pillow or plan to use tifffile.

Instead then, I will create a dummy 32x32 image with a range of 17..317 like this:

grey = np.random.randint(17,318, (32,32))

That looks like this:

array([[244,  75, 237, ..., 154, 190,  70],
       [286, 247, 158, ..., 150, 267, 124],
       [170, 305, 237, ..., 126, 111, 236],
       ...,
       [163, 292, 184, ...,  24, 253, 177],
       [314,  34,  36, ...,  87, 316, 182],
       [258, 153, 278, ..., 189,  57, 196]])

If we now want to scale that from the range 17..317 into the range 0..255, we can use:

rescaled = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

which gives us this:

array([[192,  49, 187, ..., 116, 147,  45],
       [228, 195, 119, ..., 113, 212,  90],
       [130, 244, 187, ...,  92,  79, 186],
       ...,
       [124, 233, 141, ...,   5, 200, 136],
       [252,  14,  16, ...,  59, 254, 140],
       [204, 115, 221, ..., 146,  34, 152]], dtype=uint8) 

Looking up can be done by loading the CSV file containing our colourmap, and taking the corresponding elements from the colormap as indexed by your greyscale values in the range 0...255:

#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Load image as greyscale and make into Numpy array
grey = np.array(Image.open('TdoGc.png').convert('L'))

# Load RGB LUT from CSV file
lut = np.loadtxt('cmap.csv', dtype=np.uint8, delimiter=',')

# Make output image, same height and width as grey image, but 3-channel RGB
result = np.zeros((*grey.shape,3), dtype=np.uint8)

# Take entries from RGB LUT according to greyscale values in image
np.take(lut, grey, axis=0, out=result)

# Save result
Image.fromarray(result).save('result.png')

If you scale your greyscale image to the full range after reading, using this line:

grey = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

You will get this:


If you want to visualise your colormap, change the line above that looks like this:

grey = np.array(Image.open('TdoGc.png').convert('L'))

into this so that it generates a gradient (ramp) image:

grey = np.repeat(np.arange(256,dtype=np.uint8).reshape(1,-1), 100, axis=0)

Then you can see your colourmap:


A quick hack to handle segmented linear colormaps that don't have a class variable enumerating the colours. So you can make the cmap.csv file from the autumn colourmap like this:

import numpy as np
from matplotlib import cm

# Get "autumn" colourmap
colmap = cm.get_cmap('autumn')

# Save 256 RGB entries as CSV - one for each of grey levels 0..255
np.savetxt('cmap.csv', np.array([colmap(i/255)[:3] for i in range(256)]) * 255, fmt="%d", delimiter=',')

🌐
Codegive
codegive.com › blog › convert_numpy_array_to_rgb_image.php
Convert numpy array to rgb image
Channel Order: While RGB is standard, some libraries (most notably OpenCV) default to BGR (Blue, Green, Red). Be mindful of this to avoid color inversions. Let's dive into the practical conversions! Pillow is an excellent library for general image manipulation. It's user-friendly and handles most common image formats and operations. If your NumPy array is already in (height, width, 3) shape with uint8 data type and values between 0 and 255, Pillow can convert it directly.
🌐
w3resource
w3resource.com › python-exercises › numpy › python-numpy-exercise-109.php
Python NumPy: Convert a numpy array to an image - w3resource
August 29, 2025 - ... # Importing the Image module ... an image object 'img' from the NumPy array 'data', specifying the color mode as 'RGB' img = Image.fromarray(data, 'RGB') # Saving the image as 'test.png' img.save('test.png') # Displaying ...
🌐
YouTube
youtube.com › mixible
How to convert a python numpy array to an RGB image with Opencv 2 4 - YouTube
Welcome to Mixible, your go-to source for comprehensive and informative content covering a broad range of topics from Stack Exchange websites. Our channel is...
Published: October 28, 2023
Views: 15
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 70707560 › converting-numpy-array-into-an-rgb-image-using-pillow
python - Converting numpy array into an RGB image using PILLOW - Stack Overflow
n_images = 1 train_data_np = train_data.to_numpy() train_images = train_data_np[:n_images] for i in range(n_images): image_res = np.reshape(train_images[i],[11,11]) img2 = np.zeros( ( image_res.shape[0], image_res.shape[1], 3 ) ) img2[:,:,0] = image_res # same value in each channel img2[:,:,1] = image_res img2[:,:,2] = image_res image_train = np.reshape(img2,[11,11,3]) image = im.fromarray(np.uint8(image_train),'RGB') plt.imshow(image) plt.show() can someone explain to me how to implement or use a python function to transform the NumPy array 11x11 into an array of 11x11x3 using a colormap ?
🌐
Facebook
facebook.com › groups › 1854021431561644 › posts › 2012900429007076
How can I convert numpy array to rgb image using python?
Popular groups · Find communities for you · Over 1 billion people across the globe are using Facebook Groups to explore their favorite topics · Log in · Categories · Science & tech · Travel · Animals · Sports & fitness · Entertainment
🌐
Pythoninformer
pythoninformer.com › python-libraries › numpy › numpy-and-images
PythonInformer - Image processing with pillow and NumPy
October 2, 2022 - The PIL function Image.fromarray function creates a PIL image from a NumPy array. If the NumPy array has the shape (height, width, 3) it will automatically create an RGB image. We can then use the PIL function save to save the image.
🌐
GitHub
gist.github.com › craimbert › 95498bb2c8c4a3dfd0ffd97f4bf232c8
Build an RGB image from a 1D list of RGB values · GitHub
Build an RGB image from a 1D list of RGB values. GitHub Gist: instantly share code, notes, and snippets.