以png格式保存图像的2个像素通道

时间:2017-11-24 10:40:58

标签: python scipy png

根据scipy文档,可以像这样保存图像的单个通道;

>>> x = np.zeros((255, 255))
>>> x = np.zeros((255, 255), dtype=np.uint8)
>>> x[:] = np.arange(255)
>>> imsave('/tmp/gradient.png', x)

图像的3个通道如下:

>>> rgb = np.zeros((255, 255, 3), dtype=np.uint8)
>>> rgb[..., 0] = np.arange(255)
>>> rgb[..., 1] = 55
>>> rgb[..., 2] = 1 - np.arange(255)
>>> imsave('/tmp/rgb_gradient.png', rgb)

但是,只能将图像的2个通道保存为png吗?我试图用2个频道模仿上面的代码,我遇到了以下错误:

ValueError: 'arr' does not have a suitable array shape for any mode.

2 个答案:

答案 0 :(得分:1)

我不清楚你想要达到什么目的或者你想要存储什么样的频道。

根据the PNG color options table here,只有一个选项:使用灰度+ alpha通道。当然,您可以存储您的数据,

  • 这意味着比特深度为16或32;也许不是你想要的
  • 库默认将其解释为Grayscale + alpha-channel

TIFF实际上更灵活,似乎支持arbritrary频道,根据to this libtiff不支持双频道。 (可能是过时的信息;不确定)。

所以这可能取决于你真正想做的事情。如果您只想存储2个通道(因为您想节省字节而不需要更多通道),可以根据需要调整管道中的每一步以解释它,我建议只存储3个通道,其中一个是空的(例如全零)。 PNG过滤器将能够有效地压缩它。当然,稍后阅读/使用这些内容时,您需要修改代码以将其解释为保存时已完成。

如果这只是针对某种涉及python的科学堆栈的任务,你可以使用numpy的savez_compressed存储你的数组。 (注释:会有通用压缩;但没有像x+1 - x这样的过滤器使用 - >像素:0,1,2,3难以压缩;但是使用delta-filter:0,1,1, 1易于压缩;意思是:压缩效率与PNG相比取决于您的图像)

答案 1 :(得分:1)

PNG文件格式支持具有两个通道的图像,其位深度为16或32位(每个通道)。 PNG将这样的文件解释为具有alpha(即透明度)通道的灰度图像。实际上,如果您正在尝试使用Alpha通道创建灰度图像,那么这个答案可能会对您有所帮助。如果您尝试使用PNG格式只存储数组,那么我建议使用不同的格式。请参阅@ sascha的答案以获取建议。

我写的numpngw modulesource code on github)可以用这种格式编写PNG文件。只需传入类型为np.uint16np.uint32且形状为(m, n, 2)的数组。

例如,

import numpy as np
from numpngw import write_png


# Create `img` with a black outer border, a white inner border and
# a transparent square in the middle.
img = np.full((64, 64, 2), fill_value=2**16-1, dtype=np.uint16)
img[16:-16, 16:-16, 1] = 0
img[:8, :, 0] = 0
img[-8:, :, 0] = 0
img[:, :8, 0] = 0
img[:, -8:, 0] = 0

write_png('foo.png', img)

您可能需要进行一些实验才能将此数据读回具有相同形状和数据类型的数组中。例如,Pillow读取此文件时的默认行为是返回一个形状为(m,n,4)的8位数组;也就是说,Pillow将数据转换为RGBA格式。