Bagaimana cara menyimpan gambar dengan PIL?

119

Saya baru saja melakukan beberapa pemrosesan gambar menggunakan Python image library (PIL) menggunakan postingan yang saya temukan sebelumnya untuk melakukan transformasi fourier gambar dan saya tidak dapat mengaktifkan fungsi save. Seluruh kode berfungsi dengan baik tetapi itu tidak akan menyimpan gambar yang dihasilkan:

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

Kesalahan yang saya dapatkan adalah sebagai berikut:

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

Bagaimana cara menyimpan gambar dengan Pythons PIL?

pengguna1999274
sumber

Jawaban:

144

Kesalahan mengenai ekstensi file telah ditangani, Anda menggunakan BMP(tanpa titik) atau meneruskan nama output dengan ekstensi sudah. Sekarang untuk menangani kesalahan Anda perlu memodifikasi data Anda dengan benar dalam domain frekuensi untuk disimpan sebagai gambar integer, PILmemberi tahu Anda bahwa itu tidak menerima data float untuk disimpan sebagai BMP.

Berikut adalah saran (dengan modifikasi kecil lainnya, seperti menggunakan fftshiftdan numpy.arraybukannya numpy.asarray) untuk melakukan konversi untuk visualisasi yang tepat:

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
sumber
1
hey terima kasih banyak. itu bekerja dengan sempurna sekarang! sekarang yang harus saya lakukan adalah memahami semua langkah tetapi itu tidak akan terlalu buruk. terima kasih banyak atas bantuannya
user1999274
@ user1999274 perbedaan utama adalah dalam penggunaan fft2bukan rfft2karena untuk data diskrit Saya tidak melihat titik dalam menggunakan nanti. Sisanya adalah murni kosmetik, yaitu, Anda tidak akan dapat memvisualisasikan transformasi Fourier dengan baik tanpa menerapkan faktor log padanya. Kemudian normalisasi adalah untuk membuat hal-hal sederhana untuk konversi ke kisaran [0, 255].
mmgp
1
visual = (visual - visual.min()) / (visual.max() - visual.min())akan default jika visualtidak memiliki varian (tidak mungkin, tetapi layak untuk ditangkap)
1
Saya mencoba menggunakan kode ini untuk masalah saya, tetapi saya mendapatkan gambar hitam biasa. Apakah ada yang tahu tentang ini? stackoverflow.com/questions/24266000/…
user961627
32

Anda seharusnya dapat membiarkan PIL mendapatkan jenis file dari ekstensi, yaitu menggunakan:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
wim
sumber
1
Terima kasih atas masukannya. namun ketika saya mencoba untuk membiarkan fungsi simpan mendapatkan tipe file seperti yang Anda sarankan di atas saya mendapatkan kesalahan berikut: IOError: tidak dapat menulis mode F sebagai BMP. ada saran?
pengguna1999274
1
Ya, Anda harus mengonversi larik menjadi numpy.uint8dtype daripada float.
wim
6

Coba hapus .sebelum .bmp(tidak cocok BMPseperti yang diharapkan). Seperti yang Anda lihat dari kesalahannya, save_handleradalah casing atas yang formatAnda berikan dan kemudian mencari kecocokan SAVE. Namun kunci yang sesuai dalam objek itu adalah BMP(bukan .BMP).

Saya tidak tahu banyak tentang PIL, tetapi dari beberapa pencarian cepat di sekitar tampaknya itu adalah masalah dengan modegambar. Mengubah definisi jmenjadi:

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

Tampaknya berhasil untuk saya (namun perhatikan bahwa saya memiliki sedikit pengetahuan tentang PIL, jadi saya sarankan menggunakan solusi @mmgp karena dia jelas tahu apa yang mereka lakukan :)). Untuk jenis mode, saya menggunakan halaman ini - semoga salah satu pilihan di sana akan bekerja untuk Anda.

RocketDonkey
sumber
Saya mencoba menghapus .bmp untuk mendukung bmp dan masih tidak berhasil. kesalahan yang saya dapatkan sekarang adalah: IOError: tidak dapat menulis mode F sebagai BMP. saya memeriksa halaman PIL untuk dokumentasi dan dikatakan untuk menggunakan .bmp jadi secara keseluruhan saya masih tidak tahu mengapa itu tidak berfungsi.
pengguna1999274
@ user1999274 Memposting pembaruan yang tampaknya berhasil untuk saya (maaf atas kurangnya detail - menyatukannya saat saya melanjutkan :)).
RocketDonkey
@RocketDonkey itu sedikit lebih pintar dari itu, karena mengubah hasil transformasi Fourier ke ruang warna RGB akan memberikan gambar yang tidak berarti. Hanya karena tidak lagi memunculkan eksepsi, bukan berarti hasilnya benar.
mmgp
@mmgp Setuju - itulah mengapa saya memberi Anda +1 dan berharap OP menerimanya :)
RocketDonkey
4

Saya tahu ini sudah lama, tetapi saya telah menemukan bahwa (saat menggunakan Pillow) membuka file dengan menggunakan open(fp, 'w')dan kemudian menyimpan file akan berhasil. Misalnya:

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

fp menjadi jalur file, tentu saja.

necko
sumber
1
Dokumentasi Pillow mengatakan bahwa formatparameter harus digunakan jika objek file digunakan di save. Apakah ini tidak perlu?
Rob Rose
@RobRose selama pengujian saya, ketika saya memposting jawabannya, saya tidak menemukan hal seperti itu diperlukan. Namun, mungkin itu masalahnya sekarang. Jika ada pengujian yang Anda lakukan terbukti perlu, beri tahu saya dan saya akan mengedit jawaban saya
necko