Cách chuyển đổi mảng NumPy sang hình ảnh PIL áp dụng colormap matplotlib


132

Tôi có một vấn đề đơn giản, nhưng tôi không thể tìm ra giải pháp tốt cho nó.

Tôi muốn lấy một mảng NumPy 2D đại diện cho hình ảnh thang độ xám và chuyển đổi nó thành hình ảnh PIL RGB trong khi áp dụng một số bản đồ màu matplotlib.

Tôi có thể nhận được đầu ra PNG hợp lý bằng cách sử dụng pyplot.figure.figimagelệnh:

dpi = 100.0
w, h = myarray.shape[1]/dpi, myarray.shape[0]/dpi
fig = plt.figure(figsize=(w,h), dpi=dpi)
fig.figimage(sub, cmap=cm.gist_earth)
plt.savefig('out.png')

Mặc dù tôi có thể điều chỉnh điều này để có được những gì tôi muốn (có lẽ sử dụng StringIO để có được hình ảnh PIL), tôi tự hỏi liệu không có cách nào đơn giản hơn để làm điều đó, vì dường như đó là một vấn đề rất tự nhiên của hình ảnh. Hãy nói, một cái gì đó như thế này:

colored_PIL_image = magic_function(array, cmap)

Câu trả lời:


220

Khá là một lớp lót bận rộn, nhưng đây là:

  1. Trước tiên, đảm bảo mảng NumPy của bạn myarray, được chuẩn hóa với giá trị tối đa tại 1.0.
  2. Áp dụng trực tiếp colormap myarray.
  3. Rescale đến 0-255phạm vi.
  4. Chuyển đổi sang số nguyên, sử dụng np.uint8().
  5. Sử dụng Image.fromarray().

Và bạn đã hoàn thành:

from PIL import Image
from matplotlib import cm
im = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))

với plt.savefig():

Nhập mô tả hình ảnh ở đây

với im.save():

Nhập mô tả hình ảnh ở đây


7
Phần "Áp dụng colormap trực tiếp vào myarray" phần cắt thẳng vào tim! Tôi không biết điều đó là có thể, cảm ơn bạn!
heltonbiker

34
Nghiên cứu các tài liệu về linearSegmentedColormap (từ đó cm.gist_earth là một ví dụ), tôi phát hiện ra rằng có thể gọi nó bằng một đối số "byte" đã chuyển đổi nó thành uint8. Sau đó, lớp lót trở nên yên tĩnh hơn rất nhiều:im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
heltonbiker

1
@CiprianTomoiaga, hình dạng của mảng phải là kích thước hình ảnh bạn muốn. Ví dụ: hình ảnh VGA sẽ được tạo từ một mảng có hình dạng (1024,768). Bạn nên chú ý điều này áp dụng cho hình ảnh đơn sắc. Điều này rất quan trọng vì thông thường khi bạn chuyển đổi hình ảnh RGB thành một mảng, ví dụ, hình dạng của nó là (1024,768,3), vì nó có ba kênh.
heltonbiker

5
Tôi đang gặp lỗiNameError: name 'cm' is not defined
vào

10
@msofrom matplotlib import cm
Quantum7

10
  • đầu vào = numpy_image
  • np.unit8 -> chuyển đổi sang số nguyên
  • chuyển đổi ('RGB') -> chuyển đổi sang RGB
  • Image.fromarray -> trả về một đối tượng hình ảnh

    from PIL import Image
    import numpy as np
    
    PIL_image = Image.fromarray(np.uint8(numpy_image)).convert('RGB')
    
    PIL_image = Image.fromarray(numpy_image.astype('uint8'), 'RGB')

5
Hy vọng Nó sẽ giải quyết vấn đề nhưng vui lòng thêm giải thích về mã của bạn với nó để người dùng sẽ hiểu hoàn hảo những gì anh ấy / cô ấy thực sự muốn.
Jaimil Patel

1
Tốt, cập nhật câu trả lời. Những cái trước là từ vài năm trước.
Catalina Chircu

7

Phương pháp được mô tả trong câu trả lời được chấp nhận không hiệu quả với tôi ngay cả sau khi áp dụng các thay đổi được đề cập trong các nhận xét. Nhưng mã đơn giản dưới đây đã làm việc:

import matplotlib.pyplot as plt
plt.imsave(filename, np_array, cmap='Greys')

np_array có thể là một mảng 2D với các giá trị từ 0..1 float o2 0..255 uint8 và trong trường hợp đó, nó cần cmap. Đối với mảng 3D, cmap sẽ bị bỏ qua.

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.