CT opacity gradient piecewise function

Hi, I’m going through examples from the textbook and user guide and I recently started working on https://lorensen.github.io/VTKExamples/site/Cxx/Medical/MedicalDemo4/
To volume render DICOM CT data.
I can’t figure out what the exact opacity gradient piecewise function should be.

The example originally states:

// The gradient opacity function is used to decrease the opacity
// in the “flat” regions of the volume while maintaining the opacity
// at the boundaries between tissue types. The gradient is measured
// as the amount by which the intensity changes over unit distance.
// For most medical data, the unit distance is 1mm.
vtkSmartPointer volumeGradientOpacity =
vtkSmartPointer::New();
volumeGradientOpacity->AddPoint(0, 0.0);
volumeGradientOpacity->AddPoint(90, 0.5);
volumeGradientOpacity->AddPoint(100, 1.0);`

Does this mean the point at 100 is equal to 1mm or does this change depending on the data used? Is there a formula or rule of thumb for this?

I’m using the CQ500 CT dataset
which is 512x512 1mm slice thickness, I’m also not sure of the voxel size because of the metadata, I’ll read more on that if need be

Gradient opacity function X axis is gradient, Y axis is opacity. So X axis unit is something like voxel intensity change / mm.

Usually you don’t need to use gradient opacity (it creates a glass-like transparency effect), but if you need this then it is usually quite data dependent. It can create artifacts in noisy images, so you may want to keep the value at constant 1.0 and just slightly decrease it and/or filter the image to reduce noise.

You can use interactive transfer function editor in Volume Rendering module of 3D Slicer to design transfer functions that work well for you. You can also find a couple of presets for various imaging modalities and anatomies. Once you have the transfer functions you like, you can save the functions in a text file (see file format description here).

Thanks for replying,
I was just using 3D Slicer and the Volume Rendering module to get a better idea of how this worked. I also read a bit of the users manual and in it, the following is the typical gradient opacity for 8-bit unsigned data (page 160)

vtkPiecewiseFunction gtfun
gtfun AddPoint 0 0.0
gtfun AddPoint 3 0.0
gtfun AddPoint 6 1.0
gtfun AddPoint 255 1.0

If I’m working with CT data which normally is unsigned int (16-bit) then something like this should work?

volumeScalarOpacity->AddPoint(0, 0.00);
volumeScalarOpacity->AddPoint(150, 0.25);
volumeScalarOpacity->AddPoint(350, 0.50);
volumeScalarOpacity->AddPoint(850, 1);

Regardless how you store the data (8-bit or 16-bit integer, floating-point, …) the optimal gradient opacity transfer function choice depends entirely on your data and what parts of it you want to hide by making (semi)transparent.

Note that gradient opacity transfer function is rarely used. I would consider it as a “special effect” that must be used judiciously. You need to focus on getting scalar opacity and color transfer functions right, then tune material properties, and after that maybe play around with gradient opacity.

Got it, I’d say my scalar opacity and color tfunctions are working fine so far. I’ll see if the conclusion I thought of makes my rendering better or worse. Thanks for the feedback.