简体   繁体   中英

Converting from numpy arrays to a RGB image

I have three (241, 241) numpy arrays which I would like to treat as the Red, Green and Blue components of an image.

I have tried this:

import numpy as np
from PIL import Image

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

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

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

img.show()

But the resulting image just looks like noise:

在此处输入图片说明

Can anyone tell me what I am doing wrong please?

As an example, my red_arr is an array of floats that looks like this:

在此处输入图片说明

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')

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM