Counting the number of segments

I have a volume from which I have segmented several scattered isolated structures. These are the nuclei of a group of cells.
I need to count the number of these segments (nuclei).

Is there a function to do this?

Thank you for the kind answer

You could use Identify Islands plus Segment Statistics for that. It won’t be efficient if you have over 100 islands or so. You could write a quick python script to calculate the answer.

Thank you very much for your answer pieper.

As you anticipated, I was able to use this method on small files for tests but no longer on large files with many objects.
Can you suggest me where to read material that will enable me to start writing python scripts?
Can I run these scripts directly in 3D Slicer?

Thank you

You can start by reading through the script repository to see what’s possible and then do some of the programming tutorials linked from slicer.org.

The filter that counts cells is called vtkITKIslandMath. For example:

segmentationNode = getNode('Segmentation')
segmentID = segmentationNode.GetSegmentation().GetNthSegmentID(0)

# Get segment binary labelmap representation as vtkOrientedImageData
image = slicer.vtkOrientedImageData()
segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image)

# Get number of islands
import vtkITK
islands = vtkITK.vtkITKIslandMath()
islands.SetInputData(image)
islands.SetMinimumSize(10)
islands.Update()
print(f"Found {islands.GetNumberOfIslands()} islands")

Dear pieper and lassoan,
thank you for your answers.

I tried to copy and post the script from lassoan in the Python Console of 3D Slicer replacing the text “segmentID” with the name of my segment (“Nuclei”).
And i got this error:
Traceback (most recent call last):
File “”, line 6, in
NameError: name ‘Nuclei’ is not defined

image

I also tried to convert the segment in a module. But I get the same message.

When I run the script without changing anything in it I get this error.
image

Zooming in heavily on my images, I realized that I have very small islands accidentally selected by the threshold function. This increases the number of islands and could be the problem.

I cut the segments with the Scissor function to test the script a on smaller volume. I rounded the segments with the Smoothing function and eliminated the smaller islands with Remove small islands. After several progressively more aggressive attempts, I obtained a number of islands small enough to be counted with the script. However, on the original files I will definitely have more than 255 objects.
Is there a possibility of counting more objects with a different script? Can the “maximum output pixel type” be increased?
Or, is there a possibility of analyzing sequentially adjacent portions of the volume automatically and then summing up the results of the individual portions analyzed?

What is your modality? If you are working with microscopy, did you try more cell specific NN for this task? I am not sure where they stand with 3D data, but cellpose seems to have been developed specifically for this purpose.

vtkITKIslandMath is probably just using the same scalar type as your input data. So if you cast the data, wither in vtk or using the Cast Scalar Volume module you can use an integer type with more bits to support more islands.

thank you muratmaga. The segmentation of the cells into two dimensions has already been done by another method other than cellpose but which nevertheless worked adequately. Now I need to get the data out of the 3D files.

Thank you piper.
I converted my volume in .vtk and performed again the segmentation as it was done before.

I used the code from lassoan and now I am stuck with this error:

Traceback (most recent call last):
File “”, line 1, in
File “C:\Users\XX\AppData\Local\slicer.org\Slicer 5.6.2\bin\Python\slicer\util.py”, line 1566, in getNode
raise MRMLNodeNotFoundException(“could not find nodes in the scene by name or id ‘%s’” % (pattern if (isinstance(pattern, str)) else “”))
slicer.util.MRMLNodeNotFoundException: could not find nodes in the scene by name or id ‘Segmentation’

Am I missing any steps in the segmentation?

The message is telling you that you need to use the name of the segmentation. The first line of the script may need to be changed to say “Segmentation_1” or whatever the object in your scene is called.

In fact, that was the mistake. I corrected the code but now I get the same error as before.

“Slicer has caught an application error, please save your work and restart.\n\nIf you have a repeatable sequence of steps that causes this message, please report the issue following instructions available at https://slicer.org\n\n\nThe message detail is:\n\nException thrown in event: D:\D\S\S-0-build\ITK\Modules\Segmentation\ConnectedComponents\include\itkConnectedComponentImageFilter.hxx:144:\nITK ERROR: ConnectedComponentImageFilter(0000020DD9CDF300): Number of objects (836) greater than maximum of output pixel type (255).”

With both .vtk and .nrrd volumes.

I have tried to use the “Cast Scalar Volume” module but the list of input volumes is empty even though I have loaded more than one volume with different formats.

image

Do I need to do any steps beforehand?

The volume was not shown by Cast Scalar Volume because it had not been converted to scalar volume. I converted the volume with the Vector to Scalar Volume module and then used the Cast Scalar Volume module and tried to convert the volume to Int and to Float.
I got the same error as before with both output types.

Looking closer, I see this line segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image) is giving you the smallest datatype that can represent the number of input segments.

So you need to add this to the code after getting image from the segmentationNode:

cast = vtk.vtkImageCast()
cast.SetOutputScalarTypeToInt()
cast.SetInputData(image)
cast.Update()
#  to confirm
print(cast.GetOutputDataObject(0).GetScalarTypeAsString())

And then put image through vtkITKIslandMath.

This is the code I got now but I still get the same error.

segmentationNode = getNode('Segmentation')
segmentID = segmentationNode.GetSegmentation().GetSegmentIdBySegmentName("Nuclei")

# Get segment binary labelmap representation as vtkOrientedImageData
image = slicer.vtkOrientedImageData()
segmentationNode.GetBinaryLabelmapRepresentation(segmentID, image)

#  cast vtk.vtkImageCast
cast = vtk.vtkImageCast()
cast.SetOutputScalarTypeToInt()
cast.SetInputData(image)
cast.Update()
#  to confirm
print(cast.GetOutputDataObject(0).GetScalarTypeAsString())


# Get number of islands
import vtkITK
islands = vtkITK.vtkITKIslandMath()
islands.SetInputData(image)
islands.SetMinimumSize(10)
islands.Update()
print(f"Found {islands.GetNumberOfIslands()} islands")

However, the part of the code you suggest to add works and prints “int” at the end of the code and before the error.

You need to also change islands.SetInputData(image) to islands.SetInputData(cast.GetOutputDataObject(0))

Thank you!!!
Now it’s working perfectly :smile: