Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the largest connected component of segmentation image

I have a segmentation image of CT scan (only 1 and 0 values). I use the function "label" from skimage.measure to get a ndarray of the connected component. Now I need to get only the largest connected component from the "label" output (ndarray). Do you have any idea how can I do it?

My code looks like this:

from skimage.measure import label    

def getLargestCC(segmentation):
    labels = label(segmentation)
    // now I need to get only the largest connected component and return it
return largestCC

Thanks a lot!

like image 601
Vipasana Avatar asked Nov 28 '17 21:11

Vipasana


4 Answers

The answer of Gilly is interesting but wrong if the background (label=0) is larger than CC researched. The Alaleh Rz solution deals with the background but is very slow. Adapting the solution proposed by Gilly and removing the background problem:

import numpy as np
from skimage.measure import label   

def getLargestCC(segmentation):
    labels = label(segmentation)
    assert( labels.max() != 0 ) # assume at least 1 CC
    largestCC = labels == np.argmax(np.bincount(labels.flat)[1:])+1
    return largestCC
like image 125
Vincent Agnus Avatar answered Nov 08 '22 08:11

Vincent Agnus


I was trying to figure out how to stop skimage.measure.label counting background as separate region. It was that I almost started digging skimage.measure.regionprops docs until I came upon P Tate's elegant solution. Here is a quick figure which shows how using suggested weights parameter of numpy.bincount can save some lines of code.

import skimage
import numpy as np
import matplotlib.pyplot as plt

img_bw = img_as_bool(img)
labels = skimage.measure.label(img_bw, return_num=False)

maxCC_withbcg = labels == np.argmax(np.bincount(labels.flat))
maxCC_nobcg = labels == np.argmax(np.bincount(labels.flat, weights=img_bw.flat))

fig, ax = plt.subplots(1, 2)
ax[0].imshow(maxCC_withbcg), ax[0].set_title('counts bcg')
ax[1].imshow(maxCC_nobcg), ax[1].set_title('not counts bcg')
[axi.set_axis_off() for axi in ax.ravel()]

enter image description here

like image 28
San Askaruly Avatar answered Sep 20 '22 22:09

San Askaruly


I am not sure what you want as the output, a mask?

import numpy as np
from skimage.measure import label   

def getLargestCC(segmentation):
    labels = label(segmentation)
    largestCC = labels == np.argmax(np.bincount(labels.flat))
    return largestCC

Numpy's bincount will count for each label the number of occurrences, and argmax will tell you which of these was the largest.

like image 6
Gilly Avatar answered Nov 08 '22 09:11

Gilly


The OP's input segmentation data is binary where the background is 0. So, we can use Vincent Agnus' np.bincount approach but simplify the background rejection logic by using np.bincount's weights argument. Set weights=segmentation.flat to zero out the background sum.

import numpy as np
from skimage.measure import label   

def getLargestCC(segmentation):
    labels = label(segmentation)
    largestCC = labels == np.argmax(np.bincount(labels.flat, weights=segmentation.flat))
    return largestCC
like image 6
P Tate Avatar answered Nov 08 '22 08:11

P Tate