Toggle segment view for all segments in segment editor instead of segmentations module

HI
Is it possible to toggle visibility of all segments in Segment Editor?
In segment editor, I right click on a segment of interest and click “Show only selected segments"to view my segment of interest and correct the annotation. Once I’m done, I would like to view all segmentations in Segment Editor module instead of going to segmentations module. If it was a few segments, then it wouldn’t matter, but when I’m annotating >20-30 objects it does become quite cumbersome. Is there a way for this already?

Thanks a lot.

Cheers
Pradeep

I think the use case of bulk show/hide “all other segments” has not come up before. Can you tell why do you want to show only a single segment? Do all those segment overlap with your current segment and therefore it decreases its visibility? Or do you do this for performance reasons? (Is update is slower if you show more segments? It should not be)

Hi @lassoan
Thanks for your reply.

Its mostly because I use Fill between Slices option to create a segment and since that works on only the visible segment, I need to toggle visibility of all other segments off to use this option. After I am done, I want to see all other segments to figure out which ones I need to correct or add. I need to switch between segmentation and segment editor modules to do this.

Example image:

Yes, this is another reason as well.

If you think there is a better approach than using Fill between slices, please do let me know.

Thanks

Pradeep

I guess you mean “Grow from seeds” - the attached image contains small blobs, which are not well suited for “Fill between slices”. Anyway, both these effects can process any number of visible segments at once, so it should not be necessary to define segments one by one.

A simple way to segment images like this can be to generate seed points by Thresholding and Islands split. If sometimes blobs are fused together then you can use a higher threshold value (so high that blobs are not connected anymore), then run Grow from seeds on the result (to get the complete blob from the small seed).

Hi @lassoan
Thanks for the suggestion, this is really handy for images I label from scratch.

Apologies, I was not clear, but for most of the images I get label predictions from a different program and correct it in 3D Slicer, so Fill between slices is a quick way to add a few more labels or correct labels. Currently, I use paint or level tracing to create segments, and then use Fill between slices+Smoothing to complete it. So, if the mask/label I imported already had 50 objects, I would like to hide all of them to activate Fill between slices to make a new segment and then re-display them after.

Hope it is clearer now.

Cheers
Pradeep

Showing/hiding segments and using “Fill between slices” should not be necessary for this segmentation task. Most likely you can fix all these blobs at once, by keeping all of them displayed and adding a “background” segment, and applying “Grow from seeds” effect. You probably don’t need the label predictions from another program, because you can generate seeds by thresholding and island splitting. You may also try local thresholding (in SegmentEditorExtraEffects extension).

If you can share a volume (upload to dropbox/onedrive/google drive and post the link here) then you can get more specific advice.

Thanks for that.
Its a small image which can be found here:

Image download link

To give more context and make sure I’m clear. I use 3D slicer to generate labelmaps which are then used as ground truth for training deep learning models to automate image segmentation tasks.
The seed thresholding and island splitting is a really good idea. I am so used to ImageJ that I am still getting my head around workflows in 3D Slicer. Thanks, I have installed the SegmentEditorExtraEffects extension.
Would you mind having a look at the dataset I uploaded and let me know if you have any other suggestions? I do appreciate that the image is quite small and noisy.

Thanks
Pradeep

Thank you for the sample image, it helped a lot in understanding the task and challenges. These images are different from usual 3D clinical images in that objects can overlap in the 3D space, so you will need some manual work to review and resolve these overlaps.

You can get a good starting point by automatically generating seeds and growing them:

  • Add segment
  • Thresholding effect: select range 10000 to maximum, click Apply (these will be the basis of seed points)
  • Smoothing effect: Median, 3mm (removes small speckles, fill small holes)
  • Margin: Shrink, 1mm (splits connected seeds, but needs to be used carefully, as it can also remove small seeds)
  • Islands: Split islands to segments, Minimum size: 10 voxels
  • Grow from seeds effect: in Masking section, check “Editable intensity range”, set range 5000 to maximum, click initialize, then Apply
  • Smoothing: Joint smoothing method

These may seem like a lot of steps, but once you experimented with it manually and know what parameters work the best, you perform all the steps fully automatically by a Python script.

You might consider reducing noise in the image and use that as master volume, especially for the last “Grow from seeds” step. To do this noise filtering, first you need to cast the image to float using Cast scalar volume module, then use Simple Filters module - Gradient anisotropic smoothing filter. There are many other noise reduction filters in Simple Filters module that you might try.

