【问题标题】:Removing white space around a saved image删除已保存图像周围的空白
【发布时间】:2012-08-03 23:55:01
【问题描述】:

我需要拍摄一张图片并在经过一些处理后保存。当我显示它时,这个图看起来很好,但是在保存图之后,我在保存的图像周围有一些空白。我已经尝试了'tight' 方法的'tight' 选项,也没有工作。代码:

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

  fig = plt.figure(1)
  img = mpimg.imread("image.jpg")
  plt.imshow(img)
  ax=fig.add_subplot(1, 1, 1)

  extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
  plt.savefig('1.png', bbox_inches=extent)

  plt.axis('off') 
  plt.show()

我正在尝试通过在图形上使用 NetworkX 来绘制基本图形并保存它。我意识到没有图表也可以工作,但是当添加图表时,我会在保存的图像周围出现空白;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1, 3)
G.add_edge(1, 2)
pos = {1:[100, 120], 2:[200, 300], 3:[50, 75]}

fig = plt.figure(1)
img = mpimg.imread("image.jpg")
plt.imshow(img)
ax=fig.add_subplot(1, 1, 1)

nx.draw(G, pos=pos)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('1.png', bbox_inches = extent)

plt.axis('off') 
plt.show()

【问题讨论】:

标签: python matplotlib


【解决方案1】:

您可以通过在savefig 中设置bbox_inches="tight" 来移除空白填充:

plt.savefig("test.png",bbox_inches='tight')

您必须将bbox_inches 的参数作为字符串,也许这就是为什么它不能早些为您工作的原因。


可能的重复:

Matplotlib plots: removing axis, legends and white spaces

How to set the margins for a matplotlib figure?

Reduce left and right margins in matplotlib plot

【讨论】:

  • 如果您有多个子图并且想要保存每个子图,您也可以将其与fig.savefig() 一起使用。 (plt.savefig() 在这种情况下不起作用。)
  • 这不是完全正确的。当您使用 bbox_inches 选项时,还有另一个默认设置会留下一些空间。如果你真的想摆脱一切,你还需要使用pad_inches=0.0。当然,这种紧凑的填充经常会被切断,例如指数......
  • 要同时去除黑边,您可能需要设置pad_inches=-0.1
  • 这根本行不通,您仍然会在图形周围出现空白。设置透明选项(如某些答案中所述)也无济于事,空白仍然存在,它只是透明的。
  • @piperchester 这是一个很好的问题,但可能应该完全作为一个新问题提出,这样它就不会在 cmets 中丢失。不过,您应该将新问题链接到旧问题!
【解决方案2】:

我不能声称我确切地知道我的“解决方案”为什么起作用或如何起作用,但是当我想将几个机翼截面的轮廓(没有白边)绘制到 PDF 文件时,我必须这样做。 (请注意,我在 IPython 笔记本中使用了 matplotlib,带有 -pylab 标志。)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

我已尝试停用此功能的不同部分,但这总是会导致某处出现白边。您甚至可以对其进行修改,以防止靠近图形边界的粗线因缺少边距而被剃掉。

【讨论】:

  • 终于有东西了,非常感谢!顺便说一句,在我的情况下,只有使用 set_major_locator 的两行是必要的。
  • 我在过去的一个小时里尝试了各种各样的东西,但无法摆脱 1px 的白色边框。这是唯一有效的方法-特别是其他答案未提及的pad_inches=0
  • pad_inches 帮助了我。
  • 你是个该死的英雄
  • matplotlib.ticker.NullLocator()
【解决方案3】:

在尝试上述答案但没有成功(以及大量其他堆栈帖子)之后,最终对我有用的只是

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

重要的是,这不包括 bbox 或填充参数。

【讨论】:

  • 这应该是公认的答案。此外,您甚至不需要致电set_axis_off。它不会影响保存的图像,因为在subplots_adjust 之后,轴位于 外部 图形的范围内,并且无论如何都不会绘制 heve。但是,在 Jupyter 笔记本中,您需要显式禁用轴,因为内联后端会覆盖这些设置。
  • 同意。这应该被接受为答案。我为这个问题苦苦挣扎了好几天,只有这段代码解决了我的问题。我已经尝试了很多(几个)stackoverflow 技巧和技巧、解决方法等,但都没有成功。非常感谢@SuaveSouris。
【解决方案4】:

