Skip to content

ImageIteratorDemo

Repository source: ImageIteratorDemo

Description

Unlike in C++ where vtkImageIterator is an efficient way to access the regions of a vtkImageData. We have to use indexing instead.

The differences from the C++ example are: - We cannot use pointers in Python so we use SetScalarComponentFromDoubl(...) and GetScalarComponentFromDouble(...) instead of GetScalarPointer(...). - We cannot use vtkImageIterator as it is not wrapped in Python. So we use indexing instead.

Other languages

See (Cxx)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

ImageIteratorDemo.py

#!/usr/bin/env python3

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import VTK_UNSIGNED_CHAR
from vtkmodules.vtkCommonCore import reference
from vtkmodules.vtkCommonDataModel import vtkImageData
from vtkmodules.vtkInteractionImage import vtkImageViewer2
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleImage
from vtkmodules.vtkRenderingCore import vtkRenderWindowInteractor


def main():
    # We cannot use vtkImageIterator as it is not wrapped in the Python API
    #  so we use indexing to produce the same result as in the C++ example.

    # Create an image data and specify the size and type of the image data.
    image_data = vtkImageData(dimensions=(100, 200, 30))
    image_data.AllocateScalars(VTK_UNSIGNED_CHAR, 3)

    colors = vtkNamedColors()

    rgba = tuple(colors.GetColor4ub('Banana'))

    # Fill every entry of the image data with r, g, b.
    dims = image_data.GetDimensions()
    for z in range(dims[2]):
        for y in range(dims[1]):
            for x in range(dims[0]):
                for i in range(0, 3):
                    image_data.SetScalarComponentFromDouble(x, y, z, i, rgba[i])

    # whole_extent = image_data.GetExtent()
    # Define the extent to be extracted.
    extent = [20, 50, 30, 60, 10, 20]

    # We cannot use vtkImageIterator as it is not wrapped in the Python API so we use indexing.
    # Note that we add 1 to the upper index in extent so that range() works correctly.
    rgba = tuple(colors.GetColor4ub('Tomato'))
    counter = 0
    for z in range(extent[4], extent[5] + 1):
        for y in range(extent[2], extent[3] + 1):
            counter += 1
            for x in range(extent[0], extent[1] + 1):
                for i in range(0, 3):
                    image_data.SetScalarComponentFromDouble(x, y, z, i, rgba[i])

    print(f'Number of spans:      {counter}')
    print(f'Increments:           {fmt_ints(image_data.increments)}')
    inc_x = reference(0)
    inc_y = reference(0)
    inc_z = reference(0)
    image_data.GetContinuousIncrements(extent, inc_x, inc_y, inc_z)
    print(f'ContinuousIncrements: {inc_x}, {inc_y}, {inc_z}')

    # Visualize
    image_viewer = vtkImageViewer2(input_data=image_data)

    style = vtkInteractorStyleImage()
    style.SetInteractionModeToImageSlicing()

    render_window_interactor = vtkRenderWindowInteractor()
    render_window_interactor.interactor_style = style
    image_viewer.SetupInteractor(render_window_interactor)
    slice = (extent[5] - extent[4]) // 2 + extent[4]
    image_viewer.slice = slice

    image_viewer.renderer.background = colors.GetColor3d('Slate_grey')
    image_viewer.image_actor.interpolate = False

    image_viewer.Render()
    image_viewer.renderer.ResetCamera()
    image_viewer.render_window.window_name = 'ImageIteratorDemo'

    image_viewer.Render()

    render_window_interactor.Start()


def fmt_ints(v, w=0):
    """
    Pretty print a list or tuple of ints.

    :param v: The list or tuple of ints.
    :param w: Total width of the field.
    :return: A string.
    """
    return ', '.join([f'{element:{w}}' for element in v])


def fmt_floats(v, w=0, d=6, pt='g'):
    """
    Pretty print a list or tuple of floats.

    :param v: The list or tuple of floats.
    :param w: Total width of the field.
    :param d: The number of decimal places.
    :param pt: The presentation type, 'f', 'g' or 'e'.
    :return: A string.
    """
    pt = pt.lower()
    if pt not in ['f', 'g', 'e']:
        pt = 'f'
    return ', '.join([f'{element:{w}.{d}{pt}}' for element in v])


if __name__ == '__main__':
    main()