【问题标题】:Converting from numpy arrays to a RGB image从 numpy 数组转换为 RGB 图像
【发布时间】:2018-02-01 20:48:20
【问题描述】:

我有三个 (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()

但生成的图像看起来像噪点:

谁能告诉我我做错了什么?

例如,我的 red_arr 是一个浮点数组,看起来像这样:

【问题讨论】:

  • red_arr等长什么样子?
  • red_arr 是一个浮点数组,范围约为 [-4000, 4000],我已经用一个示例更新了我的问题
  • 那就是回绕了。
  • 请您解释一下吗?
  • 这意味着RGB图像的值必须在[0, 255]的区间内,而不是[-4000, 4000],所以你需要对它们进行归一化。

标签: python numpy python-imaging-library


【解决方案1】:

在您的评论中,您指定 red_arr 等是 -4000 到 4000 范围内的数组。

但如果我们看一下Image.from_array modes 的规范,就会发现它需要一个由三个字节(值从零到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')

【讨论】:

    【解决方案2】:

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

    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) 内,您也需要重新调整它们。

    【讨论】:

    • 这不会解决生成正确图像的问题:充其量只是构造环绕值。
    • 我没有看到输入是什么,但我认为您仍然需要转换为 'uint8' 而不是 'int'。否则你仍然会得到类似于原始图片的东西。
    猜你喜欢
    • 2018-08-22
    • 2018-09-28
    • 2011-12-07
    • 2021-04-02
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    相关资源
    最近更新 更多