Matplotlib图:删除轴,图例和空白


285

我是Python和Matplotlib的新手,我想简单地将colormap应用于图像并写入结果图像,而无需使用轴,标签,标题或通常由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)

它成功删除了图形的轴,但是保存的图形在实际图像周围显示了白色填充和边框。如何删除它们(至少是白色填充)?谢谢


2
这个问题的所有解决方案都集中于imshow。如果您有散点图,那么以下答案可能会帮助您:stackoverflow.com/a/40727744/4124317
ImportanceOfBeingErnest

Answers:


372

我认为该命令axis('off')比单独更改每个轴和边框更简洁地解决了其中一个问题。但是,它仍然在边框周围留有空白区域。添加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

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

1
请注意,如果要像plt.plot(x,y)那样在plt.imshow上“绘图”,则需要确保将xlim和ylim设置为矩阵的大小。
Mathusalem

1
这不再起作用了。花了我一个小时才弄清楚。请参阅下面的答案。
央视

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 2012年

4
@Yann,除了文档之外,我发现每次注释一行以查看每个命令的作用也很有帮助。这是经验方法!
unutbu 2012年

4
删除白色边框的线是plt.Axes(fig, [0,0,1,1])。这告诉matplotlib创建一组轴,该轴的左下角位于(0%,0%)处,宽度和高度为(100%,100%)。
PhilMacKay

这是更正确的答案,因为它不仅会删除已保存图像的空白,而且会删除屏幕上的绘图。
MaxNoe

谢谢,这是唯一可在我的Ubuntu上正常工作的解决方案:)
AlphaGoMK '19

56

可能最简单的解决方案:

我只是简单地结合了问题中描述的方法和Hooked的答案中的方法。

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 2014年

5
是的,如果您不调用此命令,则大多数空白将被删除。但是,在我的情况下,我的绘图和.png图像的边缘(可能为2px宽)之间仍然存在一些空间。通过调用以下命令,我摆脱了那些固执的空间。
Domagoj 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")

它直接按原样存储图像,即不添加任何轴或边框/填充。

在此处输入图片说明


这是我大部分时间要做的,但是在某些情况下,我需要色条,在这种情况下,不保存将无法拯救我。
伊莱亚斯

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%。应该更新一下,因为它是最新的
Nathan

如果您没有使用的Axes对象(ax),它也可以使用extent = plt.gca().get_window_extent().transformed(fig.dpi_scale_trans.inverted())
敬酒


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)

显示屏变成边框(但保存有效): 在此处输入图片说明


2

已投票的答案不再起作用。要使其正常工作,您需要手动添加设置为[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")

或者,您可以只删除补丁。您无需添加子图即可删除填充。这是从下面弗拉迪的答案简化

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.3在2019/06/19 版本上进行测试的。图片见下面:

在此处输入图片说明

使用起来要简单得多pyplot.imsave。有关详细信息,请参见下面的luator回答


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.