Scale image in matplotlib without changing the axis

后端 未结 2 1618
离开以前
离开以前 2021-01-02 23:13

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 = mya         


        
相关标签:
2条回答
  • 2021-01-02 23:35

    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

    0 讨论(0)
  • 2021-01-02 23:41

    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
    
    0 讨论(0)
提交回复
热议问题