Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excessive memory usage in Matplotlib imshow

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()
like image 432
Colin Talbert Avatar asked Nov 13 '22 09:11

Colin Talbert


1 Answers

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.

like image 92
kiriloff Avatar answered Dec 10 '22 12:12

kiriloff