7

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?

1
  • 1
    maybe use a second axes and see if you can make it transparent (not sure that is possible though). Commented May 24, 2013 at 20:19

2 Answers 2

9

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

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

Comments

0

Finally, I followed tcaswell suggestion and used 2 different axes. This way, I simply have to play with set_xlim() and set_ylim() of my image axes to change the origin and/or the zooming factor of my image. I order to get the image below my plot, without hiding it with the frame of the plot, I removed the frame of the plot and used the frame of the image axes instead. I also hidden the ticks from the image axes.

from matplotlib import pyplot

f = pyplot.figure()
a = f.add_subplot(111, frameon=False) # Remove frame
a.plot(...)

myimg = pyplot.imread(...)
imgaxes = f.add_axes(a.get_position(), # new axes with same position
    label='image', # label to ensure imgaxes is different from a
    zorder=-1, # put image below the plot
    xticks=[], yticks=[]) # remove the ticks
img = imgaxes.imshow(myimg, aspect='auto') # ensure image takes all the place

# now, to modify things
img.set_alpha(...)
imgaxes.set_xlim((x1, x2)) # x1 and x2 must be calculated from
                           # image size, origin, and zoom factor

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.