从numpy数组转换为RGB图像

3

我有三个(241, 241)的numpy数组,我想把它们作为一幅图像的红、绿和蓝颜色分量。

我已经尝试过以下方法:

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

但是产生的图像只是看起来像噪音: enter image description here 请问,有谁能告诉我哪里出了问题吗?
例如,我的red_arr是一个浮点数数组,看起来像这样: enter image description here

1
red_arr等是什么样子的? - Willem Van Onsem
red_arr是一个浮点数数组,范围大约为[-4000, 4000]。我已经在我的问题中更新了一个示例。 - jlt199
1
那么这是因为它需要环绕。 - Willem Van Onsem
请问您能否再详细解释一下? - jlt199
他们的意思是RGB图像的值必须在区间[0, 255]内,而不是[-4000, 4000],因此您需要对它们进行归一化处理。 - Graipher
2个回答

4

你的np数组应该具有uint8数据类型:

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

实际上,PIL会在arr的每个步幅上调用tobytes函数,如果它们是int类型,将生成额外的字节。

以下是针对不同数据类型执行以下代码的结果。

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

enter image description here

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

图片描述在此

正如其他人所建议的,如果您的原始输入不在范围(0,255)内,您也需要重新调整它们。


这并不能解决生成正确图像的问题:最多只是构建环绕值。 - Willem Van Onsem
我没有看到输入是什么,但我认为你仍然需要将其转换为'uint8'而不是'int'。否则,您仍将获得类似于原始图片的东西。 - Haochen Wu

4
在您的评论中,您指定red_arr等是范围为-4000到4000的数组。
但如果我们查看Image.from_array模式的规格说明,我们会看到它期望一个由三个字节组成的矩阵(值从零到255)。
然而,这并不一定是个问题:我们可以执行:
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')

首先,我们将数组重新缩放到0到255的范围内,然后将其传递给PIL。

有时候我们可能希望以相同的方式缩放红、绿和蓝三个通道。这种情况下,我们可以使用:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接