Як перетворити масив NumPy в PIL-зображення, застосовуючи matplotlib colormap


134

У мене проста проблема, але я не можу знайти її хорошого рішення.

Я хочу взяти NumPy 2D масив, який представляє зображення в масштабі сірого, і перетворити його в RGB-зображення RIL, застосовуючи деякі кольорові карти matplotlib.

Я можу отримати розумний вихід PNG за допомогою pyplot.figure.figimageкоманди:

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

Хоча я міг би адаптувати це, щоб отримати те, що я хочу (можливо, використовуючи StringIO, щоб отримати зображення PIL), мені цікаво, чи не існує більш простого способу зробити це, оскільки це здається дуже природною проблемою візуалізації зображення. Скажімо, щось подібне:

colored_PIL_image = magic_function(array, cmap)

Відповіді:


222

Досить зайнятий одноколісний лайнер, але ось він:

  1. Спочатку переконайтеся, що ваш масив NumPy myarrayнормалізується з максимальним значенням at 1.0.
  2. Застосовуйте кольорову карту безпосередньо до myarray.
  3. Розширити масштаб до 0-255діапазону.
  4. Перетворити на цілі числа, використовуючи np.uint8().
  5. Використовуйте Image.fromarray().

І ви закінчили:

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

з plt.savefig():

Введіть тут опис зображення

з im.save():

Введіть тут опис зображення


7
Частина "Нанеси кольорову карту безпосередньо на myarray" вирізати прямо до серця! Я не знав, що це можливо, дякую!
heltonbiker

34
Вивчаючи документи про LinearSegmentedColormap (з якої cm.gist_earth є екземпляром), я виявив, що це можна викликати аргументом "байт", який вже перетворює його на uint8. Тоді im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
однолінійний

1
@CiprianTomoiaga, форма масиву має бути розмірами зображення, які ви хочете. Наприклад, VGA-зображення буде генеруватися з масиву з формою (1024,768). Ви повинні помітити, що це стосується монохромних зображень. Це важливо, оскільки зазвичай, коли ви перетворюєте RGB-зображення в масив, його форма, наприклад, (1024,768,3), оскільки у нього є три канали.
heltonbiker

5
Я отримую помилкуNameError: name 'cm' is not defined
rnso

10
@msofrom matplotlib import cm
Quantum7

10
  • input = numpy_image
  • np.unit8 -> перетворює на цілі числа
  • convert ('RGB') -> перетворює в RGB
  • Image.fromarray -> повертає об'єкт зображення

    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
Сподіваюся, що це вирішить проблему, але, будь ласка, додайте до нього пояснення свого коду, щоб користувач отримав ідеальне розуміння того, чого він / вона насправді хоче.
Джайміл Патель

1
Гарна, оновлена ​​відповідь. Попередні - з декількох років тому.
Каталіна Чірку

7

Метод, описаний у прийнятій відповіді, не працював для мене навіть після застосування змін, зазначених у його коментарях. Але нижче простий код працював:

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

np_array може бути або двовимірним масивом зі значеннями від 0..1 плаває o2 0..255 uint8, і в цьому випадку він потребує cmap. Для 3D-масивів cmap буде ігноровано.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.