pcolormesh使用内存

时间:2014-03-31 18:39:54

标签: python matplotlib

我一直在努力解决这个问题。我有一组图像,我对这些图像的X,Y坐标执行一些数学运算,然后使用pcolormesh绘制新图像。我已经完成的所有计算,我所做的就是加载新的X和新的Y,并使用pcolormesh中图像的颜色。

图像是2048x2448像素(比如大约5mp),第一张图像变得非常快,每张图像之后脚本变慢并占用更多内存。我尝试了一些垃圾收集,但它没有用。

我的剧本:

import numpy as np
from PIL import Image
import cPickle as pickle
import matplotlib.pyplot as plt
import os

# TRY forced garbage collection!
import gc

def rectify(cam_files, cam_rec_files, rec_file_location):
    ''' cam_files is a dictionary that contains the filenames with the camera-names as index
            example: {'KDXX04C' : C:\Users\Yorian\Desktop\TU\Stage Shore\python_files\Rectify, metadata and upload\v3\archive\KDXXXXX\original\snap\1381383000\{filename}.jpg }

        cam_rec_files_dir contains a dictionary, cameraName : fileLocation
            example: {'KDXX04C' : C:\Users\Yorian\Desktop\TU\Stage Shore\python_files\Rectify, metadata and upload\v3\camdata\KDXXXXX\KDXX04C.pkl }

        rec_file_location is a string that shows where the new rectification needs to be saved '''
    fig, ax = plt.subplots(1, 1, figsize=(60,90))

    for camname in cam_files:
        img = Image.open(cam_files[camname])
        img = np.asarray(img, dtype=np.uint8)
        height, width, channels = img.shape

        # load plot data
        fh = open(cam_rec_files[camname], 'rb')
        X = pickle.load(fh)
        Y = pickle.load(fh)

        masks = [X<=0, X>1500, Y>4000, Y<-4000]
        total_mask = masks[0] | masks[1] | masks[2] | masks[3]
        first_false = np.argwhere(total_mask == 0)
        start = int(first_false[0]/width)

        rgb = img.reshape((-1,3))/255.0
        rgba = np.concatenate((rgb, np.ones((rgb.shape[0],1), dtype=np.uint8)), axis=1)
        rgba[total_mask,3] = 0
        rgba = rgba.reshape((height,width,4))[:,:-1,:]
        rgba = rgba.reshape((-1,4))

        plotimg = ax.pcolormesh(X.reshape((height, width))[start:,:], Y.reshape((height, width))[start:,:], img.mean(-1)[start:,:], cmap='Greys') # img.mean(-1)

        plotimg.set_array(None)
        plotimg.set_edgecolor('none')
        plotimg.set_facecolor(rgba[(start*(width-1)):,:])

        fh.close()

    plt.savefig(rec_file_location)
    gc.collect()

它可以工作到六个图像,但是当我尝试八个例如我没有足够的内存(我使用python 64bit并且在我的计算机上有12gb的内存,我想这就足够了。)

有没有人知道如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

简而言之,如果您正在使用plt.close(fig)界面并想要生成大量数据而不显示它们,请在pyplot之后使用它。

每次调用rectify函数时,您都会创建一个新的(非常大的!!)数字,然后将其保留在内存中pyplot保留对该图的引用,以便在您调用plt.show()时显示该图。可以在不使用plt.close(fig)状态机的情况下调用pyplot或创建数字。 (fig.clf()也可以使用,但会保留对空白数字的引用。)

此外,鉴于您正在阅读图像文件,您的值可能是在常规的x和y网格上。如果是,请使用imshow代替pcolormesh。它的速度更快,内存效率更高。


作为第一个问题的示例,您的rectify函数基本上会执行类似的操作,并且您可能会重复调用它(如下面的循环所示):

import numpy as np
import matplotlib.pyplot as plt

def rectify():
    fig, ax = plt.subplots()
    ax.pcolormesh(np.random.random((10,10)))
    fig.savefig('blah.png')

for _ in range(10):
    rectify()

plt.show()

请注意,我们会弹出10个数字。 pyplot保留对该图的引用,以便可以使用show显示它。

如果要从pyplot状态机中删除该图,请致电plt.close(fig)

例如,如果您执行此操作,则不会显示任何数字:(每个数字都会被垃圾收集,因为您在通过调用plt.close(fig)从pyplot&#39; 。)

import numpy as np
import matplotlib.pyplot as plt

def rectify():
    fig, ax = plt.subplots()
    ax.pcolormesh(np.random.random((10,10)))
    fig.savefig('blah.png')
    plt.close(fig)

for _ in range(10):
    rectify()

plt.show()

或者,您可以绕过pyplot并直接制作图形和画布。 Pyplot的图形管理员不会参与其中,图形实例将按照您的预期进行垃圾收集。但是,这个方法相当冗长,并且假设您对matplotlib如何在幕后工作有所了解:

import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

# Don't need this, but just to demonstrate that `show()` has no effect...
import matplotlib.pyplot as plt

def rectify():
    fig = Figure()
    FigureCanvas(fig)
    ax = fig.add_subplot(1,1,1)
    ax.pcolormesh(np.random.random((10,10)))
    fig.savefig('blah.png')

for _ in range(10):
    rectify()

plt.show()

答案 1 :(得分:0)

如果清除用斧头存储的数据,则可以减少所需的内存。 在Joe Kington的rectify函数的末尾添加ax.clear()。那么程序只需要一个pcolormesh的内存即可。