Skip to content

Imageutils

imageutils #

Functions:

Name Description
array_to_image

Convert a numpy array to a SimpleITK image with optional metadata.

idxs_to_physical_points

Converts image indices to physical points based on the reference image's

image_to_array

Convert a SimpleITK image to a numpy array along with its metadata.

physical_points_to_idxs

Convert physical points to image indices based on the reference image's

array_to_image #

array_to_image(
    array: numpy.ndarray,
    origin: imgtools.utils.imageutils.Array3D = (
        0.0,
        0.0,
        0.0,
    ),
    direction: typing.Tuple[float, ...] = (
        1.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        0.0,
        0.0,
        1.0,
    ),
    spacing: imgtools.utils.imageutils.Array3D = (
        1.0,
        1.0,
        1.0,
    ),
    reference_image: SimpleITK.Image | None = None,
) -> SimpleITK.Image

Convert a numpy array to a SimpleITK image with optional metadata.

Parameters:

Name Type Description Default

array #

numpy.ndarray

The numpy array to convert.

required

origin #

imgtools.utils.imageutils.Array3D

The origin of the image (default is (0.0, 0.0, 0.0)).

(0.0, 0.0, 0.0)

direction #

typing.Tuple[float, ...]

The direction cosines of the image (default is identity matrix).

(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)

spacing #

imgtools.utils.imageutils.Array3D

The pixel spacing of the image (default is (1.0, 1.0, 1.0)).

(1.0, 1.0, 1.0)

reference_image #

SimpleITK.Image

A reference SimpleITK image to copy metadata from (default is None).

None

Returns:

Type Description
SimpleITK.Image

The resulting SimpleITK image.

Source code in src/imgtools/utils/imageutils.py
def array_to_image(
    array: np.ndarray,
    origin: Array3D = (0.0, 0.0, 0.0),
    direction: Tuple[float, ...] = (
        1.0,
        0.0,
        0.0,
        0.0,
        1.0,
        0.0,
        0.0,
        0.0,
        1.0,
    ),
    spacing: Array3D = (1.0, 1.0, 1.0),
    reference_image: sitk.Image | None = None,
) -> sitk.Image:
    """Convert a numpy array to a SimpleITK image with optional metadata.

    Parameters
    ----------
    array : np.ndarray
        The numpy array to convert.
    origin : Array3D, optional
        The origin of the image (default is (0.0, 0.0, 0.0)).
    direction : Tuple[float, ...], optional
        The direction cosines of the image (default is identity matrix).
    spacing : Array3D, optional
        The pixel spacing of the image (default is (1.0, 1.0, 1.0)).
    reference_image : sitk.Image, optional
        A reference SimpleITK image to copy metadata from (default is None).

    Returns
    -------
    sitk.Image
        The resulting SimpleITK image.
    """
    image = sitk.GetImageFromArray(array)
    if reference_image is not None:
        image.CopyInformation(reference_image)
    elif all(x is not None for x in (origin, direction, spacing)):
        image.SetOrigin(origin)
        image.SetDirection(direction)
        image.SetSpacing(spacing)
    else:
        errmsg = (
            "Either a reference image or all of the origin, direction, and spacing "
            "must be provided to create a new image."
        )
        raise ValueError(errmsg)

    return image

idxs_to_physical_points #

idxs_to_physical_points(
    image: SimpleITK.Image, idxs: numpy.ndarray
) -> numpy.ndarray

Converts image indices to physical points based on the reference image's geometry.

Parameters:

Name Type Description Default

image #

SimpleITK.Image

The reference SimpleITK image.

required

idxs #

numpy.ndarray

Array of 3D indices (continuous or discrete).

required

Returns:

Type Description
numpy.ndarray

Physical coordinates corresponding to the given indices.

Source code in src/imgtools/utils/imageutils.py
def idxs_to_physical_points(image: sitk.Image, idxs: np.ndarray) -> np.ndarray:
    """
    Converts image indices to physical points based on the reference image's
    geometry.

    Parameters
    ----------
    image : sitk.Image
        The reference SimpleITK image.
    idxs : np.ndarray
        Array of 3D indices (continuous or discrete).

    Returns
    -------
    np.ndarray
        Physical coordinates corresponding to the given indices.
    """
    continuous = np.issubdtype(idxs.dtype, np.floating)

    # TransformIndexToPhysicalPoint expects a list not a numpy array

    transform = (
        image.TransformContinuousIndexToPhysicalPoint
        if continuous
        else image.TransformIndexToPhysicalPoint
    )
    # vectorized_transform = np.vectorize(
    #     lambda x: np.array(transform(x)), signature="(3)->(3)"
    # )
    # return vectorized_transform(idxs)

    # Convert indices to lists of lists and apply the transformation
    idxs_list = idxs.tolist()
    return np.array([transform(idx) for idx in idxs_list])

image_to_array #

image_to_array(
    image: SimpleITK.Image,
) -> imgtools.utils.imageutils.ImageArrayMetadata

