6

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...

2
  • 1
    Why do you want to speed this up? Is it to increase responsiveness of the GUI or because you need to display many thousands of images and 2 seconds per image isn't fast enough? The answer may be different depending on the reason. In general, if you're using numpy's own methods, you'd be hard-pressed to better their performance as long as you stick to python, and depending on the methods, you might be hard-pressed to improve on them even in native code. 2 seconds to load a 1600x1200 image sounds ok to me. Commented Feb 20, 2011 at 19:21
  • The reason why I want to have this faster than 2 seconds is simple. When the program is in use one should be able to go through the pictures quite fast in order to obtain an overview. A time of .5 seconds would be great. The resolution is for this reason not so important. Once one has selected the interesting image the programm could load the full resolution file anyway... Commented Feb 21, 2011 at 8:59

3 Answers 3

5

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your answer and the sample code! As far as I understood this code affects only the file it saves. However, in my case I want to display the file with this size. To clearify this I added my sample-code above.
@sebastian: Does it take 2 seconds to display the lowres image? If that's true, I don't know how you could significantly speed that up. Secondly, matplotlib was not designed with speediness as a high priority. It may be faster to use imagemagick to generate all your thumbnails first, and a GUI framework like Tk, Gtk, Qt or wx to display the image. Finally, I don't think matplotlib can control the size and position of the figure's window. At least on Linux, that's controlled by the window manager.
No, it takes 2 seconds to display the high-resolution image 1200x1600 Pixel. I think that one should be able to tell matplotlib that it should take a 300x400 Pixel picture and display it like a 1200x1600 one by making 16 pixel out of one while displaying it...
3

You can disable the default interpolation of imshow by adding the following line to your matplotlibrc file (typically at ~/.matplotlib/matplotlibrc):

image.interpolation : none

The result is much faster rendering and crisper images.

Comments

1

I found a solution as long as one needs to display only low-resolution images. One can do so using the line

im  = matplotlib.pyplot.imshow(img,cmap=matplotlib.cm.gray, origin='centre',extent=(0,1600,0,1200))

where the extent-parameter tells matplotlib to plot the figure over this range. If one uses an image which has a lower resolution, this speeds up the process quite a lot. Nevertheless it would be great if somebody knows additional tricks to make the process even faster in order to use a higher resolution with the same speed.

Thanks to everyone who thought about my problem, further remarks are appreciated!!!

1 Comment

Doesn't this crop your image and only show you a small piece of it?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.