Search code examples
pythonnumpyimage-processingpython-imaging-library

Overlaying images on python


I have these three pictures from a SEM Microscope. One is the actual picture whilst the other two just indicated the presence of specific elements (Aluminium and Silicon) on the sample.

I'd like to overlay them using Numpy and matplotlib so that I can then see where exactly the elements are, however not sure how to approach this on python, so far I've only gone as far as reading the picture files as np arrays:

image_SEM = np.asarray(Image.open('Project_SEI.JPG'))
image_Al = np.asarray(Image.open('Project_Al K.JPG'))
image_Si = np.asarray(Image.open('Project_Si K.JPG'))

Thank you!

enter image description here enter image description here enter image description here


Solution

  • I would be inclined to paste Si and Al images using a mask so that they only affect the SEM image where they are coloured and not where they are black/grey - else you will tend to reduce the contrast of your base image:

    from PIL import Image
    
    # Load images
    sei = Image.open('sei.jpg')
    si = Image.open('si.jpg')
    al = Image.open('al.jpg')
    
    # Make mask which only allows coloured areas to show
    siMask = si.convert('L')
    siMask.save('DEBUG-siMask.jpg')
    
    # Paste Si image over SEM image with transparency mask
    sei.paste(si, siMask)
    
    # Make mask which only allows coloured areas to show
    alMask = al.convert('L')
    alMask.save('DEBUG-alMask.jpg')
    
    # Paste Al image over SEM image with transparency mask
    sei.paste(al, alMask)
    sei.save('result.png')
    

    DEBUG-siMask.jpg

    enter image description here

    DEBUG-alMask.jpg

    enter image description here

    result.jpg

    enter image description here


    Note that you could enhance the masks before use - for example you could median filter to remove small speckles, or you could contrast stretch to make the magenta/yellow shading come out more or less solid. For example, you can see the yellow is more solid than the magenta, which is because the yellow mask is brighter, so you could threshold the magenta mask to make it pure black and white which would make the magenta come out solid.

    So, I median-filtered out the speckles and changed the masking so that coloured areas are 50% transparent like this:

    #!/usr/bin/env python3
    
    from PIL import Image, ImageFilter
    
    # Load images
    sei = Image.open('sei.jpg')
    si = Image.open('si.jpg')
    al = Image.open('al.jpg')
    
    # Make mask which only allows coloured areas to show
    siMask = si.convert('L')
    # Median filter mask to remove small speckles
    siMask = siMask.filter(ImageFilter.MedianFilter(5))
    # Threshold mask and set opacity to 50% for coloured areas
    siMask = siMask.point(lambda p: 128 if p > 50 else 0)
    siMask.save('DEBUG-siMask.jpg')
    
    # Paste Si image over SEM image with transparency mask
    sei.paste(si, siMask)
    
    # Make mask which only allows coloured areas to show
    alMask = al.convert('L')
    # Median filter mask to remove small speckles
    alMask = alMask.filter(ImageFilter.MedianFilter(5))
    # Threshold mask and set opacity to 50% for coloured areas
    alMask = alMask.point(lambda p: 128 if p > 50 else 0)
    alMask.save('DEBUG-alMask.jpg')
    
    # Paste Al image over SEM image with transparency mask
    sei.paste(al, alMask)
    sei.save('result.jpg')
    

    That gives these masks and results:

    enter image description here

    enter image description here

    enter image description here