Measuring Layer Widths from Electron Micrograph

asked 2014-06-29 18:34:31 -0500

ccook gravatar image

I have an image from an electron micrograph depicting dense and rare layers in a biological system, as shown below.

image description

The layers in question are in the middle of the image, starting just to near the label "re" and tapering up to the left. I would like to:

1) count the total number of dark/dense and light/rare layers

2) measure the width of each layer, given that the black scale bar in the bottom right is 1 micron long

I've been trying to do this in Python. If I crop the image beforehand so as to only contain parts of a few layers, such the 3 dark and 3-4 light layers shown here,

image description

I am able to count the number of layers and measure their relative thicknesses using the code:

import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
from PIL import Image
from skimage.measure import regionprops

tap = Image.open("VDtap.png").convert('L')
tap_a = np.array(tap)

tap_g = ndimage.gaussian_filter(tap_a, 1)
tap_norm = (tap_g - tap_g.min())/(float(tap_g.max()) - tap_g.min())
tap_norm[tap_norm < 0.5] = 0
tap_norm[tap_norm >= 0.5] = 1

result = 255 - (tap_norm * 255).astype(np.uint8)

tap_labeled, count = ndimage.label(result)

props = regionprops(tap_labeled)
ds = np.array([])

for i in xrange(len(props)):
    if i==0:
        ds = np.append(ds, props[i].bbox[1] - 0)
    else:
        ds = np.append(ds, props[i].bbox[1] - props[i-1].bbox[3])

    ds = np.append(ds, props[i].bbox[3] - props[i].bbox[1])

Unfortunately this is still not ideal. Firstly, I would like to not have to crop the image beforehand, as I intend to repeat this procedure for many such images. I've considered that perhaps the (rough) periodicity of the layers could be highlighted using some sort of filter, but I'm not sure if such a filter exists? Secondly, the code above really only gives me the relative width of each layer - I still haven't figured out a way to incorporate the scale bar so as to get the actual widths.

After hearing about how powerful OpenCV is, I figured it would could be very effective at solving this problem. However, I'm still not sure where to begin after having poked through the tutorials and would appreciate some insight into which routines would be most appropriate here. Thanks in advance.

edit retag flag offensive close merge delete