python - 通过 PIL 将 Numpy 数组保存为实验室图像

标签 python numpy python-imaging-library pytorch

大家好!

我正在编写一个函数,它获取两个 Pytorch-Tensors 作为输入并将两个张量的部分合并到一个新数组,该数组将转换为 Lab-image之后。

net_input 是具有 3 个 channel (L、a、b)的张量,output 是具有 2 个 channel (a、b)的张量。 现在,我想从 net_input 获取 L channel ,从 output 获取 a channel ​​和 b channel 。

第一个张量 net_input 的值介于 -1 到 1 之间。第二个张量 output 的值介于 0 - 1 之间。

因此,它们都必须映射到从 -128 到 127 的值。我这样做是使用 interp1d

显然保存的图像有一些不需要的图案并且不正确。

原创:original .灰度:grayscale

from PIL import Image as pil
import numpy as np
from PIL import Image
from scipy.interpolate import interp1d
from datetime import datetime

def output_to_image(net_input, output, index):
    # net_input.size()  -->     torch.Size([1, 3, 225, 225]) # l, a, b channel
    # output.size()     -->     torch.Size([1, 2, 225, 225]) # a, b channel

    # A - B - Channel
    map_a_b = interp1d([0.0, 1.0], [-128, 127])

    # L-Channel
    map_l = interp1d([-1.0, 1.0], [-128, 127])

    height = output.size()[2]
    width = output.size()[3]

    l = net_input.detach().numpy()[0][0]    # l channel
    a = output.detach().numpy()[0][0]   # a channel
    b = output.detach().numpy()[0][1]   # b channel

    # pdb.set_trace()

    img_arr = np.empty([height, width, 3])  # lab img array
    l_arr = np.empty([height, width])   # grayscale img array

    for h in range(0, height-1):
        for w in range(0, width-1):
            img_arr[h][w] = [map_l(l[h][w]), map_a_b(a[h][w]), map_a_b(b[h][w])]
            l_arr[h][w] = map_l(l[h][w])

    now = datetime.now()

    img = Image.fromarray(img_arr, "LAB")
    img.save(f"../images/output/{now.strftime('%d-%m-%Y %H:%M:%S')}-lab-img{index}.tiff")

    gray = Image.fromarray(l_arr, "L")
    gray.save(f"../images/output/{now.strftime('%d-%m-%Y %H:%M:%S')}-gray-img{index}.jpg")

这是 L、a 和 b 的样子:

(Pdb) >? print(l)
[[-1. -1. -1. ... -1. -1. -1.]
 [-1. -1. -1. ... -1. -1. -1.]
 [-1. -1. -1. ... -1. -1. -1.]
 ...
 [-1. -1. -1. ... -1. -1. -1.]
 [-1. -1. -1. ... -1. -1. -1.]
 [-1. -1. -1. ... -1. -1. -1.]]
(Pdb) >? print(a)
[[0.51877767 0.5208904  0.5310791  ... 0.5340722  0.51334995 0.522657  ]
 [0.5142181  0.50250506 0.5197009  ... 0.51169556 0.5332947  0.5155644 ]
 [0.53288984 0.51795006 0.5224927  ... 0.51704454 0.53655064 0.50311136]
 ...
 [0.5270468  0.5071506  0.52318716 ... 0.5217321  0.53424454 0.5011423 ]
 [0.5216123  0.53247094 0.5254119  ... 0.53089285 0.5259453  0.532716  ]
 [0.53135234 0.5184961  0.51334924 ... 0.5131047  0.51930845 0.51474   ]]
(Pdb) >? print(b)
[[0.4812223  0.47910962 0.46892092 ... 0.46592775 0.48665005 0.47734302]
 [0.48578197 0.49749494 0.4802992  ... 0.4883045  0.46670532 0.48443565]
 [0.46711013 0.48204994 0.47750723 ... 0.4829555  0.46344927 0.4968886 ]
 ...
 [0.47295317 0.49284932 0.47681284 ... 0.47826794 0.46575552 0.49885774]
 [0.47838774 0.46752912 0.47458804 ... 0.46910718 0.47405463 0.46728405]
 [0.46864766 0.48150396 0.48665074 ... 0.48689532 0.48069155 0.48526   ]]
(Pdb) 

编辑:

按照 Mark 的建议,将插值范围调整为 0..255 后,输出看起来有点不同:

new_output

import numpy as np
from PIL import Image
from datetime import datetime


def output_to_image(net_input, output, index):
    # net_input.size()  -->     torch.Size([1, 3, 225, 225])
    # output.size()     -->     torch.Size([1, 3, 225, 225])

    height = output.size()[2]
    width = output.size()[3]

    l = net_input.detach().numpy()[0][0]    # l channel
    a = output.detach().numpy()[0][0]   # a channel
    b = output.detach().numpy()[0][1]   # b channel

    #pdb.set_trace()

    img_arr = np.empty([height, width, 3])  # lab img array
    l_arr = np.empty([height, width])   # grayscale img array

    for h in range(0, height-1):
        for w in range(0, width-1):
            img_arr[h][w] = [map_l(l[h][w]), map_a_b(a[h][w]), map_a_b(b[h][w])]
            l_arr[h][w] = map_l(l[h][w])

    now = datetime.now()

    img = Image.fromarray(img_arr, "LAB")
    img.save(f"../images/output/{now.strftime('%d-%m-%Y %H:%M:%S')}-lab-img{index}.tiff")

    gray = Image.fromarray(l_arr, "L")
    gray.save(f"../images/output/{now.strftime('%d-%m-%Y %H:%M:%S')}-gray-img{index}.jpg")


def map_l(x):
    return (x+1)*127


def map_a_b(x):
    return x*127

最佳答案

如果您使用 PIL 执行此操作:

im = Image.new('LAB',(80,80),color=(255,0,0)).save('a.tif') 

您将获得与使用 this colour converter 相同的青色并放入

L/a/b = 100/-128/-128

如果你这样做:

im = Image.new('LAB',(80,80),color=(255,255,0)).save('a.tif') 

你会发现对应

L/a/b=100/128/-128

在在线转换器上。


如果你这样做:

im = Image.new('LAB',(80,80),color=(255,255,255)).save('a.tif')

你会发现对应

L/a/b=100/128/128

在在线转换器上。

因此,我认为如果使用 PIL,您的目标限制是错误的。 Lab 的范围都应为 0..255。


关于缩放,我根本不会使用 interp1d()。如果我需要将范围 -1..1 缩放到范围 0..255,我会加 1 到范围 0..2,然后乘以 255/2。

关于python - 通过 PIL 将 Numpy 数组保存为实验室图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58892179/

相关文章:

python - 如何在不使用 numpy/pandas 的情况下处理 csv 文件中的缺失数据?

Python:在默认图像查看器中打开多个图像

python - 在 Ubuntu 上安装 Python 镜像库 (PIL)

python - 所有成员包/模块都定义了吗?

python - 由于系统 Python 2.7 的要求,Pygame 安装失败,即使我有 Python 2.7

python - 在二维数组上使用贝叶斯统计分析进行音频过滤的笨拙建议

python - 格式化图像数据以预测 MNIST 数据模型图像中的数字

python-3.x - 如何使用 PIL 或类似的东西用 yuv420 格式数据写入图像

python - Spark : Warning that task size is too large despite no large, 非分布式文件

python - 无法访问 docker 容器中的 flask 应用程序