Segmentation

<< Click to Display Table of Contents >>

Navigation:  XStream® HDVR® SDK > Implementation Concepts >

Segmentation

Previous pageReturn to chapter overviewNext page

C++ C++ Java Java .NET .NET

Summary

 

Segmentation is a process whereby voxels in the dataset are assigned to one of a range of different transfer functions. The segmentation state is represented by a data structure called the label volume. The label volume consists of a structure containing one byte per voxel. Each byte in the label volume stores the identifier of the transfer function that is used to render that voxel. The various segmentation techniques supported by the XStream® HDVR® SDK apply segmentation by setting values in the label volume.

 

By using segmentation, various structural components of a dataset may be rendered using different transfer function settings. This may be done to highlight a structural feature, such as a specific tissue or material type, or to hide such structures to improve the visibility of other dataset components. Refer to the Transfer Functions section for more information on configuring transfer functions.

 

Segmentation makes use of the octree data structure, and is therefore only available in adaptive rendering modes. These include Transfer Function, Maximum Intensity Projection (MIP), Faded MIP, and Minimum Intensity Projection (MinIP). Segmentation is not available in any of the brute force modes, including the brute force versions of the MIP, Faded MIP, and MinIP render modes.

 

Activating segmentation will consume an amount of memory equivalent to 50% of the dataset size, because each voxel in the dataset must be allocated a 1-byte value in order to designate the transfer function that will render the voxel. It is possible to segment a dataset into 256 different regions, however in practice fewer than 8 are typically required.

 

The XStream HDVR SDK supports two built-in segmentation methods. The first method is Region Selection, in which a polygonal region is designated that includes all voxels to be segmented to the active label volume. The second segmentation method is Region Growth. This segmentation method automatically segments a material or tissue type based on parameters set in the Region Growth SDK methods. The XStream HDVR SDK also supports a Custom Server Algorithm feature that can be used to develop a custom segmentation algorithm, if desired. Real-time interactive segmentaion may be performed with the methodes described in the Interactive Segmentation section.

 

Segmentation

A dataset with segmentation applied.

 

Enabling Segmentation

 

Segmentation is enabled and applied using an IVolumeSegmentationContext object. An IVolumeSegmentationContext object is created using the IServerContext::CreateVolumeSegmentation() method. Once created, the IVolumeSegmentationContext object must be initialized with the IVolumeSegmentationContext::Initialize() method. This method takes an an input parameter the address of an IOctreeContext object that has been previously associated with the IVolumeDataContext object of interest.

 

Once segmentation has been enabled target label volume must be set. This is the label volume that voxels will be associated with when segmentation is actually applied to the dataset. The active label volume is set with the IVolumeSegmentationContext::SetSegLabelIndex() method. This method takes as an input parameter an integer in the range of 0 to 7. These associate with transfer functions 0 - 7. Note that calling IVolumeSegmentationContext::SetSegLabelIndex() does not actually apply a segmentation, it only sets the label volume to be associated with the segmented voxels once segmentation is later applied.

 

After segmentation has been enabled using IVolumeSegmentationContext::Initialize() and an active transfer function is set using IVolumeSegmentationContext::SetSegLabelIndex(), actual segmentation operations may then be applied. Segmentation can be applied  using techniques discussed in the Region Selection, Region Growth, and Interactive Segmentation sections.

 

The IVolumeSegmentationContext class supports two different segmentation types, additive and subtractive. Additive segmentation causes voxels in the segmented region to be applied to the label volume designated with the IVolumeSegmentationContext::SetSegLabelIndex() method. Subtractive segmentation causes voxels in the segmented region to be applied to label volume 0. Subtractive segmentation can be used to un-segment previous segmented data. The segmentation type is set with the IVolumeSegmentationContext::SetSegType() method. This method takes as an input parameter a member of the ENUM_SEG_TYPE enumeration.

 

If a Region Growth or Interactive Segmentation operation is to be applied, the user can control what label volumes the segmentation algorithm is allowed to consider as the segmented region expands. Previously segmented regions can be designated as 'off limits' to the growth operation. This feature is controlled with the IVolumeSegmentationContext::SetSegLabelMask() method. This method takes four 64 bit integers as input parameters. Each integer acts as a bitmask for a given label volume. If a given bit is set to 1, that label volume will be considered during the segmentation growth operation. If a given bit is 0, that label volume will not be considered. In versions of the XStream HDVR SDK supporting 8 transfer functions, only the first 8 bits of the first parameter will be considered. The remaining bits are only applicable to versions of the XStream HDVR SDK supporting 256 transfer functions.

 

// Create an IVolumeSegmentationContext object.

IVolumeSegmentationContext *pSegmentationContext;

pServer->CreateVolumeSegmentation(&pSegmentationContext);

 

// Set the octree for the IVolumeSegmentationContext object. 

pSegmentationContext->Initialize(pOctree);

 

// Segmentation operations will apply to transfer function 2 (index 1).

pSegmentationContext->SetSegLabelIndex(1);

 

// Set additive segmentation.

pSegmentationContext->SetSegType(ST_ADDITIVE);

 

// Set all 8 label volumes as valid for segmentation.

pSegmentationContext->SetSegLabelMask(255, 0, 0, 0);

 

Segmentation is enabled and applied using an hdrcIVolumeSegmentation object. An hdrcIVolumeSegmentation object is created using the hdrcServerContext.createVolumeSegmentation() method. Once created, the hdrcIVolumeSegmentation object must be initialized with the hdrcIVolumeSegmentation.initialize() method. This method takes an an input parameter a reference to an hdrcOctreeContext object that has been previously associated with the hdrcVolumeDataContext object of interest.

 

Once segmentation has been enabled target label volume must be set. This is the label volume that voxels will be associated with when segmentation is actually applied to the dataset. The active label volume is set with the hdrcVolumeSegmentation.setSegLabelIndex() method. This method takes as an input parameter an integer in the range of 0 to 7. These associate with transfer functions 1 - 8. Note that calling IVolumeSegmentationContext::SetSegLabelIndex() does not actually apply a segmentation, it only sets the label volume to be associated with the segmented voxels once segmentation is later applied.

 

After segmentation has been enabled using hdrcIVolumeSegmentation::initialize() and an active transfer function is set using hdrcIVolumeSegmentation.setSegLabelIndex(), actual segmentation operations may then be applied. Segmentation can be applied  using techniques discussed in the Region Selection, Region Growth, and Interactive Segmentation sections.

 

The hdrcIVolumeSegmentation class supports two different segmentation types, additive and subtractive. Additive segmentation causes voxels in the segmented region to be applied to the label volume designated with the hdrcIVolumeSegmentation.setSegLabelIndex() method. Subtractive segmentation causes voxels in the segmented region to be applied to label volume 0. Subtractive segmentation can be used to un-segment previous segmented data. The segmentation type is set with the hdrcIVolumeSegmentation.setSegType() method. This method takes as an input parameter a member of the ENUM_SEG_TYPE enumeration.

 

If a Region Growth or Interactive Segmentation operation is to be applied, the user can control what label volumes the segmentation algorithm is allowed to consider as the segmented region expands. Previously segmented regions can be designated as 'off limits' to the growth operation. This feature is controlled with the hdvrIVolumeSegmentation.setSegLabelMask() method. This method takes four 64 bit integers as input parameters. Each integer acts as a bitmask for a given label volume. If a given bit is set to 1, that label volume will be considered during the segmentation growth operation. If a given bit is 0, that label volume will not be considered. In versions of the XStream HDVR SDK supporting 8 transfer functions, only the first 8 bits of the first parameter will be considered. The remaining bits are only applicable to versions of the XStream HDVR SDK supporting 256 transfer functions.

 

// Create an hdrcIVolumeSegmentation object.

hdrcIVolumeSegmentation segmentationContext;

segmentationContext = server.createVolumeSegmentation();

 

// Set the octree for the IVolumeSegmentationContext object. 

segmentationContext.initialize(octree);

 

// Segmentation operations will apply to transfer function 2 (index 1).

segmentationContext.setSegLabelIndex(1);

 

// Set additive segmentation.

segmentationContext.setSegType(hdrcDefines.ST_ADDITIVE);

 

// Set all 8 label volumes as valid for segmentation.

segmentationContext.setSegLabelMask(255, 0, 0, 0);

 

Saving and Restoring Segmentation States

 

The segmentation state stored in an IVolumeSegmentationContext object can be saved to disk as a GIPL file. This file can then be loaded and applied at a later time to restore a saved segmentation state. To save a GIPL file, use the IVolumeSegmentationContext::SaveSegStateAsGIPL() method. This method takes a file path and name to save the GIPL file to. Note that GIPL files are only saved by, and relative to the XStream HDVR server's working directory. To load a GIPL file use the IVolumeSegmentationContext::LoadSegStateFromGIPL() method.

 

The segmentation state stored in an hdvrIVolumeSegmentation object can be saved to disk as a GIPL file. This file can then be loaded and applied at a later time to restore a saved segmentation state. To save a GIPL file, use the hdvrIVolumeSegmentation.saveSegStateAsGIPL() method. This method takes a file path and name to save the GIPL file to. Note that GIPL files are only saved by, and relative to the HDVR server's working directory. To load a GIPL file use the hdvrIVolumeSegmentation.loadSegStateFromGIPL() method.

 

 

Undoing Segmentation Operations

 

The XStream® HDVR® SDK supports an undo feature on the segmentation operations discussed in the Region Selection, Region Growth, and Interactive Segmentation sections. The undo feature allows one to save the segmentation state in a buffer capable of storing 10 segmentation states. These saved segmentation states can then be restored from the buffer. To save the current segmentation state call the IVolumeSegmentationContext::SaveForUndo() method. This method takes two parameters. The first is an input parameter designating which label volume to save to the undo buffer. The second parameter is the address of an integer which stores the number of previously saved undo states available in the buffer. When this value reaches 10, additional calls to IVolumeSegmentationContext::SaveForUndo() will push out the oldest saved state to make room for the newest. To restore a saved segmentation state from the undo buffer, call the IVolumeSegmentationContext::UndoLast() method. This method will restore the segmentation state most recently saved to the undo buffer, and then delete it from the buffer, increasing the count of available buffer slots by one. IVolumeSegmentationContext::UndoLast() method takes as an output parameter the address of a variable that will be assigned the number of remaining saved undo states. When this value reaches 0, no more undo operations can be performed until new states are saved with the IVolumeSegmentationContext::SaveForUndo() method.

 

// Create an IVolumeSegmentationContext object.

IVolumeSegmentationContext *pSegmentationContext;

pServer->CreateVolumeSegmentation(&pSegmentationContext);

 

// Set the octree for the IVolumeSegmentationContext object. 

pSegmentationContext->Initialize(pOctree);

 

// Save state of label volume index 1.

h_uint32 availableSaveStates = 0;

pSegmentationContext->SaveForUndo(1, &availableSaveStates);

 

// Segmentation operations will apply to label volume 1.

pSegmentationContext->SetSegLabelIndex(1);

 

// User performs a segmentation operation.

UserDefinedSegmentationOperation();

 

// Undo last segmentation operation

h_uint32 savedStates = 0;

pSegmentationContext->UndoLast(&savedStates);

 

The XStream® HDVR® SDK supports an undo feature on the segmentation operations discussed in the Region Selection, Region Growth, and Interactive Segmentation sections. The undo feature allows one to save the segmentation state in a buffer capable of storing 10 segmentation states. These saved segmentation states can then be restored from the buffer. To save the current segmentation state call the hdrcIVolumeSegmentation.saveForUndo() method. This method takes an input parameter designating which label volume to save to the undo buffer. The method returns an integer which indicates the number of previously saved undo states available in the buffer. When this value reaches 10, additional calls to hdrcIVolumeSegmentation.saveForUndo() will push out the oldest saved state to make room for the newest. To restore a saved segmentation state from the undo buffer, call the hdrcIVolumeSegmentation.undoLast() method. This method will restore the segmentation state most recently saved to the undo buffer, and then delete it from the buffer, increasing the count of available buffer slots by one. hdrcIVolumeSegmentation.undoLast() method returns the number of remaining saved undo states. When this value reaches 0, no more undo operations can be performed until new states are saved with the hdrcIVolumeSegmentation.saveForUndo() method.

 

// Create an hdrcIVolumeSegmentation object.

hdrcIVolumeSegmentation segmentationContext;

segmentationContext = server.createVolumeSegmentation();

 

// Set the octree for the IVolumeSegmentationContext object. 

segmentationContext.initialize(octree);

 

// Save state of label volume index 1.

int availableSaveStates = 0;

availableSaveStates = segmentationContext.saveForUndo(1);

 

// Segmentation operations will apply to label volume 1.

segmentationContext.setSegLabelIndex(1);

 

// User performs a segmentation operation.

UserDefinedSegmentationOperation();

 

// Undo last segmentation operation

int savedStates = 0;

savedStates = segmentationContext.undoLast();

 

 

Segmentation Modifiers

 

The IVolumeSegmentationContext class supports a number of utility methods for manipulating the label volume state. These are described in the table below.

 

ClearLabels()

Clears one or more label volumes according to the input bitmask. Voxels in cleared label volumes become part of label volume 0.

CombineLabels()

Takes two label volumes and merges them together.

CopyLabel()

Copies one label volume to another.

SwapLabels()

Swaps the contents of two label volumes.

DilateOneObject()

Expands a segmented region by adding layers to the exterior surface.

ErodeOneObject()

Contracts a segmented region by removing layers from the exterior surface.

ColorizeTF()

Take a 3D Transfer Function and make it all a solid color (useful for visualizing the results of segmentation)

MakeColorLabeledTFsfromWindowLevel()

Fill in the upper TF's with colorized version of the W/L transfer function.

MakeColorLabelsFromMainTF()

Fill in the upper TF's with colorized version of the main (0) transfer function

MakeTFfromWindowLevel()

To display segmentation on 2D Thin display we utilize a fully opaque TF with a Parallel render instead of MPR render Type. This function will create that TF. for unsegmented data use (0,0,0) to (255,255,255) to get a TF which looks a a W/L display on a normal MPR 2D display. It is suggested for the segmented labels to use (r/2,g/2,b/2) to (r,g,b) for a given color for that label because then you will still see the different shades of the 2D image below the color.

 

ClearLabels()

Clears one or more label volumes according to the input bitmask. Voxels in cleared label volumes become part of label volume 0.

CombineLabels()

Takes two label volumes and merges them together.

CopyLabels()

Copies one label volume to another.

SwapLabels()

Swaps the contents of two label volumes.

DilateOneObject()

Expands a segmented region by adding layers to the exterior surface.

ErodeOneObject()

Contracts a segmented region by removing layers from the exterior surface.

ColorizeTF()

Take a 3D Transfer Function and make it all a solid color (useful for visualizing the results of segmentation)

MakeColorLabeledTFsfromWindowLevel()

Fill in the upper TF's with colorized version of the W/L transfer function.

MakeColorLabelsFromMainTF()

Fill in the upper TF's with colorized version of the main (0) transfer function

MakeTFfromWindowLevel()

To display segmentation on 2D Thin display we utilize a fully opaque TF with a Parallel render instead of MPR render Type. This function will create that TF. for unsegmented data use (0,0,0) to (255,255,255) to get a TF which looks a a W/L display on a normal MPR 2D display. It is suggested for the segmented labels to use (r/2,g/2,b/2) to (r,g,b) for a given color for that label because then you will still see the different shades of the 2D image below the color.