Python matplotlib imshow is slow


Question

I want to display an image file using imshow. It is an 1600x1200 grayscale image and I found out that matplotlib uses float32 to decode the values. It takes about 2 seconds to load the image and I would like to know if there is any way to make this faster. The point is that I do not really need a high resolution image, I just want to mark certain points and draw the image as a background. So,

  • First question: Is 2 seconds a good performance for such an image or can I speed up.
  • Second question: If it is good performance how can I make the process faster by reducing the resolution. Important point: I still want the image to strech over 1600x1200 Pixel in the end.

My code:

import matplotlib
import numpy

plotfig     = matplotlib.pyplot.figure()
plotwindow  = plotfig.add_subplot(111)
plotwindow.axis([0,1600,0,1200])
plotwindow.invert_yaxis() 
img = matplotlib.pyplot.imread("lowres.png")
im  = matplotlib.pyplot.imshow(img,cmap=matplotlib.cm.gray,origin='centre')
plotfig.set_figwidth(200.0)
plotfig.canvas.draw()
matplotlib.pyplot.show()

This is what I want to do. Now if the picture saved in lowres.png has a lower resolution as 1600x1200 (i.e. 400x300) it is displayed in the upper corner as it should. How can I scale it to the whole are of 1600x1200 pixel? If I run this program the slow part comes from the canvas.draw() command below. Is there maybe a way to speed up this command?

Thank you in advance!

According to your suggestions I have updated to the newest version of matplotlib

version 1.1.0svn, checkout 8988

And I also use the following code:

img = matplotlib.pyplot.imread(pngfile)
img *= 255
img2 = img.astype(numpy.uint8)
im  = self.plotwindow.imshow(img2,cmap=matplotlib.cm.gray, origin='centre')

and still it takes about 2 seconds to display the image... Any other ideas?

Just to add: I found the following feature

zoomed_inset_axes

So in principle matplotlib should be able to do the task. There one can also plot a picture in a "zoomed" fashion...

1
4
11/28/2011 3:28:00 PM

The size of the data is independent of the pixel dimensions of the final image.

Since you say you don't need a high-resolution image, you can generate the image quicker by down-sampling your data. If your data is in the form of a numpy array, a quick and dirty way would be to take every nth column and row with data[::n,::n].

You can control the output image's pixel dimensions with fig.set_size_inches and plt.savefig's dpi parameter:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

data=np.arange(300).reshape((10,30))
plt.imshow(data[::2,::2],cmap=cm.Greys)

fig=plt.gcf()
# Unfortunately, had to find these numbers through trial and error
fig.set_size_inches(5.163,3.75)  
ax=plt.gca()
extent=ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())

plt.savefig('/tmp/test.png', dpi=400,
            bbox_inches=extent)

enter image description here

5
2/20/2011 10:05:43 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon