PIL 中“P”模式和“L”模式的图像有什么区别?
- 2024-12-03 08:44:00
- admin 原创
- 294
问题描述:
根据https://pillow.readthedocs.io/en/3.1.x/handbook/concepts.html#concept-modes,
它们之间有什么区别?
我们可以从一种转换为另一种吗?
两种模式的图像示例有哪些?
解决方案 1:
通常情况下,图像是 RGB 格式的,也就是说图像有 3 个通道,一个用于红色,一个用于绿色,一个用于蓝色。这通常意味着每个像素占用 3 个字节的存储空间,一个用于红色,一个用于绿色,一个用于蓝色。
如果您有
P
模式图像,则意味着它是调色板化的。这意味着调色板中最多有 256 种不同的颜色,并且不是为每个像素存储 3 个字节的 R、G 和 B,而是存储 1 个字节,即调色板的索引。这既有优点也有缺点。优点是您的图像需要内存和磁盘空间的 1/3。缺点是它只能表示 256 种独特的颜色 - 因此您可能会得到带状或伪影。如果您有
L
模式图像,则意味着它是单通道图像 - 通常解释为灰度。这L
意味着它只存储亮度。它非常紧凑,但只存储灰度,而不是颜色。
您可以通过查看以下内容判断图像属于哪种模式:
image.mode
如果您的图像是调色板图像,则它将是P
,或者PA
如果图像是调色板图像并且带有 alpha 通道,则它将是 。如果您的图像是灰度图像,则它将是L
,或者LA
如果图像是带有 alpha 通道的灰度图像,则它将是 。
您可以使用convert(mode)函数在它们之间进行转换,例如要转到 RGB 模式,请使用:
image.convert('RGB')
我经常用“正常”这个词!为什么?因为你可以做不正常的事情!
您可以将灰色图像存储为 RGB 格式。您只需将红色分量等于绿色分量,蓝色分量等于蓝色分量 (R=G=B),图像就会显示为灰色,但会以低效的 RGB 格式存储,占用 3 倍于其他格式所需的空间。
您可以以 P 格式存储灰色图像,只需确保所有调色板条目都具有 R=G=B。
关键在于...如果您想要并期望获得 RGB 图像,那么您应该在打开时将其转换为 RGB:
im = Image.open("image.jpg").convert('RGB')
这样,您就永远不会遇到 GIF 文件(始终为调色板)的问题,也不会遇到 PNG 文件(可以调色板化并且可以为灰度或 RGB)的问题。您通常不会遇到 JPEG 图像的问题,因为它们几乎始终为 RGB。
下面是一个示例来演示。从这张红蓝渐变图像开始:
让我们IPython
在 RGB 空间中看一下。首先,查看红色通道:
In [21]: im = Image.open('a.png').convert('RGB')
In [22]: np.array(im.getchannel(0))
Out[22]:
array([[255, 255, 255, ..., 255, 255, 255],
[255, 255, 255, ..., 255, 255, 255],
[254, 254, 254, ..., 254, 254, 254],
...,
[ 1, 1, 1, ..., 1, 1, 1],
[ 0, 0, 0, ..., 0, 0, 0],
[ 0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
请注意,它的顶部为 255,因为它是红色,而底部为 0,因为那里没有红色。
现在让我们看看绿色通道,由于没有绿色,所以它在任何地方都是 0。
In [23]: np.array(im.getchannel(1))
Out[23]:
array([[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
最后,让我们看看蓝色通道。顶部为 0,表示图像为纯红色;底部为 255,表示图像为纯蓝色。
In [24]: np.array(im.getchannel(2))
Out[24]:
array([[ 0, 0, 0, ..., 0, 0, 0],
[ 0, 0, 0, ..., 0, 0, 0],
[ 1, 1, 1, ..., 1, 1, 1],
...,
[254, 254, 254, ..., 254, 254, 254],
[255, 255, 255, ..., 255, 255, 255],
[255, 255, 255, ..., 255, 255, 255]], dtype=uint8)
现在让我们在调色板模式下看一下同一幅图像。
# Convert to palette mode
im = Image.open('a.png').convert('P')
# Extract the palette and reshape as 256 entries of 3 RGB bytes each
In [27]: np.array(im.getpalette()).reshape(256,3)
Out[27]:
array([[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 51, 0, 0],
[102, 0, 0],
[153, 0, 0],
[204, 0, 0],
[255, 0, 0], <--- entry 15 = rgb(255,0,0) = Red
[ 0, 51, 0],
[ 51, 51, 0],
[102, 51, 0],
[153, 51, 0],
[204, 51, 0],
[255, 51, 0],
[ 0, 102, 0],
[ 51, 102, 0],
[102, 102, 0],
[153, 102, 0],
[204, 102, 0],
[255, 102, 0],
[ 0, 153, 0],
[ 51, 153, 0],
[102, 153, 0],
[153, 153, 0],
[204, 153, 0],
[255, 153, 0],
[ 0, 204, 0],
[ 51, 204, 0],
[102, 204, 0],
[153, 204, 0],
[204, 204, 0],
[255, 204, 0],
[ 0, 255, 0],
[ 51, 255, 0],
[102, 255, 0],
[153, 255, 0],
[204, 255, 0],
[255, 255, 0],
...
... up to 256 entries
现在将索引放入调色板:
In [28]: np.array(im.getchannel(0))
Out[28]:
array([[ 15, 15, 15, ..., 15, 15, 15],
[ 15, 15, 15, ..., 15, 15, 15],
[ 15, 15, 15, ..., 15, 15, 15],
...,
[190, 190, 190, ..., 190, 190, 190],
[190, 190, 190, ..., 190, 190, 190],
[190, 190, 190, ..., 190, 190, 190]], dtype=uint8)
现在您可以看到图像的顶行有调色板索引 15,如果您在前面的调色板中查找,您将看到是红色。
现在让我们看一下 L 模式下的同一图像 - 记住 L 表示“亮度”,这只是在从黑到白的范围内表示“亮度”的一种奇特方式,即灰度:
# Open into greyscale, or L mode
In [1]: im = Image.open('a.png').convert('L')
# Dump the pixels
In [2]: np.array(im.getchannel(0))
Out[2]:
array([[76, 76, 76, ..., 76, 76, 76],
[76, 76, 76, ..., 76, 76, 76],
[76, 76, 76, ..., 76, 76, 76],
...,
[29, 29, 29, ..., 29, 29, 29],
[29, 29, 29, ..., 29, 29, 29],
[29, 29, 29, ..., 29, 29, 29]], dtype=uint8)
那么,现在图像的顶行是 76,底行是 29。它们是什么?那么,将 RGB 转换为 L 的公式是:
左 = 右 299/1000 + 右 587/1000 + 左 * 114/1000
因此,在最上面一行,R=255、G=0、B=0,所以亮度变成:
L = 255 * 299/1000 + 0 + 0
L = 76
下面一行,R=0,G=0,B=255,所以亮度变成:
L = 0 + 0 + 255 * 114/1000
L = 29
关键词:Python、PIL、Pillow、调色板、图像处理、prime。
解决方案 2:
“L”模式映射到黑白像素(以及两者之间)。“P”模式映射调色板。您可以将图像转换为这些模式之一。
from PIL import Image
im = Image.open("im.jpg")
im_l = im.convert('L')
im_p = im.convert('P')
im.show()
im_l.show()
im_p.show()
解决方案 3:
这里的“L”模式代表灰度......所以它可以保存 256 种灰色中的任意一种(包括黑色和白色作为灰色)。
“P”模式可以容纳 256 种不同的颜色,如红色、蓝色、绿色等……
从一个转换到另一个,如果您的意思是将图像从灰度转换为彩色或反之亦然......是的,这是可能的......
示例:8 位黑白图像(技术上称为灰度图像)为“L”,任何 8 位彩色图像为“P”模式。