Matplotlib grafikleri: eksen, efsaneler ve beyaz boşlukların kaldırılması


285

Python ve Matplotlib'de yeniyim, eksenlere, etiketlere, başlıklara veya genellikle matplotlib tarafından otomatik olarak eklenen herhangi bir şey kullanmadan, bir resme renk haritasını uygulamak ve elde edilen görüntüyü yazmak istiyorum. İşte yaptığım şey:

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    fig.axes.get_xaxis().set_visible(False)
    fig.axes.get_yaxis().set_visible(False)
    plt.savefig(outputname)

Şeklin eksenini başarıyla kaldırır, ancak kaydedilen şekil beyaz bir dolgu ve gerçek görüntünün etrafında bir çerçeve sunar. Bunları nasıl çıkarabilirim (en azından beyaz dolgu)? Teşekkürler


2
Bu sorudaki tüm çözümlere odaklanılmıştır imshow. Eğer bir dağılım grafiğiniz varsa, aşağıdaki cevap size yardımcı olabilir: stackoverflow.com/a/40727744/4124317
ImportanceOfBeingErnest

Yanıtlar:


373

Komutun axis('off'), sorunlardan birini, her ekseni ve kenarlığı ayrı ayrı değiştirmekten daha özlü bir şekilde ele aldığını düşünüyorum . Yine de sınır çevresindeki beyaz boşluğu bırakıyor. Ekleme bbox_inches='tight'için savefigbeyaz boşluk sol çok daha küçük, ama yine de mevcut olduğunu aşağıda komutla neredeyse orada alır, sen örnekte görebilirsiniz.

bbox_inches=0Dize yerine matplotlib'in daha yeni sürümlerinin gerekli olabileceğini unutmayın 'tight'(@episodeyang ve @kadrach aracılığıyla)

from numpy import random
import matplotlib.pyplot as plt

data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches='tight')

resim açıklamasını buraya girin


4
Unutbu önerisini takiben şunu kullanabilirsiniz fig = plt.figure(), ax = plt.axes([0,0,1,1])o zaman, plt.imshow(data,interpolation="nearest". plt.axis("off")Bununla birlikte , umarım görüntünün yanındaki her şeyden kurtulmalıdır!
PhilMacKay

5
({Fig.axes.get_xaxis (). Set_visible (False) & fig.axes.get_yaxis (). Set_visible (False)}) ile {plt.axis ('off')}) arasındaki yöntemleri birleştirmek sorunu çözdü ben mi. (Artık boşluk yok). Ve savefig içinde {pad_inches} 'inizi 0 olarak ayarlamayı unutmayın.
Domagoj

3
Ben sadece bu konuya rastladım, bu konudaki ve bağlantılı olanların hiçbiri işe yaramadı. Ancak bbox_inches=0hile açıkça belirtildi .
kadrach

1
Eğer plt.plot (x, y) 'da olduğu gibi, plt.imshow üzerinde bir şeyler çiziyorsanız, xlim ve ylim öğelerini matris boyutuna ayarladığınızdan emin olmanız gerekir.
Mathusalem

1
bu artık çalışmıyor. Anlamak için bir saatimi aldı. Aşağıdaki cevaba bakınız.
bölüm

107

Bu numarayı matehat'tan öğrendim , burada :

import matplotlib.pyplot as plt
import numpy as np

def make_image(data, outputname, size=(1, 1), dpi=80):
    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    plt.set_cmap('hot')
    ax.imshow(data, aspect='equal')
    plt.savefig(outputname, dpi=dpi)

# data = mpimg.imread(inputname)[:,:,0]
data = np.arange(1,10).reshape((3, 3))

make_image(data, '/tmp/out.png')

verim

resim açıklamasını buraya girin


3
Doğru cevaba sahip olduğunuzdan eminim (muhtemelen bunu yapmanın birden fazla yolu var), ancak neden doğru cevap olduğunu açıklayıp anlayamayacağınızı merak ediyorum ? Kodunuz beyaz boşluğu kaldırırsa ne olur?
Yann

4
@Yann, belgelere ek olarak, her komutun ne gibi bir etkisi olduğunu görmek için her seferinde bir satır yorum yapmayı çok yararlı buluyorum. Ampirik yol budur!
unutbu

