Installing ITK Python package in Slicer 5.1 and above

jcfr
Tue, 11 Oct 2022 05:12:43 +0000
Development

Following the integration of Slicer pull request #6564 adding support for ITK custom namespace, it is now possible to install ITK python package from PyPI and use associated filter.

The use of functionalities relying on either ITK C++ (e.g Slicer CLIs, vtkITK library, …) or the SimpleITK python package built within Slicer have been tested and are expected to work on macOS/Linux/Windows.

Known Issues

ITK pre-release ( itk 5.3rc4.post3 or newer) should be used

The use of macOS ITK python wheels is broken and issue is been discussed at itk 5.3rc4.post3: Failure to load libtbb library (observed on macOS 10.13) - Engineering - ITK

Installing the ITK Package

You may install the ITK python wheels using

slicer.util.pip_install(["--pre", "itk==5.3rc4.post3"])

Alternatively, the instructions posted here allows to install the wheels in a dedicated directory. This more elaborated approach may be useful to avoid “polluting” the site-packages directory found in your installation of Slicer.

Example: Applying ITK filter to MRML Volume node

The following example demonstrates how to apply an ITK filter to a MRML volume node:

def updateMatrix3x3From4x4(matrix3x3, matrix4x4):
  for i_idx in range(3):
    for j_idx in range(3):
      matrix3x3.SetElement(i_idx, j_idx, matrix4x4.GetElement(i_idx, j_idx))

# Input node
import SampleData
input_volume_node = SampleData.SampleDataLogic().downloadMRHead()

# (1) Create VTK image data with expected metadata
input_vtk_image = vtk.vtkImageData()
input_vtk_image.ShallowCopy(input_volume_node.GetImageData())
input_vtk_image.SetOrigin(input_volume_node.GetOrigin())
input_vtk_image.SetSpacing(input_volume_node.GetSpacing())

directionMatrix4x4 = vtk.vtkMatrix4x4()
input_volume_node.GetIJKToRASDirectionMatrix(directionMatrix4x4)
directionMatrix3x3 = vtk.vtkMatrix3x3()
updateMatrix3x3From4x4(directionMatrix3x3, directionMatrix4x4)
input_vtk_image.SetDirectionMatrix(directionMatrix3x3)

# (2) Create ITK image data from VTK image data
import itk
input_itk_image = itk.image_from_vtk_image(input_vtk_image)

# (3) Filter ITK image
output_itk_image = itk.discrete_gaussian_image_filter(input_itk_image, variance=5.0)

# (4) Create output node
output_volume_node = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", "MRHead-Filtered")

# (5) Apply ITK filtering
vtk_output_image = itk.vtk_image_from_image(output_itk_image)

# (6) Update output node using on VTK output image spacing/origin/direction
ijkToRASMatrix = vtk.vtkMatrix4x4()
import vtkAddon
vtkAddon.vtkAddonMathUtilities.SetOrientationMatrix(vtk_output_image.GetDirectionMatrix(), ijkToRASMatrix)
output_volume_node.SetIJKToRASMatrix(ijkToRASMatrix)
output_volume_node.SetOrigin(*vtk_output_image.GetOrigin())
output_volume_node.SetSpacing(*vtk_output_image.GetSpacing())

# (7) Reset spacing/origin/direction from VTK output image
vtk_output_image.SetOrigin((0, 0, 0))
vtk_output_image.SetSpacing((1., 1., 1.))
identidyMatrix = vtk.vtkMatrix3x3()
vtk_output_image.SetDirectionMatrix(identidyMatrix)

# (8) Update output node setting VTK image data
output_volume_node.SetAndObserveImageData(vtk_output_image)

Related posts

How to install ITK python wheels with Slicer 4.10 and Slicer 4.11?

cc: @muratmaga @smrolfe @pranjal.sahu @thewtex

3 posts - 2 participants