【问题标题】:matplotlib savefig performance, saving multiple pngs within loopmatplotlib savefig 性能,在循环中保存多个 png
【发布时间】:2016-12-08 11:01:30
【问题描述】:

我希望找到一种方法来优化以下情况。我有一个用 matplotlib 的 imshow 创建的大型等高线图。然后我想使用这个等高线图来创建大量 png 图像,其中每个图像都是通过改变 x 和 y 限制以及纵横比的轮廓图像的一小部分。

所以循环中没有绘图数据发生变化,只有轴限制和纵横比在每个 png 图像之间发生变化。

以下 MWE 在“figs”文件夹中创建了 70 张 png 图像,展示了简化的想法。 fig.savefig('figs/'+filename) 占用了大约 80% 的运行时间。

我研究了以下内容,但没有提出改进意见:

  • matplotlib 的替代方案,专注于速度 - 我一直在努力寻找具有类似要求的等高线/曲面图的任何示例/文档
  • Multiprocessing -- 我在这里看到的类似问题似乎需要在循环中调用 fig = plt.figure()ax.imshow,因为 fig 和 ax 不能被腌制。就我而言,这将比通过实现多处理实现的任何速度提升都要昂贵。

如果您有任何见解或建议,我将不胜感激。

import numpy as np
import matplotlib as mpl
mpl.use('agg')
import matplotlib.pyplot as plt
import time, os

def make_plot(x, y, fix, ax):
    aspect = np.random.random(1)+y/2.0-x
    xrand = np.random.random(2)*x
    xlim = [min(xrand), max(xrand)]
    yrand = np.random.random(2)*y
    ylim = [min(yrand), max(yrand)]
    filename = '{:d}_{:d}.png'.format(x,y)

    ax.set_aspect(abs(aspect[0]))
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
    fig.savefig('figs/'+filename)

if not os.path.isdir('figs'):
    os.makedirs('figs')
data = np.random.rand(25, 25)

fig = plt.figure()
ax = fig.add_axes([0., 0., 1., 1.])
# in the real case, imshow is an expensive calculation which can't be put inside the loop
ax.imshow(data, interpolation='nearest')

tstart = time.clock()
for i in range(1, 8):
    for j in range(3, 13):
        make_plot(i, j, fig, ax)

print('took {:.2f} seconds'.format(time.clock()-tstart))

【问题讨论】:

    标签: python performance matplotlib png imshow


    【解决方案1】:

    由于这种情况下的限制是对plt.savefig() 的调用,因此无法进行很多优化。在内部,该图形是从头开始渲染的,这需要一段时间。可能减少要绘制的顶点数量可能会减少一点时间。

    在我的机器(Win 8, i5 with 4 cores 3.5GHz)上运行代码的时间是 2.5 秒。这似乎还不算太糟糕。使用 Multiprocessing 可以获得一点改进。

    关于多处理的说明:在multiprocessing 中使用 pyplot 的状态机似乎完全可以工作,这似乎令人惊讶。但确实如此。 在这种情况下,由于每个图像都基于相同的图形和轴对象,因此甚至不必创建新的图形和轴。

    我不久前针对您的情况修改了answer I gave here,使用多处理和 4 个内核上的 5 个进程,总时间大致减半。我附加了一个显示多处理效果的条形图。

    import numpy as np
    #import matplotlib as mpl
    #mpl.use('agg') # use of agg seems to slow things down a bit
    import matplotlib.pyplot as plt
    import multiprocessing
    import time, os
    
    def make_plot(d):
        start = time.clock()
        x,y=d
        #using aspect in this way causes a warning for me
        #aspect = np.random.random(1)+y/2.0-x 
        xrand = np.random.random(2)*x
        xlim = [min(xrand), max(xrand)]
        yrand = np.random.random(2)*y
        ylim = [min(yrand), max(yrand)]
        filename = '{:d}_{:d}.png'.format(x,y)
        ax = plt.gca()
        #ax.set_aspect(abs(aspect[0]))
        ax.set_xlim(xlim)
        ax.set_ylim(ylim)
        plt.savefig('figs/'+filename)
        stop = time.clock()
        return np.array([x,y, start, stop])
    
    if not os.path.isdir('figs'):
        os.makedirs('figs')
    data = np.random.rand(25, 25)
    
    fig = plt.figure()
    ax = fig.add_axes([0., 0., 1., 1.])
    ax.imshow(data, interpolation='nearest')
    
    
    some_list = []
    for i in range(1, 8):
        for j in range(3, 13):
            some_list.append((i,j))
    
    
    if __name__ == "__main__":
        multiprocessing.freeze_support()
        tstart = time.clock()
        print tstart
        num_proc = 5
        p = multiprocessing.Pool(num_proc)
    
        nu = p.map(make_plot, some_list)
    
        tooktime = 'Plotting of {} frames took {:.2f} seconds'
        tooktime = tooktime.format(len(some_list), time.clock()-tstart)
        print tooktime
        nu = np.array(nu)
    
        plt.close("all")
        fig, ax = plt.subplots(figsize=(8,5))
        plt.suptitle(tooktime)
        ax.barh(np.arange(len(some_list)), nu[:,3]-nu[:,2], 
                height=np.ones(len(some_list)), left=nu[:,2],  align="center")
        ax.set_xlabel("time [s]")
        ax.set_ylabel("image number")
        ax.set_ylim([-1,70])
        plt.tight_layout()
        plt.savefig(__file__+".png")
        plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-07
      • 2021-08-21
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多