¿Cómo puedo guardar una imagen con PIL?

118

Acabo de hacer un procesamiento de imágenes usando la biblioteca de imágenes de Python (PIL) usando una publicación que encontré anteriormente para realizar transformaciones de Fourier de imágenes y no puedo hacer que la función de guardar funcione. Todo el código funciona bien, pero no guarda la imagen resultante:

from PIL import Image
import numpy as np

i = Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j = Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")

El error que obtengo es el siguiente:

save_handler = SAVE[string.upper(format)] # unknown format
    KeyError: '.BMP'

¿Cómo puedo guardar una imagen con Pythons PIL?

usuario1999274
fuente

Respuestas:

144

Se ha manejado el error con respecto a la extensión del archivo, puede usar BMP(sin el punto) o pasar el nombre de salida con la extensión ya. Ahora, para manejar el error, necesita modificar correctamente sus datos en el dominio de frecuencia para guardarlos como una imagen entera, PILle dice que no acepta datos flotantes para guardarlos como BMP.

Aquí hay una sugerencia (con otras modificaciones menores, como usar fftshifty en numpy.arraylugar de numpy.asarray) para realizar la conversión para una visualización adecuada:

import sys
import numpy
from PIL import Image

img = Image.open(sys.argv[1]).convert('L')

im = numpy.array(img)
fft_mag = numpy.abs(numpy.fft.fftshift(numpy.fft.fft2(im)))

visual = numpy.log(fft_mag)
visual = (visual - visual.min()) / (visual.max() - visual.min())

result = Image.fromarray((visual * 255).astype(numpy.uint8))
result.save('out.bmp')
mmgp
fuente
1
hola muchas gracias. ¡funciona perfecto ahora! ahora todo lo que tengo que hacer es entender todos los pasos, pero eso no será tan malo. muchas gracias por la ayuda
user1999274
@ user1999274 la principal diferencia está en el uso de en fft2lugar de, rfft2ya que para datos discretos no veo el sentido de usar la última. El resto es puramente cosmético, es decir, no podría visualizar correctamente la transformada de Fourier sin aplicarle un factor logarítmico. Entonces, la normalización es para mantener las cosas simples para la conversión al rango [0, 255].
mmgp
1
visual = (visual - visual.min()) / (visual.max() - visual.min())será predeterminado si visualno hay variación (poco probable, pero vale la pena detectarlo)
1
Intenté usar este código para mi problema, pero obtengo imágenes negras simples. ¿Alguien tiene alguna idea de esto? stackoverflow.com/questions/24266000/…
user961627
32

Debería poder simplemente dejar que PIL obtenga el tipo de archivo de la extensión, es decir, use:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
wim
fuente
1
Gracias por el aporte. sin embargo, cuando trato de permitir que la función de guardar obtenga el tipo de archivo como sugirió anteriormente, obtengo el siguiente error: IOError: no se puede escribir el modo F como BMP. ¿algún consejo?
user1999274
1
Sí, debería convertir la matriz a numpy.uint8dtype en lugar de flotar.
wim
6

Intente eliminar el .antes del .bmp(no coincide BMPcomo se esperaba). Como puede ver en el error, save_handlerestá en mayúsculas lo formatque proporcionó y luego está buscando una coincidencia en SAVE. Sin embargo, la clave correspondiente en ese objeto es BMP(en lugar de .BMP).

No sé mucho sobre PIL, pero por una búsqueda rápida, parece que es un problema con modela imagen. Cambiar la definición de ja:

j = Image.fromarray(b, mode='RGB')

Pareció funcionar para mí (sin embargo, tenga en cuenta que tengo muy poco conocimiento PIL, por lo que sugeriría usar la solución de @ mmgp ya que él / ella sabe claramente lo que están haciendo :)). Para los tipos de mode, utilicé esta página; con suerte, una de las opciones allí funcionará para usted.

CoheteBurro
fuente
Intenté eliminar el .bmp a favor del bmp y todavía no funcionó. el error que obtengo ahora es: IOError: no se puede escribir el modo F como BMP. Revisé las páginas de PIL en busca de documentación y me dijo que usara el .bmp, así que, en general, todavía no tengo idea de por qué no funciona.
user1999274
@ user1999274 Publicó una actualización que pareció funcionar para mí (disculpas por la falta de detalles, uniéndolo a medida que avanzo :)).
RocketDonkey
@RocketDonkey ha sido un poco más inteligente que eso, porque convertir los resultados de una transformada de Fourier en un espacio de color RGB dará una imagen sin sentido. El hecho de que ya no genere una excepción no significa que el resultado sea correcto.
mmgp
@mmgp De acuerdo, por eso hice +1 en el tuyo y espero que el OP lo acepte :)
RocketDonkey
4

Sé que esto es antiguo, pero descubrí que (mientras usaba Pillow) abrir el archivo usando open(fp, 'w')y luego guardar el archivo funcionará. P.ej:

with open(fp, 'w') as f:
    result.save(f)

fp siendo la ruta del archivo, por supuesto.

cuello
fuente
1
La documentación de Pillow dice que el formatparámetro debe usarse si se usa un objeto de archivo en save. ¿No es esto necesario?
Rob Rose
@RobRose durante mi prueba, cuando publiqué la respuesta, no encontré nada como eso necesario. Sin embargo, puede ser el caso ahora. Si alguna prueba que haga demuestra que es necesario, hágamelo saber y
editaré