Unfortunately, these automated processing needs manual fixing, mostly splitting of fused segments. If you can see fused blobs in the 3D view then you can separate them by using Scissors effect with Masking/Editable area -> Inside all segments, Operation -> Fill inside. After setting this up, you can add a new segment and in circle in a 3D view the part of a segment that you want separate out into a new segment.

You may also find Paint tool useful, you can enable sphere brush to paint in multiple slices at once and set Editable intensity range to restrict it to bright regions.

Hi @lassoan
This is super useful and I’m already getting some nice results… This has also given me an idea on the workflows and possibilities with 3D slicer.

I agree that it needs some manual fixing, but this is a great start. Restricting the editing area using Masking/Editable area is really handy. Didn’t realise I could use it here.

Just one question, I tried Gradient Anisotropic Diffusion filter under Filtering->Denoising and it worked without casting the image to float. Is this the same as using the same filter under Simple Filters module?

An unrelated question, in cases of using big images, are filters in 3D Slicer GPU-accelerated or does it use the CPU mainly?

Thanks a lot

Pradeep

Probably the Gradient anisotropic diffusion filter module does the same as Simple Filters module’s filter. I recommended Simple Filters because it has many other noise filtering modules that you can experiment with, but if you end up using gradient anisotropic diffusion then it is simpler to use that module.

With a very few exceptions, image processing filters run on the CPU. GPU is mainly used in Slicer for rendering.

Thanks for that.

Is it of interest in 3D Slicer to use GPU-accelerated filters?
If so, perhaps this may be of interest?


This is a project where OpenCL kernels are being translated for use in Python.
This is from a GPU accelerated image processing library in ImageJ/FIJI which uses OpenCL kernels: https://clij.github.io/
The OpenCL implementations here are being ported for use in Python. There are quite few ITK filters in there as well.

Cheers
Pradeep

We haven’t had have huge success stories with GPU-acceleration in image processing filters. Maybe it is because processing speed on CPU is a problem mainly on big data sets and with complex algorithms. However, big data is not very well suited for GPU processing either, as CPU/GPU transfer time can be very significant and available GPU memory may be limited. Complex algorithms get even more complex when you want to run them efficiently on the GPU and often you need to develop a new algorithm almost from scratch. Additional difficulty is that development, debugging, and maintenance of OpenCL code requires special skillset which only a small fraction of developers have.

Slicer is using more and more of the GPU as ITK (and various other packages) take advantage of the GPU. We may also look into improving speed of a few specific operations that are performed very frequently and noticeably slow. But I would expect that most of the image and mesh processing operations will remain mostly on the CPU in the near term.

Thanks for the detailed reply.
The transfer time isn’t too bad, but when we are using the GPU in an image processing workflow it is better to chain the GPU operations together so that the transfer time is reduced. Its usually a balance between if the image sits in the memory and if so, is the transfer time and processing quicker than using the CPU.
I do agree that the development and maintenance can be a specialised skillset.
There is a nice list of operations that are being translated into Python here, if its of interest to yoursel or anyone else who comes across this thread in the future:

Thanks for your help again @lassoan
Pradeep

1 Like

I did some experiments with Slicer and OpenCL a while ago using PyOpenCL. Generally it worked very well. In addition to the issues Andras noted, at least when I was testing this I found a wide variety of performance and feature support across platforms (probably some drivers were buggy) so code that worked well on one machine was slow or just didn’t work on another.

That said, I agree with the overall goal of processing on the best hardware available and keeping the data in memory close to where it will be rendered. The code linked below has example segmentation and volume rendering kernels.

(yikes, was it really 9 years ago??)

3 Likes

Useful topic for me, useful information to be applied in my laboratory, thanks to all! :handshake:

Hello,

It looks like this thread theme changed a bit, so circling back, I also need to frequently turn off/toggle between many segments at a time. In my case it is because it is very busy/lots of overlap. Is there a quick way to do this without unclicking each one in the data section?

PS. Awesome program, and all these threads have been super helpful as I’ve been learning!

There are lots of ways to achieve this. You can move group of segments temporarily into another segmentation so that you can show/hide them with a single click. You can also assign a keyboard shortcut to show/hide that separate segmentation or to show/hide a custom list of segments. For example, this script toggles visibility of completed segments.

Thanks so much! I’ve move to other segments before as a work around, but the other tips are very helpful.