Using regionprops in Python

14,800

Something like this?

from skimage.io import imread, imshow
from skimage.filters import gaussian, threshold_otsu
from skimage import measure
import matplotlib.pyplot as plt

original = imread('https://i.stack.imgur.com/nkQpj.png')
blurred = gaussian(original, sigma=.8)
binary = blurred > threshold_otsu(blurred)
labels = measure.label(binary)

plots = {'Original': original, 'Blurred': blurred, 
         'Binary': binary, 'Labels': labels}
fig, ax = plt.subplots(1, len(plots))
for n, (title, img) in enumerate(plots.items()):
    cmap = plt.cm.gnuplot if n == len(plots) - 1 else plt.cm.gray
    ax[n].imshow(img, cmap=cmap)
    ax[n].axis('off')
    ax[n].set_title(title)
plt.show(fig)

props = measure.regionprops(labels)
for prop in props:
    print('Label: {} >> Object size: {}'.format(prop.label, prop.area))

Output:

Plots

Label: 1 >> Object size: 37
Label: 2 >> Object size: 66
Label: 3 >> Object size: 1
Share:
14,800
oofin
Author by

oofin

Updated on June 04, 2022

Comments

  • oofin
    oofin almost 2 years

    I am trying to analyze greyscale TIFF stacks, in which a given frame will look like this. I filter it (using Gaussian blur), and then binarize it (using Otsu's method for threshold).

    MATLAB code, which works great:

    image_conncomp = bwconncomp(image_binary); # entire stack is held in image_binary
    
    for i=1:image_conncomp.NumObjects
        object_size = length(image_conncomp.PixelIdxList{i});
    end
    

    Each white spot in the example image is picked up, and its volume (in pixels) is pretty accurately given by object_size.

    Python code:

    from skimage import measure
    
    labels = measure.label(image_binary, background=1) # same image_binary as above
    propsa = measure.regionprops(labels)
    
    for label in propsa:
        object_size = len(label.coords)
    

    The Python code seems to work decently... except that most detected objects will have object_size of 1 - 200, and then a couple will have a size of several thousand pixels.

    What are these functions doing differently? I would be happy to try another approach in Python to get calculate object sizes, but I struggled to find another one. It'd be great to have a Python version of this code, if I could find a good substitute for Matlab's bwconncomp function.

    enter image description here

    • Cris Luengo
      Cris Luengo almost 6 years
      Did you look at the output of measure.label?
    • oofin
      oofin almost 6 years
      I honestly don't understand the output in its raw form. It's supposed to label the objects that it recognizes, but not sure exactly how it does it
    • Juan
      Juan almost 6 years
      Why did you set background=1? Surely that is not the default in Matlab? Also, the RegionProp objects have some nice properties, including area which is what you want: for prop in propsa: object_size = prop.area. Anyway, I suggest using skimage.color.label2rgb to look at the label image and make sure that that step is working. The rest looks good (assuming the binaries really are identical, and that the background is set to 0, I think)
  • oofin
    oofin almost 6 years
    This works great for measuring area. However, I'm looking for volume. Generally, a stack will have 34 frames similar to the sample image above. Objects will appear in more than one frame, but not all - so I have to look at the entire stack all at the same time to actually get volume. To measure volume, I just want to count the # of pixels found in the object
  • Tonechas
    Tonechas almost 6 years
    In that case you need to loop over the stack and compute the volume as the sum of the areas of the regions which correspond to the same object.
  • oofin
    oofin almost 6 years
    but how do i know that they are the same object? the only method I can think of is to compute the distance between centroids, but that sounds very time expensive
  • oofin
    oofin almost 6 years
    I added the stack (converted to png, Chrome can't render .tiff's) to the bottom of original question
  • Tonechas
    Tonechas almost 6 years
    I am not able to download the stack from the url you provided. Could you post a Dropbox/Google drive link?
  • Juan
    Juan about 5 years
    I missed this discussion. @oofin, the property "area" actually returns a volume if your image is 3D