ฉันจะบันทึกภาพด้วย PIL ได้อย่างไร?


119

ฉันเพิ่งทำการประมวลผลรูปภาพโดยใช้ไลบรารีรูปภาพ Python (PIL) โดยใช้โพสต์ที่ฉันพบก่อนหน้านี้เพื่อทำการแปลงฟูเรียร์ของรูปภาพและฉันไม่สามารถให้ฟังก์ชันบันทึกทำงานได้ รหัสทั้งหมดใช้งานได้ดี แต่จะไม่บันทึกภาพที่ได้:

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

ข้อผิดพลาดที่ฉันได้รับมีดังต่อไปนี้:

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

ฉันจะบันทึกภาพด้วย Pythons PIL ได้อย่างไร?

คำตอบ:


144

ข้อผิดพลาดเกี่ยวกับนามสกุลไฟล์ได้รับการจัดการแล้วคุณอาจใช้BMP(โดยไม่มีจุด) หรือส่งชื่อเอาต์พุตที่มีนามสกุลอยู่แล้ว ตอนนี้เพื่อจัดการกับข้อผิดพลาดที่คุณต้องแก้ไขข้อมูลของคุณอย่างถูกต้องในโดเมนความถี่เพื่อบันทึกเป็นรูปภาพจำนวนเต็มPILกำลังบอกคุณว่าไม่ยอมรับข้อมูลลอยเพื่อบันทึกเป็น BMP

นี่คือคำแนะนำ (พร้อมการปรับเปลี่ยนเล็กน้อยอื่น ๆ เช่นการใช้fftshiftและnumpy.arrayแทนnumpy.asarray) สำหรับการแปลงเพื่อการแสดงภาพที่เหมาะสม:

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
เฮ้ขอบคุณมาก มันใช้งานได้ดีเลย! ตอนนี้สิ่งที่ฉันต้องทำคือเข้าใจขั้นตอนทั้งหมด แต่นั่นก็ไม่เลวร้ายเกินไป ขอบคุณมากสำหรับความช่วยเหลือ
user1999274

@ user1999274 ข้อแตกต่างที่สำคัญคือการใช้fft2แทนrfft2ตั้งแต่สำหรับข้อมูลที่ไม่ต่อเนื่องฉันไม่เห็นประเด็นในการใช้ในภายหลัง ส่วนที่เหลือเป็นเครื่องสำอางล้วนๆกล่าวคือคุณจะไม่สามารถเห็นภาพการแปลงฟูเรียร์ได้อย่างถูกต้องโดยไม่ใช้ปัจจัยบันทึกกับมัน จากนั้นการทำให้เป็นมาตรฐานคือการทำให้สิ่งต่างๆง่ายขึ้นสำหรับการแปลงเป็นช่วง [0, 255]
mmgp

1
visual = (visual - visual.min()) / (visual.max() - visual.min())จะเป็นค่าเริ่มต้นหากvisualไม่มีความแปรปรวน (ไม่น่าจะเป็นไปได้ แต่น่าจับ)

1
ฉันพยายามใช้รหัสนี้สำหรับปัญหาของฉัน แต่ได้ภาพสีดำธรรมดา ใครมีความคิดเกี่ยวกับเรื่องนี้บ้าง? stackoverflow.com/questions/24266000/…
user961627

32

คุณควรจะสามารถให้ PIL รับประเภทไฟล์จากนามสกุลได้เช่นใช้:

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

1
ขอบคุณสำหรับข้อมูล อย่างไรก็ตามเมื่อฉันพยายามให้ฟังก์ชันบันทึกได้รับประเภทไฟล์อย่างที่คุณแนะนำข้างต้นฉันได้รับข้อผิดพลาดต่อไปนี้: IOError: ไม่สามารถเขียนโหมด F เป็น BMP ได้ คำแนะนำใด ๆ?
user1999274

1
ใช่คุณควรแปลงอาร์เรย์เป็นnumpy.uint8dtype แทนที่จะเป็น float
Wim

6

ลองลบ.ก่อนหน้า.bmp(ไม่ตรงBMPตามที่คาดไว้) ที่คุณสามารถดูจากความผิดพลาดที่save_handlerเป็นบนปลอกคุณให้ไว้แล้วมองสำหรับการแข่งขันในformat SAVEอย่างไรก็ตามคีย์ที่เกี่ยวข้องในออบเจ็กต์นั้นคือBMP(แทน.BMP)

ฉันไม่รู้อะไรมากPILนัก แต่จากการค้นหาอย่างรวดเร็วดูเหมือนว่าจะมีปัญหากับmodeภาพ การเปลี่ยนคำจำกัดความของjเป็น:

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

ดูเหมือนจะทำงานให้ฉัน (อย่างไรก็ตามโปรดทราบว่าฉันมีความรู้น้อยมากPILดังนั้นฉันขอแนะนำให้ใช้โซลูชันของ @ mmgp เพราะเขา / เขารู้อย่างชัดเจนว่าพวกเขากำลังทำอะไร :)) สำหรับประเภทต่างๆmodeฉันใช้หน้านี้ - หวังว่าหนึ่งในตัวเลือกจะเหมาะกับคุณ


ฉันลองลบ. bmp แทน bmp แล้วก็ยังใช้ไม่ได้ ข้อผิดพลาดที่ฉันได้รับตอนนี้คือ: IOError: ไม่สามารถเขียนโหมด F เป็น BMP ฉันตรวจสอบเอกสารในหน้า PIL และมันบอกว่าใช้. bmp ดังนั้นโดยรวมแล้วฉันยังไม่รู้ว่าทำไมมันถึงใช้งานไม่ได้
user1999274

@ user1999274 โพสต์การอัปเดตที่ดูเหมือนจะใช้งานได้สำหรับฉัน (ขออภัยสำหรับการขาดรายละเอียด - ประกอบเข้าด้วยกันในขณะที่ฉันดำเนินการ :))
RocketDonkey

@RocketDonkey มันฉลาดกว่านั้นเล็กน้อยเพราะการแปลงผลลัพธ์ของการแปลงฟูเรียร์เป็น RGB colorspace จะให้ภาพที่ไร้ความหมาย เพียงเพราะไม่มีข้อยกเว้นอีกต่อไปก็ไม่ได้หมายความว่าผลลัพธ์จะถูกต้อง
mmgp

@mmgp ตกลง - นั่นคือเหตุผลที่ฉัน +1 ของคุณและหวังว่า OP จะยอมรับ :)
RocketDonkey

4

ฉันรู้ว่านี่เก่า แต่ฉันพบว่า (ในขณะที่ใช้หมอน) เปิดไฟล์โดยใช้open(fp, 'w')แล้วบันทึกไฟล์จะทำงาน เช่น:

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

fp แน่นอนว่าเป็นเส้นทางของไฟล์


1
หมอนเอกสารบอกว่าพารามิเตอร์ควรจะใช้ในกรณีที่วัตถุไฟล์ที่ใช้ในการformat saveนี่มันไม่จำเป็นหรอ?
Rob Rose

@RobRose ในระหว่างการทดสอบของฉันเมื่อฉันโพสต์คำตอบฉันไม่พบสิ่งที่จำเป็น อย่างไรก็ตามอาจเป็นกรณีนี้ หากการทดสอบใด ๆ ที่คุณพิสูจน์ได้ว่าจำเป็นแจ้งให้เราทราบแล้วฉันจะแก้ไขคำตอบของฉัน
necko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.