This is my first post. I’ve been spending a lot of time learning about 3D Slicer, particularly focusing on the docs and segmentation techniques. I’m currently faced with the challenge of segmenting tumours that don’t appear in every slice of an MRI volume.
I’m wondering if there is a method to apply the local thresholding feature in the segmentation editor on a per-slice basis similar to the brush feature. Ideally, the workflow would involve, to :
Highlighting masks or regions of interest (ROIs) on individual slices where a tumor is detected.
Applying local thresholding on each of these slices to adjust the threshold by analyzing the local histogram.
Repeating this process for each slice and eventually compiling these into a complete volume segmentation.
I found the local threshold useful, but it seems that it highlights all slices when the boundaries are set. Is there any way to achieve this in the segmentation editor directly on a slice by slice basis where it resets the thresholding nodes for each slice?
Alternatively, would creating this workflow as a seperate module be a good work around?
I don’t think you can have Slicer apply the threshold only in a single slice, that’s a global (3D) operation. You can do something like this: For your current slice, preview and adjust the threshold range visually but instead of apply, hit use for masking and then switch to the paint/draw tool and select the area you would like to apply that threshold in that slice. Then switch to the next slice and repeat the procedure.
With python, it should be possible to extract the intensity values from a single slice, and let you choose the cut off values (or automatically calculate the cut off using one of the automated procedures). Though it is integration with segment editor might be a of work.
For this portion, it really defeats the purpose. I am looking for something more semi-automatic especially with almost 1000 example of annotations needed. The idea is to really avoid using paintbrush for manual segmentation, but rely on local thresholding from roi masks drawn with the brush.
it would be great practice and experience to automate this workflow using a custom module. If paint/brush is able to segment slice by slice, there has to be a way to code the local thresholding feature per slice node and reset the state each time we jump to another slice?
Would anybody be able to guide me/help in this process?
I mean there are many ways of doing this. Here is a chatGPT generated script that will extract the intensity values from an arbitrary slice and will put them into a numpy array that you can get min, max, std, mean, and do all sorts of histogram things to calculate a threshold
import slicer
import numpy as np
# Use "MRHead" as the volume name
volumeNode = slicer.util.getNode("MRHead")
# Get image data and check if it's valid
imageData = volumeNode.GetImageData()
if not imageData:
raise ValueError("The volume node does not contain image data.")
# Extract the intensity values from slice index 100
sliceIndex = 100
volumeArray = slicer.util.arrayFromVolume(volumeNode)
if sliceIndex < 0 or sliceIndex >= volumeArray.shape[0]:
raise ValueError("Slice index out of bounds.")
sliceArray = volumeArray[sliceIndex, :, :]
# Print the slice intensity values
print("Intensity values from slice index 100:")
print(sliceArray)
# get values
sliceArray.mean()
sliceArray.max()
sliceArray.std()
The point though, unless you have a dataset that is very unique and constructed slice by slice (as opposed to a 3D dataset), the intensity distributions from neighboring slices will be very very similar. So you will have a very complicated workflow with marginal gains (or maybe none).
If you describe what you are trying to do, there might be other options. Manual segmentaiton is too tedious.
I tried this workaround initially, but it doesnt scale, and having a gui to set local threshold boundary based on every slice is very helpful, instead of hard coding every slice instance.
Unfortunately, my dataset is composed of gliomas tumours. The intensities distribution dont often contribute to the same intensities on from neighbouring slices because they aren’t found in every slice. That is why i would need a slice by slice case workflow. Certain also have liquid build up creating artifacts thus being very complex for automatic process. The goal is to eventually use the segmentation as a training set for automatic pipelines.
Setting the GUI right is usually the most complex part of the module development. You will have to look into Slicer development (https://slicer.readthedocs.io) or hire someone.
Also your glioma tumors have thousands of slices, what kind of modality is that, histology? If you have thousands of slices in total, but only few slices per volume/specimen, you can potentially import every single slice of a specimen as an individual volume, segment them as individual slices (in this case threshold tool will work) and then programmatically stitch them together. This might be less development effort than creating your custom segmentation tool.
My apologies, i want to just clarify that they are MRI images each composed about about 20-30 slices per volume with different orientations. I have a couple hundreds of of MRI images requiring segmentation in a semi-automatic segmentations. Hope that clarifies.
Thank you for the tips. Will update on what works best for me.
If that’s the case, I would at least do couple manually in the way I describe. import each slice as a separate volume, segment the way you are thinking of with local threshold, and save, and then stitch.
If this workflow does indeed show slice-by-slice segmentation gives you better results, then you can consider automating it somehow.