Jak mogę zapisać obraz za pomocą PIL?

119

Właśnie wykonałem trochę przetwarzania obrazu przy użyciu biblioteki obrazów Python (PIL), korzystając z postu, który znalazłem wcześniej, aby wykonać transformacje Fouriera obrazów i nie mogę uruchomić funkcji zapisywania. Cały kod działa dobrze, ale po prostu nie zapisze wynikowego obrazu:

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

Otrzymuję następujący błąd:

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

Jak mogę zapisać obraz za pomocą Pythons PIL?

user1999274
źródło

Odpowiedzi:

144

Błąd dotyczący rozszerzenia pliku został rozwiązany, albo użyj BMP(bez kropki), albo już przekazujesz nazwę wyjściową z rozszerzeniem. Teraz, aby poradzić sobie z błędem, musisz odpowiednio zmodyfikować dane w dziedzinie częstotliwości, aby zostały zapisane jako obraz całkowity, PILinformuje, że nie akceptuje danych zmiennoprzecinkowych do zapisania jako BMP.

Oto sugestia (z innymi drobnymi modyfikacjami, takimi jak użycie fftshifti numpy.arrayzamiast numpy.asarray), aby wykonać konwersję w celu właściwej wizualizacji:

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
źródło
1
hej, bardzo dziękuję. teraz działa idealnie! teraz wszystko, co muszę zrobić, to zrozumieć wszystkie kroki, ale to nie będzie takie złe. bardzo dziękuję za pomoc
user1999274
@ user1999274 główna różnica polega na używaniu fft2zamiast, rfft2ponieważ w przypadku danych dyskretnych nie widzę sensu używania późniejszego. Reszta jest czysto kosmetyczna, tj. Nie byłbyś w stanie poprawnie zwizualizować transformaty Fouriera bez zastosowania do niej współczynnika logarytmicznego. Następnie normalizacja polega na uproszczeniu konwersji do zakresu [0, 255].
mmgp,
1
visual = (visual - visual.min()) / (visual.max() - visual.min())domyślnie, jeśli visualnie ma wariancji (mało prawdopodobne, ale warte złapania)
1
Próbowałem użyć tego kodu do rozwiązania mojego problemu, ale otrzymuję zwykłe czarne obrazy. Czy ktoś ma o tym jakiś pomysł? stackoverflow.com/questions/24266000/…
user961627
32

Powinieneś móc po prostu pozwolić PILowi pobrać typ pliku z rozszerzenia, tj. Użyj:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
wim
źródło
1
Dzięki za wkład. Jednak kiedy próbuję pozwolić funkcji zapisu na pobranie typu pliku, jak zasugerowałeś powyżej, pojawia się następujący błąd: IOError: nie można zapisać trybu F jako BMP. jakakolwiek rada?
user1999274
1
Tak, tablicę należy przekonwertować na numpy.uint8dtype zamiast na float.
wim
6

Spróbuj usunąć .przed .bmp(nie pasuje BMPzgodnie z oczekiwaniami). Jak widać z błędu, save_handlerjest to duże litery formatpodane przez Ciebie, a następnie szuka dopasowania w SAVE. Jednak odpowiadający mu klucz w tym obiekcie to BMP(zamiast .BMP).

Nie wiem zbyt wiele PIL, ale po szybkich poszukiwaniach wydaje się, że jest to problem z modeobrazem. Zmiana definicji jna:

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

Wydawało mi się, że działa dla mnie (jednak zauważ, że mam bardzo małą wiedzę PIL, więc sugerowałbym użycie rozwiązania @ mmgp, ponieważ on / on wyraźnie wie, co robią :)). Jeśli chodzi o typy mode, użyłem tej strony - mam nadzieję, że jeden z dostępnych wyborów będzie dla Ciebie odpowiedni.

RocketDonkey
źródło
Próbowałem usunąć plik .bmp na rzecz bmp, ale nadal nie działał. błąd, który teraz otrzymuję to: IOError: nie można zapisać trybu F jako BMP. Sprawdziłem strony PIL w poszukiwaniu dokumentacji i powiedziałem, że używam pliku .bmp, więc ogólnie nadal nie mam pojęcia, dlaczego nie działa.
user1999274
@ user1999274 Wysłałem aktualizację, która wydawała się działać dla mnie (przepraszam za brak szczegółów - składam to razem w miarę postępu :)).
RocketDonkey
@RocketDonkey to było trochę mądrzejsze, ponieważ konwersja wyników transformacji Fouriera na przestrzeń kolorów RGB da obraz bez znaczenia. To, że nie zgłasza już wyjątku, nie oznacza, że ​​wynik jest poprawny.
mmgp
@mmgp Zgoda - dlatego dałem +1 Twojemu i mam nadzieję, że OP to zaakceptuje :)
RocketDonkey
4

Wiem, że to jest stare, ale odkryłem, że (podczas korzystania z Pillow) otwarcie pliku za pomocą, open(fp, 'w')a następnie zapisanie pliku będzie działać. Na przykład:

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

fp jest to oczywiście ścieżka do pliku.

necko
źródło
1
Dokumentacja Pillow mówi, że formatparametr powinien być używany, jeśli obiekt pliku jest używany w save. Czy to nie jest konieczne?
Rob Rose,
@RobRose podczas moich testów, kiedy zamieściłem odpowiedź, nie znalazłem czegoś takiego, co byłoby konieczne. Jednak teraz może tak być. Jeśli jakiekolwiek testy okażą się konieczne, daj mi znać, a
zmienię