Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python matplotlib imshow is slow

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

like image 904
r6d9 Avatar asked Feb 20 '11 18:02

r6d9


People also ask

What is the use of imshow in Matplotlib?

matplotlib.pyplot.imshow () Function: The imshow () function in pyplot module of matplotlib library is used to display data as an image; i.e. on a 2D regular raster.

Why is Matplotlib so slow to display data?

Just a quick note, depending on your exact use case, matplotlib may not be a great choice. It's oriented towards publication-quality figures, not real-time display. However, there are a lot of things you can do to speed this example up. There are two main reasons why this is as slow as it is. 1) Calling fig.canvas.draw () redraws everything.

How to fix the smooth animations of a Matplotlib plot?

Both these can be fixed by using blitting. To do blitting efficiently, you'll have to use backend-specific code. In practice, if you're really worried about smooth animations, you're usually embedding matplotlib plots in some sort of gui toolkit, anyway, so this isn't much of an issue.

How to change aspect ratio in Matplotlib using Pyplot?

Syntax: pyplot.imshow (image, aspect=’value’) We can replace the value for the aspect ratio with ‘equal’, ‘auto’, or any float value representing the desired aspect ratio. For this article, we have used the below image to demonstrate the changes in aspect ratio using Matplotlib.


1 Answers

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

like image 52
unutbu Avatar answered Sep 30 '22 11:09

unutbu