PIL的“ P”和“ L”模式下的图像有什么区别?

时间:2018-09-13 05:40:56

标签: python python-imaging-library

根据https://pillow.readthedocs.io/en/3.1.x/handbook/concepts.html#concept-modes

  1. 它们之间有什么区别?
  2. 我们可以从一个转换为另一个吗?
  3. 两种模式下的图像示例都是什么?

3 个答案:

答案 0 :(得分:11)

  • 通常,图像是RGB,这意味着它们具有3个通道,一个用于红色,一个用于绿色,一个用于蓝色。通常,这意味着每个像素占用3个字节的存储空间,一个存储红色,一个存储绿色,一个存储蓝色。

  • 如果您有P模式图像,则表示它已调色板化。这意味着其中有一个调色板,其中最多包含256种不同的颜色,而不是为每个像素分别为R,G和B存储3个字节,而是存储1个字节(这是调色板的索引)。这同时具有优点和缺点。好处是您的映像需要内存和磁盘上1/3的空间。缺点是它只能代表256种独特的颜色-因此您可能会出现条纹或伪像。

  • 如果具有L模式图像,则表示它是单通道图像-通常解释为灰度。 L表示仅存储亮度。它非常紧凑,但是只存储灰度而不是颜色。

您可以使用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。


这是一个示例进行演示。从此红蓝色渐变图像开始:

enter image description here

让我们使用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)

最后,让我们看一下Blue频道。在图像为纯红色的顶部为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的公式是:

  

L = R * 299/1000 + G * 587/1000 + B * 114/1000

因此,在第一行中,R = 255,G = 0,B = 0,所以亮度变为:

L = 255 * 299/100 + 0 + 0 
L = 76

在最底行,R = 0,G = 0,B = 255,因此亮度变为:

L = 0 + 0 + 255 * 114/100
L = 29

答案 1 :(得分:4)

“ 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()

enter image description here

答案 2 :(得分:2)

“ L”模式在这里代表灰度。...因此它可以容纳256个灰度阴影中的任何一个(包括黑白作为灰度阴影)。

“ P”模式可以容纳256种不同的颜色,例如红色,蓝色,绿色等。

彼此转换,如果您的意思是将图像从灰度转换为彩色,反之亦然。...是的,这是可能的。...

示例:8位黑白图像(技术上为灰度图像)为“ L”,任何8位彩色图像为“ P”模式。