我从 Arvind Pereira (http://robotics.usc.edu/~ampereir/wordpress/?p=626) 那里找到了一些东西,并且似乎对我有用:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)

【讨论】:

  • transparent=True 会让它看起来没有问题,但它只会隐藏空白,图像尺寸不会好。
  • 感谢您提及pad_inches!我希望我早点知道这个选项!
  • 这适用于大多数情节,但这删除了我的混淆矩阵的右边框。只需添加一个小填充 pad_inches=.25
【解决方案5】:

以下函数包含上面的 johannes-s 答案。我已经用plt.figureplt.subplots() 对它进行了多轴测试,效果很好。

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')

【讨论】:

  • 工作就像一个魅力。上一个答案是我的导出中的一些必需命令。
【解决方案6】:

我发现以下代码非常适合这项工作。

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)

【讨论】:

  • 一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。
【解决方案7】:

我按照这个顺序,它就像一个魅力。

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)

【讨论】:

  • 其实我发现这个答案很简单,用起来更方便。
  • 这个对我有用;接受的答案没有。
  • 就我而言,在savefig 命令中使用bbox_inches='tight'pad_inches=0 两个参数使其完美运行。
【解决方案8】:

这对我有用 plt.savefig(save_path,bbox_inches='tight', pad_inches=0, transparent=True)

【讨论】:

  • 不确定这与此处发布的其他答案有什么不同。
【解决方案9】:

最直接的方法是使用plt.tight_layout 转换,这实际上更可取,因为它在使用plt.savefig 时不会进行不必要的裁剪

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')

但是,这对于修改图形的复杂绘图可能并不可取。如果是这种情况,请参阅使用plt.subplots_adjustJohannes S's answer

【讨论】:

    【解决方案10】:

    我发现一个更简单的方法是使用plt.imsave

        import matplotlib.pyplot as plt
        arr = plt.imread(path)
        plt.imsave('test.png', arr)
    

    【讨论】:

    • 被低估的答案。在长时间搜索如何使用plt.savefig() 保留分辨率和删除空格后,这对我有所帮助。
    • 这仅适用于您想要将数组 (!) 保存为图像的情况。这不允许保存任意图形。
    • 任意图像是什么意思?图像不是值数组吗?
    【解决方案11】:

    对于任何想要以像素而不是英寸工作的人来说,这都可以。

    加上平时你也需要的

    from matplotlib.transforms import Bbox
    

    然后你可以使用以下内容:

    my_dpi = 100 # Good default - doesn't really matter
    
    # Size of output in pixels
    h = 224
    w = 224
    
    fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)
    
    ax.set_position([0, 0, 1, 1]) # Critical!
    
    # Do some stuff
    ax.imshow(img)
    ax.imshow(heatmap) # 4-channel RGBA
    ax.plot([50, 100, 150], [50, 100, 150], color="red")
    
    ax.axis("off")
    
    fig.savefig("saved_img.png",
                bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
                dpi=my_dpi)
    

    【讨论】:

    • 你不必指定dpi,你可以使用默认的fig.dpi来代替
    【解决方案12】:

    因此解决方案取决于您是否调整子图。如果您指定 plt.subplots_adjust (top, bottom, right, left),您不想将 bbox_inches='tight' 的 kwargs 与 plt.savefig 一起使用,因为它自相矛盾地创建了空白填充。它还允许您将图像保存为与输入图像相同的暗度(600x600 输入图像另存为 600x600 像素输出图像)。

    如果您不关心输出图像大小的一致性,您可以省略 plt.subplots_adjust 属性,只需将 bbox_inches='tight' 和 pad_inches=0 kwargs 与 plt.savefig 一起使用。

    此解决方案适用于 matplotlib 版本 3.0.1、3.0.3 和 3.2.1。当您有超过 1 个子图(例如 plt.subplots(2,2,...))时,它也可以工作。

    def save_inp_as_output(_img, c_name, dpi=100):
        h, w, _ = _img.shape
        fig, axes = plt.subplots(figsize=(h/dpi, w/dpi))
        fig.subplots_adjust(top=1.0, bottom=0, right=1.0, left=0, hspace=0, wspace=0) 
        axes.imshow(_img)
        axes.axis('off')
        plt.savefig(c_name, dpi=dpi, format='jpeg') 
    

    【讨论】:

      【解决方案13】:

      你可以试试这个。它解决了我的问题。

      import matplotlib.image as mpimg
      img = mpimg.imread("src.png")
      mpimg.imsave("out.png", img, cmap=cmap)
      

      【讨论】:

        【解决方案14】:

        这适用于我将使用 imshow 绘制的 numpy 数组保存到文件

        import matplotlib.pyplot as plt
        
        fig = plt.figure(figsize=(10,10))
        plt.imshow(img) # your image here
        plt.axis("off")
        plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
                hspace = 0, wspace = 0)
        plt.savefig("example2.png", box_inches='tight', dpi=100)
        plt.show()
        

        【讨论】: