Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scale image in matplotlib without changing the axis

I have a GUI that displays a plot. I want to fit that plot to an existing image. I displayed the image under the plot using:

myaxe.plot(...)
myaxeimage = myaxe.imshow(myimage, axpect='auto', extent=myaxe.axis(), zorder=-1)

I'm already able to play with the opacity of the image, using

myaxeimage.set_alpha()

Now I'd like to be able to zoom in and out and to move around the image, using the GUI, without touching to the existing plot and axes, in order to align it with my plot. In other words, I want to scale to given sx and sy factors, and to put origin of the image at a given (x,y) point, clipping parts of the image going outside the axes. How can I do that?

like image 566
Charles Brunet Avatar asked May 24 '13 19:05

Charles Brunet


People also ask

How do I resize a figure in Matplotlib?

Set the Height and Width of a Figure in Matplotlib Instead of the figsize argument, we can also set the height and width of a figure. These can be done either via the set() function with the figheight and figwidth argument, or via the set_figheight() and set_figwidth() functions.

How do you scale an image on Imshow?

Use the extent parameter of imshow to map the image buffer pixel coordinates to a data space coordinate system. Next, set the aspect ratio of the image manually by supplying a value such as "aspect=4" or let it auto-scale by using aspect='auto'. This will prevent stretching of the image.


1 Answers

There is a watermark example distributed with matplotlib that is sort of similar. Starting from that code, we can modify as follows:

Use ax.imshow to plot the image first. I do this because the extent parameter affects the final extent of ax. Since we want the final extent to be governed by the plt.plot(...), let's put it last.

myaximage = ax.imshow(im, aspect='auto', extent=(1,15,0.3,0.7), alpha=0.5, origin='upper', zorder=-1)

Instead of extent=myaxe.axis(), use extent to control the position and size of the image. extent=(1,15,0.3,0.7) places the image in the rectangle with (1, 0.3) as the bottom left corner and (15, 0.7) as the top right corner.

With origin='upper', the [0,0] index of the array im is placed at the upper left corner of the extent. With origin='lower' it would have been placed at the lower left corner.


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.image as image
np.random.seed(1)
datafile = cbook.get_sample_data('logo2.png', asfileobj=False)
im = image.imread(datafile)
fig, ax= plt.subplots()

myaximage = ax.imshow(im, aspect='auto', extent=(1,15,0.3,0.7), alpha=0.5, zorder=-1)
ax.plot(np.random.rand(20), '-o', ms=20, lw=2, alpha=1.0, mfc='orange')
ax.grid()
plt.show()

enter image description here


If you want to expand the image and clip it to the extent of the plot, you might need to use ax.set_xlim and ax.set_ylim as well:

myaximage = ax.imshow(im, aspect='auto', extent=(-1,25,0.3,0.7), alpha=0.5, zorder=-1,
                      origin='upper')

ax.plot(np.random.rand(20), '-o', ms=20, lw=2, alpha=1.0, mfc='orange')
ax.set_xlim(0,20)
ax.set_ylim(0,1)

enter image description here


Or, for more control, you can clip the image to an arbitrary path by using myaximage.set_clip_path:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.image as image
import matplotlib.patches as patches
np.random.seed(1)
datafile = cbook.get_sample_data('logo2.png', asfileobj=False)
im = image.imread(datafile)
fig, ax= plt.subplots()

myaximage = ax.imshow(im, aspect='auto', extent=(-5,25,0.3,0.7), 
                      alpha=0.5, origin='upper',
                      zorder=-2)
# patch = patches.Circle((300,300), radius=100)
patch = patches.Polygon([[5, 0.4], [15, 0.4], [15, 0.6], [5, 0.6]], closed=True,
                        transform=ax.transData)
myaximage.set_clip_path(patch)
ax.plot(np.random.rand(20), '-o', ms=20, lw=2, alpha=1.0, mfc='orange', 
        zorder=-1)

ax.set_xlim(0, 20)
ax.set_ylim(0, 1)

plt.show()

enter image description here

like image 55
unutbu Avatar answered Sep 28 '22 01:09

unutbu