4
Beyaz kenarlığı kaldıran çizgi plt.Axes(fig, [0,0,1,1]). Bu, matplotlib'e, sol alt köşesi (% 0,% 0) konumunda ve genişliği ve yüksekliği (% 100,% 100) olan bir eksen kümesi oluşturmasını söyler.
PhilMacKay

Bu daha doğru cevaptır, çünkü sadece kaydedilen görüntü için beyaz alanı değil, aynı zamanda ekran grafikleri için de beyaz alanı kaldırır.
MaxNoe

Teşekkürler, bu SADECE benim Ubuntu iyi çalışıyor :)
AlphaGoMK

56

Olası en basit çözüm:

Ben sadece soruda açıklanan yöntemi ve Hooked tarafından cevap yöntemini birleştirdim.

fig = plt.imshow(my_data)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('pict.png', bbox_inches='tight', pad_inches = 0)

Bu koddan sonra boşluk ve çerçeve yoktur.

Beyaz boşluk, eksen veya çerçeve yok


3
Metodunuz bu görüntü çevresindeki tüm beyaz boşlukları kaldırdı, iyi iş, ama yine de neden komutu eklemeyi fig.axes.get_xaxis().set_visible(False)sorunu çözdüğünü bilmiyorum . Thanks
ollydbg23

5
Evet, bu komutları çağırmazsanız beyaz boşlukların çoğu kaldırılır. Ancak benim durumumda hala benim .png görüntüsünün kenarı (belki 2 piksel genişliğinde) arasında bazı boşluklar vardı. Aşağıdaki komutları çağırarak o inatçı boşluklardan kurtuldum.
Domagoj

3
Bununla birlikte, yukarıdakinin aynı şekilde birden fazla eksen varlığında başarısız olacağını unutmayın (benim durumumda çizimde gömülü bir görüntü). Çözüm: fig.axes[0]ve genel olarak tüm veya seçilen eksenler.
Ioannis Filippidis

29

Henüz kimseden bahsetmedi imsave, bu da onu bir astar haline getiriyor:

import matplotlib.pyplot as plt
import numpy as np

data = np.arange(10000).reshape((100, 100))
plt.imsave("/tmp/foo.png", data, format="png", cmap="hot")

Görüntüyü olduğu gibi doğrudan saklar, yani herhangi bir eksen veya kenarlık / dolgu eklemez.

resim açıklamasını buraya girin


Çoğu zaman yaptığım budur, ancak colorbar'a ihtiyaç duyduğum durumlar vardır ve bu durumlarda imsave beni kurtaramaz.
Elias

9

Ayrıca, şeklin kapsamını bbox_inchesbağımsız değişkene de belirleyebilirsiniz . Bu, figürün etrafındaki beyaz dolgudan kurtulacaktır.

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    ax = fig.gca()
    ax.set_axis_off()
    ax.autoscale(False)
    extent = ax.get_window_extent().transformed(plt.gcf().dpi_scale_trans.inverted())
    plt.savefig(outputname, bbox_inches=extent)

8

Bu, tüm dolguları ve kenarlıkları kaldırmalıdır:

from matplotlib import pyplot as plt

fig = plt.figure()
fig.patch.set_visible(False)

ax = fig.add_subplot(111)

plt.axis('off')
plt.imshow(data)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig("../images/test.png", bbox_inches=extent)

Yetersiz cevap! Bu beni orada% 99 gibi buldu. Daha güncel olmalı çünkü en güncel
Nathan

Ayrıca, üzerinde bir Axes nesnesi ( ax) yoksa da çalışır extent = plt.gca().get_window_extent().transformed(fig.dpi_scale_trans.inverted()).
Toast


3

Yükseltilmiş cevap artık çalışmıyor. Çalışması için [0, 0, 1, 1] olarak ayarlanmış bir ekseni manuel olarak eklemeniz veya şekil altındaki yamayı kaldırmanız gerekir.

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 5), dpi=20)
ax = plt.Axes(fig, [0., 0., 1., 1.])
fig.add_axes(ax)
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')                                # same as: ax.set_axis_off()

plt.savefig("test.png")

