【问题标题】:Saving Numpy Array as Lab Image via PIL通过 PIL 将 Numpy 数组保存为实验室图像
【发布时间】:2019-11-22 20:33:45
【问题描述】:

大家好!

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

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

第一个张量 net_input 的值从 -1 到 1。第二个张量 output 的值从 0 到 1。

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

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

原文:。灰度:

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 后,输出看起来有点不同:

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

【问题讨论】:

  • 不太确定您的输入和输出是什么 - 也许您可以对 Lab 中的每一个说它们一开始是什么范围/类型以及什么最后你期望的范围?我认为你在使用 PIL 时会遇到问题,因为它只喜欢 8 位图像pillow.readthedocs.io/en/3.1.x/handbook/… 也许你可以提供一些生成虚拟数据的代码以及它应该是什么样子的一些指示。
  • @MarkSetchell,感谢您的回复!我在显示这些频道的地方进行了编辑。你宁愿使用 cv2 还是其他东西?如果是这样,您能否提供一些基本代码,展示如何从 numpy 数组中获取 Lab-image?
  • 我们可以从一些每个人都可以生成和使用的简单数据开始,而不是pytorch吗?我们如何让a 只是一个简单的左右黑白渐变a = np.linspace(0,1,225) + np.zeros((225,1))b 完全相同但旋转了90 度,所以它从下到上运行b = a.rot90()L 只是一个像这样的常数0.5 L = np.zeros_like(a) + 0.5 这是否代表了您所拥有的以及将产生您可以使用的实验室图像?

标签: python numpy python-imaging-library pytorch


【解决方案1】:

如果您使用 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。

【讨论】:

  • 谢谢!这实际上对调整范围非常有帮助。你也知道我可以摆脱这种模式吗?
  • 我把新的输出放在原帖中
  • 所以你认为,奇怪模式的起源是interp1d() 函数?
  • 模式仍然存在
  • @Stefan 你能在没有interp1d 的情况下使用@MarkSetchell 建议包含你的sn-p 吗?
猜你喜欢
  • 1970-01-01
  • 2017-06-25
  • 2010-10-28
  • 2020-02-17
  • 2019-06-04
  • 2015-02-20
  • 2010-09-27
  • 2011-10-18
相关资源
最近更新 更多