Matplotlibプロット:軸、凡例、空白の削除


285

私はPythonとMatplotlibを初めて使用するので、軸、ラベル、タイトル、または通常matplotlibによって自動的に追加されるものを使用せずに、単にカラーマップを画像に適用し、結果の画像を書き込みたいと思います。これが私がしたことです:

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)

Figureの軸は正常に削除されますが、保存されたFigureは、実際の画像の周りに白いパディングとフレームを表示します。どうすれば削除できますか(少なくとも白いパディング)?ありがとう


2
この質問のすべてのソリューションは、に焦点を当てていimshowます。あなたは散布図を持っている場合は代わりに次の答えはあなたを助けるかもしれない:stackoverflow.com/a/40727744/4124317
ImportanceOfBeingErnest

回答:


373

このコマンドaxis('off')は、各軸と境界を個別に変更するよりも簡潔に問題の1つを処理すると思います。ただし、境界線の周りにはまだ空白が残っています。コマンドに追加するbbox_inches='tight'と、savefigほとんど問題はありません。以下の例では、余白がずっと小さくなっていますが、まだ存在しています。

matplotlibの新しいバージョンでbbox_inches=0は、文字列の代わりに'tight'(@episodeyangおよび@kadrachを介して)必要になる場合があることに注意してください。

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

ここに画像の説明を入力してください


4
unutbuの提案に続いて、あなたが使用することができfig = plt.figure()ax = plt.axes([0,0,1,1])そして、plt.imshow(data,interpolation="nearest"。と組み合わせるとplt.axis("off")、画像自体以外のすべてのものが取り除かれるはずです。
PhilMacKay 2013

5
質問のメソッドを組み合わせる({fig.axes.get_xaxis()。set_visible(False)&fig.axes.get_yaxis()。set_visible(False)})と{plt.axis( 'off')})を組み合わせて、私。(空白文字はもうありません)。そして、savefigの{pad_inches}を0に設定することを忘れないでください。–
Domagoj

3
私はこの問題に遭遇しましたが、このスレッドの解決策もリンクされた解決策も機能しませんでした。しかし、明示的に指定する bbox_inches=0ことがトリックをしました。
kadrach 2015

1
plt.plot(x、y)のように、plt.imshowの上に「プロット」する場合は、xlimとylimを行列のサイズに設定する必要があります。
Mathusalem

1
これはもう機能しません。それを理解するのに1時間かかった。以下の回答を参照してください。
Episodeyang

107

私はここでmatehatからこのトリックを学びました

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

収量

ここに画像の説明を入力してください


3
私はあなたが正しい答えを持っていると確信しています(おそらくそれを行う方法は複数あるでしょう)が、それが正しい答えである理由を説明できるかどうか疑問に思っていますか?あなたのコードは空白を取り除きますか?
Yann

4
@Yannは、ドキュメントに加えて、一度に1行ずつコメントアウトして、各コマンドがどのような影響を与えるかを確認すると非常に役立ちます。それは経験的な方法です!
unutbu

4
白い境界線を削除する線はplt.Axes(fig, [0,0,1,1])です。これは、matplotlibに、左下隅が(0%、0%)にあるポイントで、幅と高さが(100%、100%)の軸のセットを作成するように指示します。
PhilMacKay 2013

これは、保存されたイメージだけでなく、画面上のプロットの空白も削除するので、より正しい答えです。
MaxNoe

おかげで、これは私のUbuntuで
正常に機能する唯一の

56

可能な最も簡単な解決策:

質問で述べた方法とフッキングの答えからの方法を単純に組み合わせました。

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)

このコードの後、空白やフレームはありません。

空白、軸、フレームなし


3
あなたの方法はこの画像の周りのすべての空白を削除しました、良い仕事です、しかし私はまだコマンドを追加しfig.axes.get_xaxis().set_visible(False)て問題を解決する理由がわかりません。ありがとう
ollydbg23

5
はい、このコマンドを呼び出さない場合は、ほとんどの空白が削除されます。ただし、私の場合、プロットと.png画像の端(おそらく2px幅)の間にまだスペースが残っていました。次のコマンドを呼び出すことで、私はそれらの頑固なスペースを取り除きました。
ドマゴジ2014

3
ただし、同じ図に複数の軸が存在する場合(上記の例ではプロットに埋め込まれた画像)、上記は失敗することに注意してください。解決策:fig.axes[0]、および一般的にすべてまたは選択された軸。
Ioannis Filippidis 2015

29

imsaveまだ誰も言及していないので、これはワンライナーです:

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

画像をそのまま保存します。つまり、軸やボーダー/パディングを追加しません。

ここに画像の説明を入力してください


これはほとんどの場合私が行うことですが、カラーバーが必要な場合があり、これらの場合、imsaveは私を保存できません。
エリアス

9

bbox_inches引数に図形の範囲を指定することもできます。これは、図の周りの白いパディングを取り除きます。

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

これにより、すべてのパディングとボーダーが削除されます。

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)

過小評価された答え!これにより、道のりの99%が達成されました。それが最も最新なので、もっと賛成すべきです
ネイサン

でAxesオブジェクト(ax)がない場合にも機能しextent = plt.gca().get_window_extent().transformed(fig.dpi_scale_trans.inverted())ます。
トースト


3

賛成投票はもう機能しません。これを機能させるには、[0、0、1、1]に設定された軸を手動で追加するか、図の下のパッチを削除する必要があります。

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

または、パッチを削除することもできます。パディングを削除するためにサブプロットを追加する必要はありません。これは以下のVladyの答えから簡略化されています

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

これは3.0.32019/06/19のバージョンでテストされています。画像は以下を参照してください:

ここに画像の説明を入力してください

より簡単な方法は、を使用することpyplot.imsaveです。詳細については、以下のルアーの回答を参照してください


私にとっては、Axesバージョンのみが機能します。パッチをオフにしたバージョンでパディングを取得します。とにかくthx!
save_jeff

2

私はubuntuの答えが好きでしたが、正方形以外の画像のサイズをすぐに設定する方法を明示的に示していなかったため、簡単にコピーして貼り付けられるように変更しました。

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 = sizeが維持されている場合は、選択したdpiに関係なく、境界線なしで画像を保存するのは簡単です。

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

ここに画像の説明を入力してください

しかし、表示は不気味です。小さいdpiを選択すると、画像サイズが画面より大きくなり、表示中に境界線が表示されます。それにもかかわらず、これは節約に影響しません。

だから

save_image_fix_dpi(data, dpi=20)

ディスプレイは縁取られます(ただし、作品は保存されます)。 ここに画像の説明を入力してください


1

まず、特定の画像形式(TIFFなど)では、実際にカラーマップをヘッダーに保存でき、ほとんどのビューアーはデータをカラーマップで表示します。

matplotlib画像に注釈やその他のデータを追加するのに役立つ実際の画像を保存するために、私は次のソリューションを使用しました:

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

皆からの素晴らしい回答に感謝します...余分なパディング/スペースなしで画像だけをプロットしたいのとまったく同じ問題があったので、ここで皆のアイデアを見つけることができてとても幸せでした。

パディングのない画像とは別に、単純な画像プロットだけでなく、注釈なども簡単に追加できるようにしたいと思っていました。

結局、私がやったのは、Davidの回答csnemes の回答を組み合わせて、図の作成時に単純なラッパーを作成することでした。これを使用する場合、後でimsave()などを使用して変更する必要はありません。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.