无法从 PIL 保存的 PNG 图像中恢复相同的 numpy 数组
Can't recover the same numpy array from PIL-saved PNG image
我正在使用 PIL 将 Numpy 数组保存为 PNG 图像,但是当我读回它时,我没有得到相同的数组编号。
我保存了一张 PNG 图像,其中一个像素的值为 2^16,但是当我将其读回 Numpy 数组时,该像素的值为 2^16 - 1。
似乎位深度范围被限制为 2^16 -1 位,但文档说保存为 PNG,我可以使用 'I' 模式,它适用于 32 位有符号整数。
The mode of an image is a string which defines the type and depth of a
pixel in the image. Each pixel uses the full range of the bit depth.
So a 1-bit pixel has a range of 0-1, an 8-bit pixel has a range of
0-255 and so on. The current release supports the following standard
modes:
I
(32-bit signed integer pixels)
Pillow identifies, reads, and writes PNG files containing 1, L, LA, I, P, RGB or RGBA data.
可重现的例子:
import tempfile
from PIL import Image
import numpy as np
im_np = np.array([[1, 1], [1, 2**16]], dtype=np.int32)
im_pil = Image.fromarray(im_np, mode='I')
with tempfile.TemporaryFile() as f:
im_pil.save(f, 'PNG')
with Image.open(f) as im:
recovered_im_np = np.array(im)
print(f"Numpy array:\n{im_np}")
print(f"Numpy array receovered from PNG:\n {recovered_im_np}")
我明白了:
Numpy array:
[[ 1 1]
[ 1 65536]]
Numpy array receovered from PNG:
[[ 1 1]
[ 1 65535]]
Python版本:3.9.10 (main, Feb 17 2022, 18:15:00) \n[GCC 9.3.0]
PIL 版本:9.0.1
Numpy 版本:1.22.2
Pillow 可能支持 32 位有符号整数图像,但 png 不支持。 png 格式支持的每个像素的最大颜色深度为 16 位。我不确定它们在什么意义上意味着支持保存 I 模式图像。
您始终可以直接使用 numpy.save 保存 numpy 数组。
正如@mateusreis 正确指出的那样,.png
格式仅支持每像素 16 位灰度,因此您必须将该值转换为每像素 3x8 24 位 RGB 值,或者您应该保存采用支持每像素 32 位的图像格式,如 TIFF:
import tempfile
from PIL import Image
import numpy as np
im_np = np.array([[1, 1], [1, 2 ** 16]], dtype=np.int32)
im_pil = Image.fromarray(im_np, mode='I')
with tempfile.TemporaryFile() as f:
im_pil.save(f, 'TIFF')
with Image.open(f) as im:
recovered_im_np = np.array(im)
print(f"Numpy array:\n{im_np}")
print(f"Numpy array receovered from PNG:\n {recovered_im_np}")
结果:
Numpy array:
[[ 1 1]
[ 1 65536]]
Numpy array receovered from PNG:
[[ 1 1]
[ 1 65536]]
这里的关键是要意识到你进行了 2 次转换(双向):
- 1.)
numpy
数组 -> 2.) PIL
图片 -> 3.) 图片文件格式
您的 mode='I'
涵盖 1 -> 2,但您需要选择正确的格式以保留 2 -> 3 的数据。
我正在使用 PIL 将 Numpy 数组保存为 PNG 图像,但是当我读回它时,我没有得到相同的数组编号。
我保存了一张 PNG 图像,其中一个像素的值为 2^16,但是当我将其读回 Numpy 数组时,该像素的值为 2^16 - 1。
似乎位深度范围被限制为 2^16 -1 位,但文档说保存为 PNG,我可以使用 'I' 模式,它适用于 32 位有符号整数。
The mode of an image is a string which defines the type and depth of a pixel in the image. Each pixel uses the full range of the bit depth. So a 1-bit pixel has a range of 0-1, an 8-bit pixel has a range of 0-255 and so on. The current release supports the following standard modes:
I
(32-bit signed integer pixels)
Pillow identifies, reads, and writes PNG files containing 1, L, LA, I, P, RGB or RGBA data.
可重现的例子:
import tempfile
from PIL import Image
import numpy as np
im_np = np.array([[1, 1], [1, 2**16]], dtype=np.int32)
im_pil = Image.fromarray(im_np, mode='I')
with tempfile.TemporaryFile() as f:
im_pil.save(f, 'PNG')
with Image.open(f) as im:
recovered_im_np = np.array(im)
print(f"Numpy array:\n{im_np}")
print(f"Numpy array receovered from PNG:\n {recovered_im_np}")
我明白了:
Numpy array:
[[ 1 1]
[ 1 65536]]
Numpy array receovered from PNG:
[[ 1 1]
[ 1 65535]]
Python版本:3.9.10 (main, Feb 17 2022, 18:15:00) \n[GCC 9.3.0]
PIL 版本:9.0.1
Numpy 版本:1.22.2
Pillow 可能支持 32 位有符号整数图像,但 png 不支持。 png 格式支持的每个像素的最大颜色深度为 16 位。我不确定它们在什么意义上意味着支持保存 I 模式图像。
您始终可以直接使用 numpy.save 保存 numpy 数组。
正如@mateusreis 正确指出的那样,.png
格式仅支持每像素 16 位灰度,因此您必须将该值转换为每像素 3x8 24 位 RGB 值,或者您应该保存采用支持每像素 32 位的图像格式,如 TIFF:
import tempfile
from PIL import Image
import numpy as np
im_np = np.array([[1, 1], [1, 2 ** 16]], dtype=np.int32)
im_pil = Image.fromarray(im_np, mode='I')
with tempfile.TemporaryFile() as f:
im_pil.save(f, 'TIFF')
with Image.open(f) as im:
recovered_im_np = np.array(im)
print(f"Numpy array:\n{im_np}")
print(f"Numpy array receovered from PNG:\n {recovered_im_np}")
结果:
Numpy array:
[[ 1 1]
[ 1 65536]]
Numpy array receovered from PNG:
[[ 1 1]
[ 1 65536]]
这里的关键是要意识到你进行了 2 次转换(双向):
- 1.)
numpy
数组 -> 2.)PIL
图片 -> 3.) 图片文件格式
您的 mode='I'
涵盖 1 -> 2,但您需要选择正确的格式以保留 2 -> 3 的数据。