Alternatif olarak, yamayı kaldırabilirsiniz. Dolguları kaldırmak için bir alt grafik eklemenize gerek yoktur. Bu, Vlady'nin aşağıdaki cevabından basitleştirilmiştir

fig = plt.figure(figsize=(5, 5))
fig.patch.set_visible(False)                   # turn off the patch

plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')

plt.savefig("test.png", cmap='hot')

Bu, 3.0.32019/06/19 sürümü ile test edilmiştir . Görüntü aşağıdaki feryat:

resim açıklamasını buraya girin

Yapılacak daha basit bir şey kullanmaktır pyplot.imsave. Ayrıntılar için aşağıdaki luator yanıtına bakın


benim için sadece Axes sürümü çalışıyor. Ben yama kapalı sürümü ile dolgu olsun. yine de teşekkürler!
save_jeff

2

Ubuntu'nun cevabını beğendim , ancak kare olmayan görüntüler için kutunun dışında nasıl ayarlanacağını açıkça göstermiyordum, bu yüzden kolay kopyala yapıştır için değiştirdim:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

def save_image_fix_dpi(data, dpi=100):
    shape=np.shape(data)[0:2][::-1]
    size = [float(i)/dpi for i in shape]

    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig,[0,0,1,1])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(data)
    fig.savefig('out.png', dpi=dpi)
    plt.show()

Pixel_size / dpi = boyut korunuyorsa, seçtiğiniz dpi ne olursa olsun görüntüleri kenarlıksız kaydetmek kolaydır.

data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)

resim açıklamasını buraya girin

Ancak görüntüleme ürkütücü. Küçük dpi seçerseniz, görüntü boyutunuz ekranınızdan daha büyük olabilir ve ekran sırasında kenarlık elde edebilirsiniz. Bununla birlikte, bu tasarrufu etkilemez.

İçin böylece

save_image_fix_dpi(data, dpi=20)

Ekran sınırlanır (ancak kaydetme çalışır): resim açıklamasını buraya girin


1

İlk olarak, belirli görüntü formatları (yani TIFF ) için renk haritasını başlığa kaydedebilirsiniz ve çoğu izleyici verilerinizi renk haritasıyla gösterecektir.

matplotlibGörüntülere ek açıklamalar veya başka veriler eklemek için yararlı olabilecek gerçek bir resmi kaydetmek için aşağıdaki çözümü kullandım:

fig, ax = plt.subplots(figsize=inches)
ax.matshow(data)  # or you can use also imshow
# add annotations or anything else
# The code below essentially moves your plot so that the upper
# left hand corner coincides with the upper left hand corner
# of the artist
fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
# now generate a Bbox instance that is the same size as your
# single axis size (this bbox will only encompass your figure)
bbox = matplotlib.transforms.Bbox(((0, 0), inches))
# now you can save only the part of the figure with data
fig.savefig(savename, bbox_inches=bbox, **kwargs)

0

Herkesten harika cevaplar için teşekkürler ... Ben sadece ekstra bir dolgu / boşluk vb ile bir görüntü çizmek isteyen ile aynı sorunu vardı, bu yüzden burada herkesin fikirlerini bulmak için çok mutlu oldu.

Hiçbir dolgu ile görüntü dışında, sadece basit bir görüntü arsa ötesinde kolayca ek açıklamalar vb eklemek istedim.

Sonuçta David'in cevabını csnemes ile birleştirerek figür yaratma zamanında basit bir sarıcı yapmaktı. Bunu kullandığınızda, daha sonra imsave () veya başka bir şeyle değişiklik yapmanız gerekmez:

def get_img_figure(image, dpi):
    """
    Create a matplotlib (figure,axes) for an image (numpy array) setup so that
        a) axes will span the entire figure (when saved no whitespace)
        b) when saved the figure will have the same x/y resolution as the array, 
           with the dpi value you pass in.

    Arguments:
        image -- numpy 2d array
        dpi -- dpi value that the figure should use

    Returns: (figure, ax) tuple from plt.subplots
    """

    # get required figure size in inches (reversed row/column order)
    inches = image.shape[1]/dpi, image.shape[0]/dpi

    # make figure with that size and a single axes
    fig, ax = plt.subplots(figsize=inches, dpi=dpi)

    # move axes to span entire figure area
    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)

    return fig, ax
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.