Plot semi transparent contour plot over image file using matplotlib

11,562

You basically need to do two things, set the extent of the image you want in the background. If you dont, the coordinates are assumed to be pixel coordinates, in this case 0 till 600 for both x and y. So adjust you imshow command to:

implot = subplot1.imshow(pyplot.imread(r'test.png'), interpolation='nearest', 
                         alpha=0.5, extent=[-2500.0,2500.0,-2500.0,2500.0])

If you want to stretch the image to the limits of the plot automatically, you can grab the extent with:

extent = subplot1.get_xlim()+ subplot1.get_ylim()

And pass it to imshow as extent=extent.

Since its the background image, setting the alpha to 0.5 makes it very faint, i would set it to 1.0.

Secondly, you set the alpha of the contour lines, but you probably also (or especially) want to set the alpha of the filled contours. And when you use alpha with filled contours, enabling anti-aliasing reduces artifacts. So change your contourf command to:

pp = pyplot.contourf(x,y,z,levels=levels,cmap=cmap, alpha=.5, antialiased=True)

And since you already create the subplot object yourself, i would advice also using it to do the plotting instead of the pyplot interface, which operates on the currently active axes.

So:

subplot1.contourf()
etc

Instead of:

pyplot.contourf()

With the two changes mentioned above, my result looks like:

enter image description here

Share:
11,562
HotDogCannon
Author by

HotDogCannon

Updated on June 17, 2022

Comments

  • HotDogCannon
    HotDogCannon almost 2 years

    I'd like to plot a transparent contour plot over an image file in matplotlib/pyplot.

    Here's what I got so far...

    I have a 600x600 pixel square image file test.png that looks like so:

    enter image description here

    I would like to plot a contour plot over this image (having the image file be 'below' and a semi-transparent version of the contour plot overlaid) using matplotlib and pyplot. As a bonus, the image would be automatically scaled to fit within the current plotting boundaries. My example plotting script is as follows:

    from matplotlib import pyplot
    from matplotlib.ticker import MultipleLocator, FormatStrFormatter
    from matplotlib.colors import BoundaryNorm
    from matplotlib.ticker import MaxNLocator
    from pylab import *
    import numpy as np
    import random
    
    # ----------------------------- #
    
    dx, dy = 500.0, 500.0
    y, x = np.mgrid[slice(-2500.0, 2500.0 + dy, dy),slice(-2500.0, 2500.0 + dx, dx)]
    
    z = []
    for i in x:
        z.append([])
        for j in y:
            z[-1].append(random.uniform(80.0,100.0))
    
    # ----------------------------- #
    
    plot_aspect = 1.2
    plot_height = 10.0
    plot_width = int(plot_height*plot_aspect)
    
    # ----------------------------- #
    
    pyplot.figure(figsize=(plot_width, plot_height), dpi=100)
    pyplot.subplots_adjust(left=0.10, right=1.00, top=0.90, bottom=0.06, hspace=0.30)
    subplot1 = pyplot.subplot(111)
    
    # ----------------------------- #
    
    cbar_max = 100.0
    cbar_min = 80.0
    cbar_step = 1.0
    cbar_num_colors = 200
    cbar_num_format = "%d"
    
    # ----------
    
    levels = MaxNLocator(nbins=cbar_num_colors).tick_values(cbar_min, cbar_max)
    cmap = pyplot.get_cmap('jet')
    norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
    pp = pyplot.contourf(x,y,z,levels=levels,cmap=cmap)
    cbar = pyplot.colorbar(pp, orientation='vertical', ticks=np.arange(cbar_min, cbar_max+cbar_step, cbar_step), format=cbar_num_format)
    cbar.ax.set_ylabel('Color Scale [unit]', fontsize = 16, weight="bold")
    
    # ----------
    
    CS = pyplot.contour(x,y,z, alpha=0.5)
    
    # ----------
    
    majorLocator1   = MultipleLocator(500)
    majorFormatter1 = FormatStrFormatter('%d')
    minorLocator1   = MultipleLocator(250)
    
    subplot1.xaxis.set_major_locator(majorLocator1)
    subplot1.xaxis.set_major_formatter(majorFormatter1)
    subplot1.xaxis.set_minor_locator(minorLocator1)
    
    pyplot.xticks(fontsize = 16)
    pyplot.xlim(-2500.0,2500.0)
    
    # ----------
    
    majorLocator2   = MultipleLocator(500)
    majorFormatter2 = FormatStrFormatter('%d')
    minorLocator2   = MultipleLocator(250)
    
    subplot1.yaxis.set_major_locator(majorLocator2)
    subplot1.yaxis.set_major_formatter(majorFormatter2)
    subplot1.yaxis.set_minor_locator(minorLocator2)
    
    pyplot.yticks(fontsize = 16)
    pyplot.ylim(-2500.0,2500.0)
    
    # ----------
    
    subplot1.xaxis.grid()
    subplot1.yaxis.grid()
    
    # ----------
    
    subplot1.axes.set_aspect('equal')
    
    # ----------
    
    pyplot.suptitle('Main Title', fontsize = 24, weight="bold")
    
    # ----------
    
    pyplot.xlabel('X [m]', fontsize=16, weight="bold")
    pyplot.ylabel('Y [m]', fontsize=16, weight="bold")
    
    # ----------
    
    implot = subplot1.imshow( pyplot.imread('test.png') , interpolation='nearest', alpha=0.5)
    
    # ----------
    pyplot.show()
    #pyplot.savefig("tmp.png", dpi=100)
    pyplot.close()
    

    ...but I'm not getting the result I want... instead I just see the contour plot part. Something like:

    enter image description here

    What should I do in my code to get what I want?