Làm cách nào để lưu ảnh bằng PIL?


118

Tôi vừa thực hiện một số xử lý hình ảnh bằng thư viện hình ảnh Python (PIL) bằng cách sử dụng một bài đăng mà tôi đã tìm thấy trước đó để thực hiện chuyển đổi fourier của hình ảnh và tôi không thể làm cho chức năng lưu hoạt động. Toàn bộ mã hoạt động tốt nhưng nó chỉ không lưu hình ảnh kết quả:

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ỗi tôi nhận được là như sau:

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

Làm cách nào để lưu ảnh bằng Pythons PIL?

Câu trả lời:


143

Lỗi liên quan đến phần mở rộng tệp đã được xử lý, bạn sử dụng BMP(không có dấu chấm) hoặc chuyển tên đầu ra với phần mở rộng đã có. Bây giờ để xử lý lỗi, bạn cần sửa đổi đúng cách dữ liệu của mình trong miền tần số để được lưu dưới dạng hình ảnh số nguyên,PIL nó cho bạn biết rằng nó không chấp nhận dữ liệu float để lưu dưới dạng BMP.

Đây là một gợi ý (với các sửa đổi nhỏ khác, như sử dụng fftshiftnumpy.arraythay vì numpy.asarray) để thực hiện chuyển đổi để có hình ảnh phù hợp:

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
này cảm ơn rất nhiều. nó hoạt động hoàn hảo ngay bây giờ! bây giờ tất cả những gì tôi phải làm là hiểu tất cả các bước nhưng điều đó sẽ không quá tệ. cảm ơn bạn rất nhiều vì sự giúp đỡ
user1999274

@ user1999274 sự khác biệt chính là trong việc sử dụng fft2thay rfft2vì đối với dữ liệu rời rạc, tôi không thấy điểm nào trong việc sử dụng sau này. Phần còn lại hoàn toàn là thẩm mỹ, tức là bạn sẽ không thể hình dung chính xác phép biến đổi Fourier nếu không áp dụng hệ số log cho nó. Sau đó, việc chuẩn hóa là giữ cho mọi thứ đơn giản để chuyển đổi thành phạm vi [0, 255].
mmgp

1
visual = (visual - visual.min()) / (visual.max() - visual.min())sẽ mặc định nếu visualkhông có phương sai (không, nhưng giá trị đánh bắt)

1
Tôi đã cố gắng sử dụng mã này cho sự cố của mình, nhưng tôi nhận được hình ảnh màu đen đơn giản. Có ai có bất kỳ ý tưởng về điều này? stackoverflow.com/questions/24266000/…
user961627

32

Bạn có thể chỉ cần cho phép PIL lấy loại tệp từ phần mở rộng, tức là sử dụng:

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

1
Cảm ơn các đầu vào. tuy nhiên khi tôi cố gắng để hàm lưu nhận được loại tệp như bạn đã đề xuất ở trên, tôi gặp lỗi sau: IOError: không thể ghi chế độ F dưới dạng BMP. bất kỳ lời khuyên?
user1999274

1
Có, bạn nên chuyển mảng thành numpy.uint8kiểu dtype hơn là float.
wim

6

Hãy thử loại bỏ .trước .bmp(nó không khớp BMPnhư mong đợi). Như bạn có thể nhìn thấy từ lỗi, save_handlerlà phía trên vỏ các formatbạn cung cấp và sau đó tìm kiếm một trận đấu trong SAVE. Tuy nhiên, khóa tương ứng trong đối tượng đó là BMP(thay vì.BMP ).

Tôi không biết nhiều về nó PIL, nhưng từ một số tìm kiếm nhanh xung quanh, có vẻ như đó là một vấn đề với modehình ảnh. Thay đổi định nghĩa của jthành:

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

Có vẻ hiệu quả với tôi (tuy nhiên lưu ý rằng tôi có rất ít kiến ​​thức về nó PIL, vì vậy tôi khuyên bạn nên sử dụng giải pháp của @ mmgp vì s / anh ấy biết rõ ràng họ đang làm gì :)). Đối với các loạimode , tôi đã sử dụng này trang - hy vọng một trong những lựa chọn sẽ làm việc cho bạn.


Tôi đã thử xóa .bmp thay vì bmp và nó vẫn không hoạt động. lỗi bây giờ tôi nhận được là: IOError: không thể ghi chế độ F là BMP. Tôi đã kiểm tra các trang PIL để tìm tài liệu và nó cho biết sử dụng .bmp nên về tổng thể, tôi vẫn không biết tại sao nó không hoạt động.
user1999274

@ user1999274 Đã đăng một bản cập nhật có vẻ phù hợp với tôi (xin lỗi vì thiếu chi tiết - chắp nối nó lại với nhau khi tôi tiếp tục :)).
RocketDonkey

@RocketDonkey nó thông minh hơn thế một chút, bởi vì việc chuyển đổi kết quả của phép biến đổi Fourier thành không gian màu RGB sẽ cho hình ảnh vô nghĩa. Chỉ vì nó không còn đưa ra một ngoại lệ, điều đó không có nghĩa là kết quả là chính xác.
mmgp

@mmgp Đồng ý - đó là lý do tại sao tôi +1 của bạn và hy vọng các OP chấp nhận nó :)
RocketDonkey

4

Tôi biết rằng điều này đã cũ, nhưng tôi nhận thấy rằng (trong khi sử dụng Pillow), mở tệp bằng cách sử dụng open(fp, 'w')và sau đó lưu tệp sẽ hoạt động. Ví dụ:

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

fp tất nhiên là đường dẫn tệp.


1
Tài liệu của Pillow nói rằng formatthông số này nên được sử dụng nếu một đối tượng tệp được sử dụng trong save. Điều này có cần thiết không?
Rob Rose

@RobRose trong quá trình thử nghiệm của tôi, khi tôi đăng câu trả lời, tôi không thấy bất kỳ điều gì như vậy là cần thiết. Tuy nhiên, nó có thể là trường hợp bây giờ. Nếu bất kỳ thử nghiệm bạn làm chứng minh nó cần thiết cho tôi biết và tôi sẽ sửa câu trả lời của tôi
necko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.