Matplotlib renk haritası uygulayarak NumPy dizisini PIL görüntüsüne dönüştürme


134

Basit bir problemim var ama buna iyi bir çözüm bulamıyorum.

Gri tonlamalı bir görüntüyü temsil eden bir NumPy 2D dizisi almak ve bazı matplotlib renk haritalarını uygularken bunu bir RGB PIL görüntüsüne dönüştürmek istiyorum.

Şu pyplot.figure.figimagekomutu kullanarak makul bir PNG çıktısı alabilirim :

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

Bunu istediğimi elde etmek için uyarlayabilsem de (muhtemelen StringIO kullanarak PIL görüntüsünü elde edebilirim), bunu yapmanın daha basit bir yolu olup olmadığını merak ediyorum, çünkü bu çok doğal bir görüntü görselleştirme problemi gibi görünüyor. Şöyle bir şey diyelim:

colored_PIL_image = magic_function(array, cmap)

Yanıtlar:


222

Oldukça yoğun bir tek hat, ama işte burada:

  1. Öncelikle NumPy dizinizin myarraymaks . Değeriyle normalize edildiğinden emin olun 1.0.
  2. Renk haritasını doğrudan öğesine uygulayın myarray.
  3. Aralığı yeniden ölçeklendirin 0-255.
  4. Kullanarak tamsayılara dönüştürün np.uint8().
  5. Kullanın Image.fromarray().

Ve bitirdiniz:

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

ile plt.savefig():

Buraya resim açıklamasını girin

ile im.save():

Buraya resim açıklamasını girin


7
"Renk haritasını doğrudan uygula myarray" bölümü doğrudan kalbe kesilir! Bunun mümkün olduğunu bilmiyordum, teşekkürler!
heltonbiker

34
LinearSegmentedColormap (cm.gist_earth bir örnektir) hakkındaki dokümanları incelerken, onu zaten uint8'e dönüştüren bir "bayt" argümanıyla çağırmanın mümkün olduğunu keşfettim. Ardından, tek im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
hat

1
@CiprianTomoiaga, dizinin şekli istediğiniz görüntü boyutlarında olmalıdır. Örneğin, şekil (1024,768) olan bir diziden bir VGA görüntüsü oluşturulacaktır. Bunun tek renkli görüntüler için geçerli olduğunu fark etmelisiniz. Bu önemlidir, çünkü genellikle bir RGB görüntüsünü bir diziye dönüştürdüğünüzde, üç kanalı olduğu için şekli örneğin (1024,768,3) şeklindedir.
heltonbiker

5
Hata alıyorumNameError: name 'cm' is not defined
rnso

10
@msofrom matplotlib import cm
Quantum7

10
  • input = numpy_image
  • np.unit8 -> tamsayılara dönüştürür
  • convert ('RGB') -> RGB'ye dönüştürür
  • Image.fromarray -> bir görüntü nesnesi döndürür

    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
Umarım sorunu çözecektir, ancak lütfen kodunuzun açıklamasını ekleyin, böylece kullanıcı gerçekten istediği şeyi mükemmel bir şekilde anlayacaktır.
Jaimil Patel

1
Güzel, güncellenmiş cevap. Öncekiler birkaç yıl öncesine ait.
Catalina Chircu

7

Kabul edilen cevapta açıklanan yöntem, yorumlarında belirtilen değişiklikleri uyguladıktan sonra bile benim için işe yaramadı. Ancak aşağıdaki basit kod işe yaradı:

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

np_array, 0..1 floats o2 0..255 uint8 değerlerine sahip bir 2D dizi olabilir ve bu durumda cmap gerekir. 3B diziler için cmap göz ardı edilecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.