Get the largest connected component of segmentation image
Asked Answered
H

6

15

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!

Hillinck answered 28/11, 2017 at 21:6 Comment(2)
Could you post the content of segmentation for testing?Devoid
It's a bit of a problem because it's an image and I don't know how can I add this kind of a file in the posts here. It's actually an image file which I did segmentation for it, so every pixels with value between 2 values are 1 and all the others are 0.Hillinck
P
27

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
Pfeiffer answered 11/3, 2019 at 21:48 Comment(0)
L
8

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
Lymphangitis answered 20/5, 2019 at 14:31 Comment(1)
Interesting solution!Cureall
M
6

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.

Myology answered 11/12, 2017 at 3:4 Comment(0)
R
4

The following function gives the largest connected segmentation which is not backgroud. The shape of input and output is the same which could be 2D or 3D images.

import numpy as np
from skimage.measure import label

def getLargestCC(segmentation):
    labels = label(segmentation)
    unique, counts = np.unique(labels, return_counts=True)
    list_seg=list(zip(unique, counts))[1:] # the 0 label is by default background so take the rest
    largest=max(list_seg, key=lambda x:x[1])[0]
    labels_max=(labels == largest).astype(int)
    return labels_max
Rent answered 30/1, 2019 at 21:10 Comment(0)
U
4

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

Upsydaisy answered 11/9, 2020 at 6:45 Comment(0)
I
0

Based on P Tate's solution and assuming that the binary segmentation mask is of type bool one could also use that mask to only input the foreground pixels into np.bincount by indexing/masking with segmentation:

import numpy as np
from skimage.measure import label   

def largest_connected_component(segmentation):
    labels = label(segmentation)
    largest_cc = labels == np.argmax(np.bincount(labels[segmentation]))
    return largest_cc
Idiotism answered 2/3, 2023 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.