I’m using vtkOpenGLGPUVolumeRayCastMapper for 3D image volume rendering. For this purpose, I have two 3D images: one is the original image and the other is a mask image. The mask image contains labels that describe corresponding segments. I set up both of them into an instance of vtkOpenGLGPUVolumeRayCastMapper.
The question is, how can I display only a part of the original image based on a specific label from the mask and hide all other parts of the image? I know that there is a method SetMaskTypeToBinary, and in this case, all voxels with label 0 will be hidden, but I need to show, for example, voxels with label 20 and hide all other voxels.
Perhaps you could use the binary mask, on a scalar generated by vtkProgrammableAttributeDataFilter, i.e., make a new array that is zero whenever your label is == some number of your choosing?
I looked around for some more elegant way, but there are a LOT of classes to look through.
Perhaps also vtkThresholdFilter.You can select cells of input based on one of these conditions: 1) greater than some value, 2) less than some value, or what may interest you is 3) between some values … so if you wanted 20, you could say between 19 and 21?
Also perhaps: vtkExtractSelection … which uses vtkSelection.
Hi @rexthor, thank you for your assistance. I believe vtkThresholdFilter isn’t suitable in this scenario because the mask is set directly into vtkOpenGLGPUVolumeRayCastMapper via the function, not through the algorithm port. Here’s the function: void SetMaskInput(vtkImageData* mask). I’m also considering creating separate 3D images for each label, but this would increase memory consumption.
I never use volume mappers … but would the selection suggestion work?
I think selection work in the same way if I just create separate image volumes per each label. And it takes time on CPU, I would prefer to do it on fly in GPU. I even looked at the source code, and found out that modifying the shader might have helped, but I’m not sure, also I don’t have access to change shader outside of vtkOpenGLGPUVolumeRayCastMapper
Is there some way to change the opacity of the color map to render transparent all of the stuff you don’t want to see?
This can be a solution by the way, there is a possibility to setup colors and opactiy per label and also change blending between mask and image. It seems like workaround
We experimented with basic binary labelmap based masking and the results were really bad. It can only be useful if the boundary of the masked region is already empty and you only need to use a single color.
Instead, we developed a new method in 3D Slicer that works very well. It dilates labels and masks the volume with smooth transition, and generates an RGBA volume as output that VTK can directly render using raycasting.
Full implementation is available in 3D Slicer in “Colorize volume” module (in Sandbox extension) - see full source code.
Some more images and discussion is available here:
The processing (except the labelmap dilation) is very simple, so it would not be too hard to port to work on GPU, but it is probably not worth the trouble since processing takes only a few seconds on the CPU, volume rendering pipeline is already very complex, and shaders are a bit moving target in VTK now.
Hi @lassoan, thanks for information. Is there implementation for C++ or it is available only for python?
C++ implementation is exactly the same as Python. If you don’t want to translate the code yourself then you can probably use any of that AI chatbots.