我一直在努力解决这个问题。我有一组图像,我对这些图像的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的内存,我想这就足够了。)
有没有人知道如何解决这个问题?
答案 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的内存即可。