De acuerdo con https://pillow.readthedocs.io/en /3.1.x/handbook/concepts.html#concept-modes,

  1. ¿Cuál es la diferencia entre ellos?
  2. ¿Podemos convertirnos de uno a otro?
  3. ¿Cuáles son los ejemplos de imagen para ambos modos?
20
bigchaipat 13 sep. 2018 a las 08:40

3 respuestas

La mejor respuesta
  • Normalmente, las imágenes son RGB, lo que significa que tienen 3 canales, uno para el rojo, uno para el verde y otro para el azul. Eso normalmente significa que cada píxel ocupa 3 bytes de almacenamiento, uno para el rojo, uno para el verde y otro para el azul.

  • Si tiene una imagen en modo P, eso significa que está paletizada. Eso significa que hay una paleta con hasta 256 colores diferentes, y en lugar de almacenar 3 bytes para R, G y B para cada píxel, almacena 1 byte, que es el índice en la paleta. Esto confiere ventajas y desventajas. La ventaja es que su imagen requiere 1/3 del espacio en la memoria y en el disco. La desventaja es que solo puede representar 256 colores únicos, por lo que puede obtener bandas o artefactos.

  • Si tiene una imagen en modo L, eso significa que es una imagen de un solo canal, normalmente interpretada como escala de grises. La L significa que solo almacena la Luminancia. Es muy compacto, pero solo almacena una escala de grises, no un color.

Usted convierte entre ellos usando la función convert(mode), p. para ir al modo RGB, use:

image.convert('RGB')

¡Utilicé bastante la palabra "normalmente" ! ¿Por qué? ¡Porque puedes hacer cosas anormales!

  • Puede almacenar una imagen de aspecto gris en formato RGB. Todo lo que debe hacer es hacer que el componente rojo sea igual al componente verde igual al componente azul (R = G = B) y aparecerá gris pero se almacenará en un formato RGB ineficiente que ocupa 3 veces el espacio que de otro modo podría necesitar.

  • Puede almacenar una imagen de aspecto gris en formato P, solo asegúrese de que todas las entradas de la paleta tengan R = G = B.


Aquí está el truco ... si quieres y esperas una imagen RGB, solo debes convertir a RGB al abrir:

im = Image.open("image.jpg").convert('RGB')

De esa manera nunca tendrá problemas con los archivos GIF (que siempre están paletizados) ni con los archivos PNG que pueden paletizarse y pueden ser en escala de grises o RGB. Normalmente no tendrá problemas con las imágenes JPEG porque de todos modos son casi siempre RGB.


Aquí hay un ejemplo para demostrar. Comience con esta imagen de degradado rojo-azul:

enter image description here

Usemos IPython para mirar en el espacio RGB. Primero, mira el canal rojo:

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)

Observe que tiene 255 en la parte superior porque es rojo y 0 en la parte inferior porque no hay rojo allí.

Ahora veamos el canal Verde, es 0 en todas partes porque no hay verde.

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)

Y finalmente, echemos un vistazo al canal azul. Es 0 en la parte superior donde la imagen es rojo puro y 255 en la parte inferior donde la imagen es azul puro.

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)

Ahora veamos la misma imagen en modo paleta.

# 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

Ahora ingrese los índices en la paleta:

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)

Ahora puede ver que la fila superior de la imagen tiene el índice de paleta 15, que, si lo busca en la paleta anterior, verá que es Rojo.

Ahora veamos la misma imagen en modo L: recuerde que L significa "Luminancia" , que es solo una forma elegante de decir "brillo" en una escala de negro a blanco, es decir, escala de grises:

# 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)

Entonces, ahora la fila superior de la imagen es 76 y la fila inferior es 29. ¿Cuáles son esos? Bueno, la fórmula para convertir RGB a L es:

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

Entonces, en la fila superior, R = 255, G = 0, B = 0, entonces la Luminancia se ha convertido en:

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

Y en la fila inferior, R = 0, G = 0, B = 255, entonces la Luminancia se ha convertido en:

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

Palabras clave : Python, PIL, Pillow, paleta, procesamiento de imágenes, prime.

31
Mark Setchell 2 feb. 2020 a las 19:40

El modo "L" se asigna a píxeles en blanco y negro (y en el medio). El modo "P" se asigna con una paleta de colores. Puede convertir la imagen a uno de estos modos.

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

5
cemsazara 13 sep. 2018 a las 06:38

El modo "L" representa la escala de grises aquí ... Por lo tanto, puede contener cualquiera de los 256 tonos de gris (incluye blanco y negro como tonos de gris).

El modo "P" puede contener 256 colores diferentes como rojo, azul, verde, etc.

Conversión entre sí, si quiere decir convertir imágenes de escala de grises a color o viceversa ... Sí, es posible ...

Ejemplos: la imagen en blanco y negro de 8 bits (técnicamente imagen en escala de grises) es "L" y cualquier imagen en color de 8 bits es modo "P".

3
Pavan Chandaka 13 sep. 2018 a las 06:19