Convert a SimpleITK image to a numpy array along with its metadata.

Parameters:

Name Type Description Default

image #

SimpleITK.Image

The SimpleITK image to convert.

required

Returns:

Name Type Description
ImageArrayMetadata typing.Tuple[numpy.ndarray, imgtools.utils.imageutils.Array3D, imgtools.utils.imageutils.Array3D, imgtools.utils.imageutils.Array3D]

A tuple containing: - The image as a numpy array. - The origin of the image (tuple of floats). - The direction cosines of the image (tuple of floats). - The pixel spacing of the image (tuple of floats).

Source code in src/imgtools/utils/imageutils.py
def image_to_array(image: sitk.Image) -> ImageArrayMetadata:
    """Convert a SimpleITK image to a numpy array along with its metadata.

    Parameters
    ----------
    image : sitk.Image
        The SimpleITK image to convert.

    Returns
    -------
    ImageArrayMetadata : Tuple[np.ndarray, Array3D, Array3D, Array3D]
        A tuple containing:
        - The image as a numpy array.
        - The origin of the image (tuple of floats).
        - The direction cosines of the image (tuple of floats).
        - The pixel spacing of the image (tuple of floats).
    """
    array: np.ndarray = sitk.GetArrayFromImage(image)
    return array, image["origin"], image["direction"], image["spacing"]

physical_points_to_idxs #

physical_points_to_idxs(
    image: SimpleITK.Image,
    points: typing.List[numpy.ndarray],
    continuous: bool = False,
) -> typing.List[numpy.ndarray]

Convert physical points to image indices based on the reference image's geometry.

This function uses the geometry of a SimpleITK image (origin, spacing, direction) to convert real-world physical coordinates into indices in the image grid. It optionally supports continuous indices for sub-pixel precision.

Parameters:

Name Type Description Default

image #

SimpleITK.Image

The reference SimpleITK image.

required

points #

typing.List[numpy.ndarray]

List of 3D physical points to transform.

required

continuous #

bool

If True, returns continuous indices; otherwise, returns integer indices. Default is False.

False

Returns:

Type Description
typing.List[numpy.ndarray]

A list of transformed points in image index space, reversed to match library conventions.

Notes

The following steps occur within the function: 1. A numpy.vectorize function is defined to apply the transformation method (physical to index) to each 3D point in the input array. 2. The transformation is applied to each set of points in the list, reversing the coordinate order to match the library's indexing convention.

Source code in src/imgtools/utils/imageutils.py
def physical_points_to_idxs(
    image: sitk.Image,
    points: List[np.ndarray],
    continuous: bool = False,
) -> List[np.ndarray]:
    """Convert physical points to image indices based on the reference image's
    geometry.

    This function uses the geometry of a SimpleITK image (origin, spacing,
    direction) to convert real-world physical coordinates into indices in the
    image grid. It optionally supports continuous indices for sub-pixel
    precision.

    Parameters
    ----------
    image : sitk.Image
        The reference SimpleITK image.
    points : List[np.ndarray]
        List of 3D physical points to transform.
    continuous : bool, optional
        If True, returns continuous indices; otherwise, returns integer indices.
        Default is False.

    Returns
    -------
    List[np.ndarray]
        A list of transformed points in image index space, reversed to match
        library conventions.

    Notes
    -----
    The following steps occur within the function:
    1. A `numpy.vectorize` function is defined to apply the transformation
       method (physical to index) to each 3D point in the input array.
    2. The transformation is applied to each set of points in the list,
       reversing the coordinate order to match the library's indexing
       convention.
    """
    # Select the appropriate transformation function based on the `continuous` parameter.
    transform = (
        image.TransformPhysicalPointToContinuousIndex
        if continuous
        else image.TransformPhysicalPointToIndex
    )

    # Step 1: Define a vectorized transformation function
    # The lambda function takes a single 3D point `x` and:
    # - Applies the selected transformation (`transform(x)`) to convert it from physical space to index space.
    # - Wraps the result into a numpy array for further processing.
    # `np.vectorize` creates a vectorized function that can process arrays of points in one call.
    # The `signature="(3)->(3)"` ensures the transformation operates on 3D points, returning 3D results.
    vectorized_transform = np.vectorize(
        lambda x: np.array(transform(x)), signature="(3)->(3)"
    )

    # Step 2: Apply the vectorized transformation to all slices of points.
    # For each 2D array `slc` in the `points` list:
    # - `vectorized_transform(slc)` applies the transformation to all points in `slc`.
    # - `[:, ::-1]` reverses the coordinate order (from (x, y, z) to (z, y, x)) to match the library's convention.
    # The result is stored as a list of numpy arrays (`t_points`), each corresponding to a transformed slice.
    t_points: List[np.ndarray] = [
        vectorized_transform(slc)[:, ::-1] for slc in points
    ]

    # Return the list of transformed points.
    return t_points