Wie kann ich ein Bild mit PIL speichern?

118

Ich habe gerade eine Bildverarbeitung mit der Python-Bildbibliothek (PIL) unter Verwendung eines Beitrags durchgeführt, den ich zuvor gefunden habe, um Fourier-Transformationen von Bildern durchzuführen, und ich kann die Speicherfunktion nicht zum Laufen bringen. Der gesamte Code funktioniert einwandfrei, aber das resultierende Bild wird nicht gespeichert:

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

Der Fehler, den ich bekomme, ist der folgende:

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

Wie kann ich ein Bild mit Pythons PIL speichern?

user1999274
quelle

Antworten:

143

Der Fehler bezüglich der Dateierweiterung wurde behoben. Sie verwenden entweder BMP(ohne Punkt) oder übergeben den Ausgabenamen bereits mit der Erweiterung. Um den Fehler zu beheben, müssen Sie Ihre Daten im Frequenzbereich ordnungsgemäß ändern, um sie als ganzzahliges Bild zu speichern.PIL Dies bedeutet, dass keine Float-Daten zum Speichern als BMP akzeptiert werden.

Hier ist ein Vorschlag (mit anderen geringfügigen Änderungen, wie z. B. Verwenden von fftshiftund numpy.arrayanstelle von numpy.asarray), um die Konvertierung für eine ordnungsgemäße Visualisierung durchzuführen:

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
quelle
1
Hey, vielen Dank. es funktioniert jetzt perfekt! Jetzt muss ich nur noch alle Schritte verstehen, aber das wird nicht so schlimm. Vielen Dank für die Hilfe
user1999274
@ user1999274 Der Hauptunterschied besteht in der Verwendung von fft2anstelle von, rfft2da ich für diskrete Daten keinen Sinn darin sehe, die späteren zu verwenden. Der Rest ist rein kosmetisch, dh Sie könnten die Fourier-Transformation nicht richtig visualisieren, ohne einen Log-Faktor darauf anzuwenden. Dann besteht die Normalisierung darin, die Umrechnung in den Bereich [0, 255] einfach zu halten.
mmgp
1
visual = (visual - visual.min()) / (visual.max() - visual.min())wird standardmäßig verwendet, wenn visualkeine Abweichung
1
Ich habe versucht, diesen Code für mein Problem zu verwenden, erhalte jedoch einfache schwarze Bilder. Hat jemand eine Idee dazu? stackoverflow.com/questions/24266000/…
user961627
32

Sie sollten in der Lage sein, PIL einfach den Dateityp von der Erweiterung abrufen zu lassen, dh verwenden Sie:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
wim
quelle
1
Danke für die Eingabe. Wenn ich jedoch versuche, die Speicherfunktion den oben vorgeschlagenen Dateityp abrufen zu lassen, wird der folgende Fehler angezeigt: IOError: Modus F kann nicht als BMP geschrieben werden. irgendein Rat?
user1999274
1
Ja, Sie sollten das Array in numpy.uint8dtype konvertieren und nicht in float.
wim
6

Versuchen Sie, das .vor dem zu entfernen .bmp(es stimmt nicht BMPwie erwartet überein). Wie Sie aus dem Fehler ersehen können, save_handlerist das obere Gehäuse das von formatIhnen bereitgestellte und sucht dann nach einer Übereinstimmung in SAVE. Der entsprechende Schlüssel in diesem Objekt ist jedoch BMP(anstelle von.BMP ).

Ich weiß nicht viel darüber PIL, aber nach einigem Suchen scheint es ein Problem mit modedem Bild zu sein. Ändern der Definition von jin:

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

Schien für mich zu funktionieren (beachten Sie jedoch, dass ich nur sehr wenig darüber PILweiß, daher würde ich vorschlagen, die Lösung von @ mmgp zu verwenden, da er / sie genau weiß, was sie tun :)). Für die Arten von habe modeich diese Seite verwendet - hoffentlich funktioniert eine der Auswahlmöglichkeiten für Sie.

RocketDonkey
quelle
Ich habe versucht, die .bmp zugunsten der bmp zu entfernen und die funktionierte immer noch nicht. Der Fehler, den ich jetzt bekomme, ist: IOError: Modus F kann nicht als BMP geschrieben werden. Ich habe die PIL-Seiten auf Dokumentation überprüft und es wurde gesagt, dass die .bmp verwendet werden soll, sodass ich insgesamt immer noch keine Ahnung habe, warum es nicht funktioniert.
user1999274
@ user1999274 Hat ein Update gepostet, das für mich zu funktionieren schien (entschuldige mich für den Mangel an Details - setze es zusammen, während ich weiter mache :)).
RocketDonkey
@RocketDonkey es ist ein bisschen schlauer als das, weil das Konvertieren der Ergebnisse einer Fourier-Transformation in einen RGB-Farbraum ein bedeutungsloses Bild ergibt. Nur weil keine Ausnahme mehr ausgelöst wird, bedeutet dies nicht, dass das Ergebnis korrekt ist.
mmgp
@mmgp Einverstanden - deshalb habe ich + 1 Ihre und hoffe, dass das OP es akzeptiert :)
RocketDonkey
4

Ich weiß, dass dies alt ist, aber ich habe festgestellt, dass (während der Verwendung von Pillow) das Öffnen der Datei mithilfe von open(fp, 'w')und das anschließende Speichern der Datei funktionieren. Z.B:

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

fp natürlich der Dateipfad.

necko
quelle
1
In der Dokumentation von Pillow heißt es, dass der formatParameter verwendet werden sollte, wenn ein Dateiobjekt in verwendet wird save. Ist das nicht nötig?
Rob Rose
@RobRose Während meiner Tests, als ich die Antwort veröffentlichte, fand ich so etwas nicht notwendig. Dies kann jedoch jetzt der Fall sein. Wenn irgendwelche Tests, die Sie durchführen, dies als notwendig erweisen, lassen Sie es mich wissen und ich werde meine Antwort bearbeiten
necko