¿Cómo convierto una imagen PIL en una matriz NumPy?

6 minutos de lectura

avatar de usuario
akdom

¿Cómo convierto un PIL? Image de ida y vuelta a una matriz NumPy para que pueda hacer transformaciones de píxeles más rápidas que las de PIL PixelAccess permite? Puedo convertirlo en una matriz NumPy a través de:

pic = Image.open("foo.jpg")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)

Pero, ¿cómo lo vuelvo a cargar en el PIL? Image después de haber modificado la matriz? pic.putdata() no está funcionando bien.

  • Tenga en cuenta que pic.size[0] y pic.size[1] debe ser intercambiado (es decir. reshape(pic.size[1], pic.size[0], 3)), ya que size es width x height o x * ymientras que el orden de la matriz es rows x columns.

    – nieblas

    21 de marzo de 2018 a las 15:16


avatar de usuario
dF.

No estás diciendo cómo exactamente putdata() no se está comportando. asumo que lo estas haciendo

>>> pic.putdata(a)
Traceback (most recent call last):
  File "...blablabla.../PIL/Image.py", line 1185, in putdata
    self.im.putdata(data, scale, offset)
SystemError: new style getargs format but argument is not a tuple

Esto es porque putdata espera una secuencia de tuplas y le estás dando una matriz numpy. Este

>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)

funcionará pero es muy lento.

A partir de PIL 1.1.6, el forma “adecuada” de convertir entre imágenes y matrices numpy es simple

>>> pix = numpy.array(pic)

aunque la matriz resultante tiene un formato diferente al suyo (matriz tridimensional o filas/columnas/rgb en este caso).

Luego, después de realizar los cambios en la matriz, debería poder hacer cualquiera de las dos pic.putdata(pix) o crear una nueva imagen con Image.fromarray(pix).

  • Esa página enumera numpy.asarray(pic) como la forma “adecuada” de convertir, no numpy.array(pic). Según esta respuesta array hará una copia mientras que asarray no lo hará (pero entonces el asarray el resultado será de solo lectura).

    – Arthur Taca

    30 de noviembre de 2016 a las 10:13

  • La segunda respuesta es mejor.

    – Nathan

    2 de junio de 2020 a las 17:42

avatar de usuario
endolito

Abierto I como una matriz:

>>> I = numpy.asarray(PIL.Image.open('test.jpg'))

hacer algunas cosas para Iluego, vuelva a convertirlo en una imagen:

>>> im = PIL.Image.fromarray(numpy.uint8(I))

Fuente: Filtrar imágenes numpy con FFT, Python

Si quiere hacerlo explícitamente por alguna razón, hay funciones pil2array() y array2pil() que usan getdata() en esta página en correlación.zip.

  • @ArditS.: ¿Usted import Image ¿primero? ¿Tienes PIL instalado?

    – endolito

    9 de noviembre de 2013 a las 17:04

  • Es el uint8 conversión necesaria?

    – Neil Traft

    16 de enero de 2014 a las 5:33


  • numpy.asarray(Image.open(filename)) parece funcionar para imágenes .jpg pero no para .png. El resultado se muestra como array(<PngImagePlugin.PngImageFile image mode=LA size=500x500 at 0x3468198>, dtype=object). No parece haber métodos obviamente nombrados de la PngImagePlugin.PngImageFile objeto para resolver esto. Supongo que debería hacer esto como una pregunta nueva, pero es muy relevante para este hilo. ¿Alguien entiende lo que está mal aquí?

    – jez

    1 de diciembre de 2015 a las 23:59


  • @Rebs: aquí está la razón por qué esto es mucho más rápido: getdata() devuelve una secuencia como objeto (almohada.readthedocs.io/en/3.4.x/reference/…), pero una imagen de almohada implementa el __array_interface__ cual numpy puede usar para acceder a los bytes sin procesar de una imagen sin tener que pasar por un iterador (ver github.com/python-pillow/Pillow/blob/… y docs.scipy.org/doc/numpy/reference/arrays.interface.html). Incluso puedes usar numpy.array(PIL.Image.open('test.jpg'))

    – tdp2110

    28 de julio de 2017 a las 17:34

  • @jez Verifique si el objeto Imagen está cerrado antes de convertirlo en numpy. A mí me pasó lo mismo y descubrí que cerré el objeto de la imagen en alguna parte.

    – Shaohua Li

    18 de agosto de 2018 a las 14:34

