I've got a PyQT4 application that displays medium size images in a Matplotlib figure. The test image that I'm displaying is about 5Mb (2809 x 1241 pixels). I read in the data using GDAL by the way. The image is read into an array with nodata values masked out. This is then displayed with normalized values and a specified colormap
It seems to use an inordinate amount of memory to display a 5mb file. What I'm seeing is that it takes a 140mb of memory to display this image read in at full resolution. (application with imshow commented out used 60mb of memory, vs 206 with it) The problem gets worse as images are displayed in multiple figures as each one uses an additional 200m of memory. At about 3 or 4 figures displayed the applications starts bogging down as the memory usage gets into the 700-900 mb range.
I understand about matplotlib having to store all the pixels even though it's displaying only a downsampled subset to match the screen resolution. I'll probably end up writing routines to only read in an amount of pixels to match the figure size. But since this application will be displaying up to 8 maps on 8 separate screens I'm concerned about it still using excessive memory.
So my questions are:
1) Does this seem like an inordinate amount of memory to be using for displaying a simple colormapped image? It does to me.
2) Is there something I could be doing to decrease this memory usage? For example using integer datatypes, releasing memory, etc.
3) What other strategies should I be using to deal with this memory usage? For example downsampling (might not be very effective at full screen resolution 1900x1200), switching to 64bit architecture, etc
Thanks, Code below
import sys, os, random
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import matplotlib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.colors as colors
import numpy as np
from osgeo import gdal, gdalconst
gridfile = r"i:\vistrails\workingfiles\secondseason\secondseason_workfile_2012_02_28b\brt_1\brt_prob_map.tif"
class AppForm(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.create_main_frame()
ds = gdal.Open(gridfile, gdal.GA_ReadOnly)
ary = ds.GetRasterBand(1).ReadAsArray(buf_ysize=500, buf_xsize=300)
ndval = ds.GetRasterBand(1).GetNoDataValue()
rasterdata = np.ma.masked_array(ary, mask=(ary==ndval))
del ary
self.axes.imshow(rasterdataint, cmap=matplotlib.cm.jet)
del rasterdata
def create_main_frame(self):
self.main_frame = QWidget()
# Create the mpl Figure and FigCanvas objects.
# 5x4 inches, 100 dots-per-inch
#
self.dpi = 100
self.fig = Figure((5.0, 4.0), dpi=self.dpi)
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self.main_frame)
self.axes = self.fig.add_subplot(111)
self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
vbox = QVBoxLayout()
vbox.addWidget(self.canvas)
vbox.addWidget(self.mpl_toolbar)
self.main_frame.setLayout(vbox)
self.setCentralWidget(self.main_frame)
def main():
app = QApplication(sys.argv)
form = AppForm()
form.show()
app.exec_()
if __name__ == "__main__":
main()
Memory issue with use of imshow()
have been noticed, as here.
1/ Upgrade
As mentionned here, upgrading to latest vesion of mpl may fix the problem.
2/ PIL
As an alternative, you may make you of the PIL library.
When it goes to jpg files, imshow()
is using PIL if installed. You can use PIL module directly, as documented here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With