将16位numpy数组保存为16位PNG图像

4
我试图将一个16位的numpy数组保存为16位的PNG格式,但是我得到的只是一张黑色的图片。下面是一个最简单的例子。
im = np.random.randint(low=1, high=6536, size=65536).reshape(256,256) #sample numpy array to save as image
plt.imshow(im, cmap=plt.cm.gray)

enter image description here

给定上述的numpy数组,使用matplotlib我能看到这张图片,但是当我将这张图片保存为16位的png格式时,我得到了下面这张图片:

import imageio

imageio.imwrite('result.png', im)

图像已保存:

enter image description here

在图像中可以看到一些浅灰色斑点,但图像基本上是黑色的。无论如何,当我读回图像并再次使用matplotlib可视化时,我看到了相同的起始图像。我还尝试了其他库(如PIL或PyPNG)代替imageio,但结果相同。

我知道16位图像值的范围是0到65535,在这里的numpy数组中只有1到6536的值,但我需要保存类似于这样的numpy数组图像,即图像中表示的最大值不是最大可表示值。我认为保存过程中涉及某种归一化。我需要以matplotlib在其最大分辨率下看到它们的确切数组,并且没有压缩或缩小其值(因此除以255或转换为8位数组不适用)。


寻找未压缩格式,例如.tif。 像.jpg.png这样的格式总是会应用某种压缩。 - JacoSolari
@JacoSolari,PNG是一种无损格式,因此压缩不是问题。 - Warren Weckesser
2
@Aelius,请注意,matplotlib的imshow函数会在绘图时归一化颜色范围。如果要查看无符号16位整数的“真实”颜色比例尺,请使用plt.imshow(im, cmap=plt.cm.gray, vmin=0, vmax=65535) - Warren Weckesser
你说得对,沃伦!你知道是否有一种方法可以在将图像保存为PNG时,通过某种方式实现最大值的归一化吗?我需要将数组保存为在matpotlib中看到的样子。 - Aelius
1
你的示例值范围从1到6535。如果你想让16位灰度图像从黑色到白色有完整的范围,你需要将值缩放到[0, 65535]的范围内。但问题中给出的印象是你不想缩放这些值。如果在保存数据之前缩放数据可以接受,请查看我的更新答案。 - Warren Weckesser
1个回答

10

根据情况来看,如果在将PNG文件写入之前将数组的数据类型转换为numpy.uint16imageio.imwrite会处理正确:

imageio.imwrite('result.png', im.astype(np.uint16))

当我这样做时,result.png 是一个16位灰度PNG文件。
如果您希望图像具有从黑到白的完整灰度范围,则必须将值缩放到范围[0,65535]。例如,可以使用以下代码实现:
im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)

然后,您可以使用以下方式保存该数组:

imageio.imwrite('result2.png', im2)

要将 NumPy 数组写入 PNG 文件,一个替代方案是 numpngw(我创建的一个包)。例如:
from numpngw import write_png

im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)
write_png('result2.png', im2)

如果你已经在使用imageio,那么使用numpngw可能没有明显的优势。但是,它比imageio更轻量级 - 它仅依赖于NumPy(不依赖于PIL/Pillow和libpng)。

当我使用imageio.imwrite时,我收到消息"从uint16到uint8的有损转换。失去了8位的分辨率。在保存之前将图像转换为uint8以抑制此警告。" - undefined
对我来说,它仍然有效,使用的是numpy 1.26.1和imageio 2.31.6在Python 3.12.0中。你是否将图像保存为PNG文件?如果你再次确认你运行的代码与这里显示的代码相同,但仍然出现错误,你应该提出一个新的问题来解决。 - undefined
看了一下imageio的文档,似乎它可能会委托给一系列不同的库,而功能可能取决于安装了什么。无论如何,numpngw对我来说解决了问题,所以感谢你创建它! - undefined

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