Come posso salvare un'immagine con PIL?


119

Ho appena eseguito l'elaborazione delle immagini utilizzando la libreria di immagini Python (PIL) utilizzando un post che ho trovato in precedenza per eseguire trasformazioni di Fourier delle immagini e non riesco a far funzionare la funzione di salvataggio. L'intero codice funziona bene ma non salverà l'immagine risultante:

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

L'errore che ottengo è il seguente:

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

Come posso salvare un'immagine con Pythons PIL?

Risposte:


144

L'errore relativo all'estensione del file è stato gestito, si utilizza BMP(senza il punto) o si passa il nome dell'output già con l'estensione. Ora per gestire l'errore è necessario modificare correttamente i dati nel dominio della frequenza per essere salvati come immagine intera, ti PILsta dicendo che non accetta dati float da salvare come BMP.

Ecco un suggerimento (con altre modifiche minori, come usare fftshifte numpy.arrayinvece di numpy.asarray) per eseguire la conversione per una corretta visualizzazione:

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

1
hey grazie mille. funziona perfettamente ora! ora tutto quello che devo fare è capire tutti i passaggi ma non sarà poi così male. grazie mille per l'aiuto
user1999274

@ user1999274 la differenza principale è nell'uso di fft2invece di rfft2poiché per i dati discreti non vedo il punto nell'usare il successivo. Il resto è puramente cosmetico, cioè non saresti in grado di visualizzare correttamente la trasformata di Fourier senza applicarvi un fattore logaritmico. Quindi la normalizzazione consiste nel mantenere le cose semplici per la conversione nell'intervallo [0, 255].
mmgp

1
visual = (visual - visual.min()) / (visual.max() - visual.min())sarà predefinito se visualnon ha varianza (improbabile, ma vale la pena

1
Ho provato a utilizzare questo codice per il mio problema, ma ottengo semplici immagini nere. Qualcuno ha idea di questo? stackoverflow.com/questions/24266000/...
user961627

32

Dovresti essere in grado di consentire semplicemente a PIL di ottenere il tipo di file dall'estensione, ovvero utilizzare:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")

1
Grazie per l'input. tuttavia, quando provo a lasciare che la funzione di salvataggio ottenga il tipo di file come suggerito sopra, ottengo il seguente errore: IOError: impossibile scrivere la modalità F come BMP. qualche consiglio?
user1999274

1
Sì, dovresti convertire l'array in numpy.uint8dtype piuttosto che in float.
wim

6

Prova a rimuovere .prima di .bmp(non corrisponde BMPcome previsto). Come puoi vedere dall'errore, save_handlerè in maiuscolo quello che formathai fornito e quindi cerca una corrispondenza in SAVE. Tuttavia la chiave corrispondente in quell'oggetto è BMP(invece di .BMP).

Non ne so molto PIL, ma da una rapida ricerca in giro sembra che sia un problema con model'immagine. Modifica della definizione di jin:

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

Sembrava funzionare per me (tuttavia nota che ne ho pochissima conoscenza PIL, quindi suggerirei di usare la soluzione di @ mmgp poiché sa chiaramente cosa stanno facendo :)). Per i tipi di mode, ho usato questa pagina - spero che una delle scelte funzionerà per te.


Ho provato a rimuovere il .bmp a favore del bmp e ancora non funzionava. l'errore che ora ottengo è: IOError: impossibile scrivere la modalità F come BMP. Ho controllato le pagine PIL per la documentazione e diceva di usare .bmp quindi nel complesso non ho ancora idea del motivo per cui non funziona.
user1999274

@ user1999274 Ha pubblicato un aggiornamento che sembrava funzionare per me (mi scuso per la mancanza di dettagli - lo metto insieme man mano che procedo :)).
RocketDonkey

@RocketDonkey è stato un po 'più intelligente di così, perché la conversione dei risultati di una trasformata di Fourier in uno spazio colore RGB darà un'immagine priva di significato. Solo perché non solleva più un'eccezione, non significa che il risultato sia corretto.
mmgp

@mmgp Concordato - ecco perché ho fatto +1 sul tuo e spero che l'OP lo accetti :)
RocketDonkey

4

So che questo è vecchio, ma ho scoperto che (durante l'utilizzo di Pillow) l'apertura del file utilizzando open(fp, 'w')e quindi il salvataggio del file funzionerà. Per esempio:

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

fp essendo il percorso del file, ovviamente.


1
La documentazione di Pillow dice che il formatparametro dovrebbe essere utilizzato se viene utilizzato un oggetto file in save. Non è necessario?
Rob Rose

@ RobRose durante i miei test, quando ho postato la risposta, non ho trovato nulla del genere necessario. Tuttavia, potrebbe essere il caso ora. Se qualsiasi test lo dimostra necessario, fammelo sapere e modificherò la mia risposta
necko
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.