【问题标题】:Save plot to image file instead of displaying it using Matplotlib将绘图保存到图像文件而不是使用 Matplotlib 显示它
【发布时间】:2012-03-26 04:50:39
【问题描述】:

我正在编写一个快速而肮脏的脚本来动态生成绘图。我使用下面的代码(来自Matplotlib 文档)作为起点:

from pylab import figure, axes, pie, title, show

# Make a square figure and axes
figure(1, figsize=(6, 6))
ax = axes([0.1, 0.1, 0.8, 0.8])

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

explode = (0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
title('Raining Hogs and Dogs', bbox={'facecolor': '0.8', 'pad': 5})

show()  # Actually, don't show, just save to foo.png

我不想在 GUI 上显示绘图,相反,我想将绘图保存到文件(例如 foo.png)中,以便例如在批处理脚本中使用。我该怎么做?

【问题讨论】:

标签: python matplotlib plot


【解决方案1】:

虽然问题已得到解答,但我想在使用matplotlib.pyplot.savefig 时添加一些有用的提示。文件格式可以通过扩展名指定:

from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

将分别给出光栅化或矢量化输出,两者都可能有用。此外,图像周围通常会有不受欢迎的空白,可以通过以下方式删除:

plt.savefig('foo.png', bbox_inches='tight')

注意,如果显示绘图,plt.show() 应该跟在plt.savefig() 后面,否则文件图像将是空白的。

【讨论】:

    【解决方案2】:

    正如其他人所说,plt.savefig()fig1.savefig() 确实是保存图像的方式。

    但是我发现在某些情况下总是显示该数字。 (例如,使用具有plt.ion() 的 Spyder:交互模式 = On。)我通过使用 plt.close(figure_object) 强制关闭我的巨型循环中的图形窗口来解决此问题(请参阅documentation),所以我没有循环期间的百万开放数字:

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
    ax.plot([0,1,2], [10,20,3])
    fig.savefig('path/to/save/image/to.png')   # save the figure to file
    plt.close(fig)    # close the figure window
    

    如果需要,您应该可以稍后使用 fig.show() 重新打开该图(我自己没有测试)。

    【讨论】:

    【解决方案3】:

    解决办法是:

    pylab.savefig('foo.png')
    

    【讨论】:

    • pylab 未定义
    【解决方案4】:

    刚刚在 MatPlotLib 文档中找到了这个链接,该链接正好解决了这个问题: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

    他们说防止图形弹出的最简单方法是使用非交互式后端(例如 Agg),通过matplotib.use(<backend>),例如:

    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    plt.plot([1,2,3])
    plt.savefig('myfig')
    

    我个人仍然更喜欢使用plt.close( fig ),从那时起,您可以选择隐藏某些数字(在循环期间),但仍显示用于循环后数据处理的数字。不过,它可能比选择非交互式后端要慢 - 如果有人对此进行测试会很有趣。

    更新:对于Spyder,你通常不能这样设置后端(因为Spyder通常会提前加载matplotlib,阻止你使用matplotlib.use())。

    改为使用plt.switch_backend('Agg'),或在 Spyder 首选项中关闭“启用支持”并自行运行matplotlib.use('Agg') 命令。

    从这两个提示:onetwo

    【讨论】:

    • 这非常适用于您没有设置显示器的情况。如果os.environ['DISPLAY'] 设置不正确,使用另一个带有.plot() 的后端会引发错误。
    • 谢谢。这对于没有互联网连接并且需要系统管理员安装任何软件包的生产服务器非常有用。
    • 我喜欢 matplotlib 网站关于“后端”的描述/定义的教程:matplotlib.org/tutorials/introductory/…
    【解决方案5】:

    如果您不喜欢“当前”图形的概念,请执行以下操作:

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

    【讨论】:

    • 这不是把src.png复制到out.png吗?
    • 这只是一个例子,如果你有一个图像对象(img),那么你可以用.imsave()方法将它保存到文件中。
    • @wonder.mice 将帮助展示如何在不使用当前图形的情况下创建图像。
    • @wonder.mice 感谢这个例子,这是第一个向我展示如何将图像对象保存到 .png 的例子。
    • @scry 您并不总是需要创建图像,有时您尝试一些代码并想要视觉输出,这在这种情况下很方便。
    【解决方案6】:
    import datetime
    import numpy as np
    from matplotlib.backends.backend_pdf import PdfPages
    import matplotlib.pyplot as plt
    
    # Create the PdfPages object to which we will save the pages:
    # The with statement makes sure that the PdfPages object is closed properly at
    # the end of the block, even if an Exception occurs.
    with PdfPages('multipage_pdf.pdf') as pdf:
        plt.figure(figsize=(3, 3))
        plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
        plt.title('Page One')
        pdf.savefig()  # saves the current figure into a pdf page
        plt.close()
    
        plt.rc('text', usetex=True)
        plt.figure(figsize=(8, 6))
        x = np.arange(0, 5, 0.1)
        plt.plot(x, np.sin(x), 'b-')
        plt.title('Page Two')
        pdf.savefig()
        plt.close()
    
        plt.rc('text', usetex=False)
        fig = plt.figure(figsize=(4, 5))
        plt.plot(x, x*x, 'ko')
        plt.title('Page Three')
        pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
        plt.close()
    
        # We can also set the file's metadata via the PdfPages object:
        d = pdf.infodict()
        d['Title'] = 'Multipage PDF Example'
        d['Author'] = u'Jouni K. Sepp\xe4nen'
        d['Subject'] = 'How to create a multipage pdf file and set its metadata'
        d['Keywords'] = 'PdfPages multipage keywords author title subject'
        d['CreationDate'] = datetime.datetime(2009, 11, 13)
        d['ModDate'] = datetime.datetime.today()
    

    【讨论】:

    • plt.close() 正是我想要的!
    【解决方案7】:

    其他答案都是正确的。但是,我有时会发现我想稍后再打开图object。例如,我可能想要更改标签大小、添加网格或进行其他处理。在一个完美的世界里,我会简单地重新运行生成情节的代码,并调整设置。唉,世界并不完美。因此,除了保存为 PDF 或 PNG 之外,我还添加:

    with open('some_file.pkl', "wb") as fp:
        pickle.dump(fig, fp, protocol=4)
    

    这样,我以后可以加载图形对象并随意操作设置。

    我还将堆栈中的每个函数/方法的源代码和 locals() 字典写出堆栈,以便我以后可以准确地知道生成该图形的原因。

    注意:请小心,因为有时这种方法会生成巨大的文件。

    【讨论】:

    • 在 jupyter notebook 中进行开发会不会更容易,内联数字?这样您就可以准确地跟踪历史记录,甚至可以重新运行它。
    • @CiprianTomoiaga 我从不从交互式 Python shell(Jupyter 或其他)生成生产图。我从脚本中绘制所有内容。
    【解决方案8】:

    在使用 plot() 和其他函数创建您想要的内容后,您可以使用这样的子句来选择是打印到屏幕还是打印到文件:

    import matplotlib.pyplot as plt
    
    fig = plt.figure(figsize=(4, 5))       # size in inches
    # use plot(), etc. to create your plot.
    
    # Pick one of the following lines to uncomment
    # save_file = None
    # save_file = os.path.join(your_directory, your_file_name)  
    
    if save_file:
        plt.savefig(save_file)
        plt.close(fig)
    else:
        plt.show()
    

    【讨论】:

    • 有人说fig = plt.figure(figuresize=4, 5)可能是fig = plt.figure(figsize=(4, 5)) #figure sizes in inches
    【解决方案9】:

    我使用了以下内容:

    import matplotlib.pyplot as plt
    
    p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
    p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
    plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)
    
    plt.savefig('data.png')  
    plt.show()  
    f.close()
    plt.close()
    

    发现保存图后使用plt.show很重要,否则无法使用。figure exported in png

    【讨论】:

    • 对不起,这是什么?绘制的图像文件? f= plt.savefig('data.png')
    【解决方案10】:

    如果像我一样使用 Spyder IDE,则必须使用以下命令禁用交互模式:

    plt.ioff()

    (该命令随科学启动自动启动)

    如果您想再次启用它,请使用:

    plt.ion()

    【讨论】:

      【解决方案11】:

      你可以这样做:

      plt.show(hold=False)
      plt.savefig('name.pdf')
      

      记得在关闭 GUI 绘图之前让 savefig 完成。这样您就可以事先看到图像。

      或者,您可以使用plt.show() 查看它 然后关闭 GUI 并再次运行脚本,但这次将 plt.show() 替换为 plt.savefig()

      或者,您可以使用

      fig, ax = plt.figure(nrows=1, ncols=1)
      plt.plot(...)
      plt.show()
      fig.savefig('out.pdf')
      

      【讨论】:

      • 得到了一个意外的关键字参数'hold'
      【解决方案12】:

      根据问题Matplotlib (pyplot) savefig outputs blank image

      需要注意的一点:如果你使用plt.show,并且它应该在plt.savefig之后,否则你会给出一个空白图像。

      一个详细的例子:

      import numpy as np
      import matplotlib.pyplot as plt
      
      
      def draw_result(lst_iter, lst_loss, lst_acc, title):
          plt.plot(lst_iter, lst_loss, '-b', label='loss')
          plt.plot(lst_iter, lst_acc, '-r', label='accuracy')
      
          plt.xlabel("n iteration")
          plt.legend(loc='upper left')
          plt.title(title)
          plt.savefig(title+".png")  # should before plt.show method
      
          plt.show()
      
      
      def test_draw():
          lst_iter = range(100)
          lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
          # lst_loss = np.random.randn(1, 100).reshape((100, ))
          lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
          # lst_acc = np.random.randn(1, 100).reshape((100, ))
          draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")
      
      
      if __name__ == '__main__':
          test_draw()
      

      【讨论】:

        【解决方案13】:

        解决方案:

        import pandas as pd
        import numpy as np
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.style.use('ggplot')
        ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
        ts = ts.cumsum()
        plt.figure()
        ts.plot()
        plt.savefig("foo.png", bbox_inches='tight')
        

        如果您确实想显示图像并保存图像,请使用:

        %matplotlib inline
        

        之后 import matplotlib

        【讨论】:

          【解决方案14】:

          使用matplotlib.pyplot 时,必须先保存绘图,然后使用以下两行将其关闭:

          fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
          plt.close(fig) # close the figure window
          

          【讨论】:

            【解决方案15】:
            import matplotlib.pyplot as plt
            plt.savefig("image.png")
            

            在 Jupyter Notebook 中,您必须删除 plt.show() 并添加 plt.savefig(),以及一个单元格中的其余 plt 代码。 图片仍会显示在您的笔记本中。

            【讨论】:

              【解决方案16】:

              除上述内容外,我还为名称添加了__file__,以便图片和 Python 文件具有相同的名称。我还添加了一些参数以使其看起来更好:

              # Saves a PNG file of the current graph to the folder and updates it every time
              # (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
              plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
              # Hard coded name: './test.png'
              

              【讨论】:

                【解决方案17】:

                鉴于今天(提出这个问题时不可用)很多人使用 Jupyter Notebook 作为 python 控制台,有一种非常简单的方法可以将绘图保存为.png,只需调用matplotlib 的@来自 Jupyter Notebook 的 987654323@ 类,绘制图形“内联”jupyter 单元格,然后将该图形/图像拖到本地目录。不要忘记 %matplotlib inline 在第一行!

                【讨论】:

                • 这是个好主意,只需要注意如果图像嵌入笔记本中对文件大小的影响..
                【解决方案18】:

                只是一个额外的说明,因为我还不能评论帖子。

                如果您正在使用plt.savefig('myfig') 或类似的内容,请确保在保存图像后添加plt.clf()。这是因为 savefig 不会关闭绘图,如果您在没有 plt.clf() 的情况下添加到绘图中,您将添加到上一个绘图中。

                您可能不会注意到您的情节是否与前一个情节相似,但如果您在循环中保存图形,情节将慢慢变得庞大,并使您的脚本非常缓慢。

                【讨论】:

                  【解决方案19】:

                  如前所述,您可以使用:

                  import matplotlib.pyplot as plt
                  plt.savefig("myfig.png")
                  

                  用于保存您正在显示的任何 IPhython 图像。或者换一种说法(从不同的角度看),如果你曾经使用过 open cv,或者如果你已经导入了 open cv,你可以去:

                  import cv2
                  
                  cv2.imwrite("myfig.png",image)
                  

                  但这只是以防万一您需要使用 Open CV。否则plt.savefig() 就足够了。

                  【讨论】:

                    【解决方案20】:

                    好吧,我确实建议使用包装器来渲染或控制绘图。示例可以是 mpltex (https://github.com/liuyxpp/mpltex) 或 prettyplotlib (https://github.com/olgabot/prettyplotlib)。

                    import mpltex
                    
                    @mpltex.acs_decorator
                    def myplot():
                      plt.figure()
                      plt.plot(x,y,'b-',lable='xxx')
                      plt.tight_layout(pad=0.5)
                      plt.savefig('xxxx')  # the figure format was controlled by the decorator, it can be either eps, or pdf or png....
                      plt.close()
                    

                    我基本上经常使用这个装饰器在美国化学学会、美国物理学会、美国光学学会、Elsivier 等各种期刊上发表学术论文。

                    可以找到一个示例,如下图 (https://github.com/MarkMa1990/gradientDescent):

                    【讨论】:

                      【解决方案21】:

                      您可以使用任何扩展名(png、jpg 等)和您想要的分辨率保存您的图像。这是一个保存图形的功能。

                      import os
                      
                      def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
                          path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
                          print("Saving figure", fig_id)
                          if tight_layout:
                              plt.tight_layout()
                          plt.savefig(path, format=fig_extension, dpi=resolution)
                      

                      'fig_id' 是您要用来保存图形的名称。希望对你有帮助:)

                      【讨论】:

                        【解决方案22】:

                        你可以这样做:

                        def plotAFig():
                          plt.figure()
                          plt.plot(x,y,'b-')
                          plt.savefig("figurename.png")
                          plt.close()
                        

                        【讨论】:

                          【解决方案23】:

                          没有什么对我有用。问题是保存的图像非常小,我不知道怎么把它变大。

                          这似乎使它变大了,但仍然不是全屏。

                          https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.set_size_inches

                          fig.set_size_inches((w, h))

                          希望对某人有所帮助。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2018-04-23
                            • 1970-01-01
                            • 1970-01-01
                            • 2021-05-25
                            相关资源
                            最近更新 更多