avatar de usuario
Daniel

Estoy usando Pillow 4.1.1 (el sucesor de PIL) en Python 3.5. La conversión entre Pillow y numpy es sencilla.

from PIL import Image
import numpy as np
im = Image.open('1.jpg')
im2arr = np.array(im) # im2arr.shape: height x width x channel
arr2im = Image.fromarray(im2arr)

Una cosa que debe notarse es que el estilo de almohada im es columna principal mientras que estilo numpy im2arr es fila mayor. Sin embargo, la función Image.fromarray ya lo tiene en cuenta. Eso es, arr2im.size == im.size y arr2im.mode == im.mode en el ejemplo anterior.

Debemos cuidar el formato de datos HxWxC al procesar las matrices numpy transformadas, por ejemplo, hacer la transformación im2arr = np.rollaxis(im2arr, 2, 0) o im2arr = np.transpose(im2arr, (2, 0, 1)) en formato CxHxW.

  • Este es el ejemplo más limpio, incluidas las declaraciones de importación (gracias por ese detalle). Votemos esta respuesta para aumentar la visibilidad.

    –David Parques

    7 de abril de 2018 a las 15:17

  • Descubrí que cuando convertí una imagen dibujada de PIL en una matriz numpy, al usar matplotlib imshow en la matriz, se mostraba al revés y requería un np.flipud arreglar. Aunque mi imagen PIL se creó desde cero usando ImageDraw.Draw. Creo que hay que tener cuidado de dónde viene el origen de sus coordenadas.

    – CMC Dragonkai

    13 de abril de 2018 a las 7:21

  • ¡¡Salud!! He estado buscando esta respuesta durante medio día. Resuelve mi problema de restaurar el eje original después de la imagen de la trama al original.

    – Campanita

    27 de junio de 2018 a las 10:21

Debe convertir su imagen en una matriz numpy de esta manera:

import numpy
import PIL

img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img) 

Convertir Numpy to PIL imagen y PIL to Numpy

import numpy as np
from PIL import Image

def pilToNumpy(img):
    return np.array(img)

def NumpyToPil(img):
    return Image.fromarray(img)

El ejemplo, lo he usado hoy:

import PIL
import numpy
from PIL import Image

def resize_image(numpy_array_image, new_height):
    # convert nympy array image to PIL.Image
    image = Image.fromarray(numpy.uint8(numpy_array_image))
    old_width = float(image.size[0])
    old_height = float(image.size[1])
    ratio = float( new_height / old_height)
    new_width = int(old_width * ratio)
    image = image.resize((new_width, new_height), PIL.Image.ANTIALIAS)
    # convert PIL.Image into nympy array back again
    return array(image)

Si su imagen está almacenada en un formato Blob (es decir, en una base de datos), puede usar la misma técnica explicada por Billal Begueradj para convertir su imagen de Blobs a una matriz de bytes.

En mi caso, necesitaba mis imágenes almacenadas en una columna blob en una tabla db:

def select_all_X_values(conn):
    cur = conn.cursor()
    cur.execute("SELECT ImageData from PiecesTable")    
    rows = cur.fetchall()    
    return rows

Luego creé una función auxiliar para cambiar mi conjunto de datos a np.array:

X_dataset = select_all_X_values(conn)
imagesList = convertToByteIO(np.array(X_dataset))

def convertToByteIO(imagesArray):
    """
    # Converts an array of images into an array of Bytes
    """
    imagesList = []

    for i in range(len(imagesArray)):  
        img = Image.open(BytesIO(imagesArray[i])).convert("RGB")
        imagesList.insert(i, np.array(img))

    return imagesList

Después de esto, pude usar byteArrays en mi red neuronal.

plt.imshow(imagesList[0])

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad