Skip to content

Morphological operations on volumetric data

The qim3d library provides a set of methods for different morphological operations on volumes.

qim3d.morphology

Morphological operations for volumetric data.

qim3d.morphology.dilate

dilate(vol, kernel, method='pygorpho.linear', **kwargs)

Dilate an image. If method is either pygorpho.linear or pygorpho.flat, the dilation methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to dilate.

required
kernel int or ndarray

The structuring element/kernel to use while performing dilation. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for dilation. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
dilated_vol ndarray

The dilated volume.

Example
import qim3d
import numpy as np

# Generate tubular synthetic blob
vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

# Visualize synthetic volume
qim3d.viz.volumetric(vol)
# Apply dilation
vol_dilated = qim3d.morphology.dilate(vol, kernel=(8,8,8), method='scipy.ndimage')

# Visualize
qim3d.viz.volumetric(vol_dilated)
Source code in qim3d/morphology/_common_morphologies.py
def dilate(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Dilate an image. If method is either pygorpho.linear or pygorpho.flat, the dilation methods from [Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used. These methods require a GPU, and we therefore recommend using the
    [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
        vol (np.ndarray): The volume to dilate.
        kernel (int or np.ndarray): The structuring element/kernel to use while performing dilation. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
        method (str, optional): Determines the method for dilation. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
        **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
        dilated_vol (np.ndarray): The dilated volume.


    Example:
        ```python
        import qim3d
        import numpy as np

        # Generate tubular synthetic blob
        vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

        # Visualize synthetic volume
        qim3d.viz.volumetric(vol)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_original.html" width="100%" height="500" frameborder="0"></iframe>

        ```python
        # Apply dilation
        vol_dilated = qim3d.morphology.dilate(vol, kernel=(8,8,8), method='scipy.ndimage')

        # Visualize
        qim3d.viz.volumetric(vol_dilated)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_dilated.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.dilate(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.linear_dilate(vol, linesteps, linelens)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.grey_dilation(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)

qim3d.morphology.erode

erode(vol, kernel, method='pygorpho.linear', **kwargs)

Erode an image. If method is either pygorpho.linear or pygorpho.flat, the erosion methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to erode.

required
kernel int or ndarray

The structuring element/kernel to use while performing erosion. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for erosion. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
eroded_vol ndarray

The eroded volume.

Example
    import qim3d
    import numpy as np

    # Generate tubular synthetic blob
    vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

    # Visualize synthetic volume
    qim3d.viz.volumetric(vol)
    # Apply erosion
    vol_eroded = qim3d.morphology.erode(vol, kernel=(10,10,10), method='scipy.ndimage')

    # Visualize
    qim3d.viz.volumetric(vol_eroded)
Source code in qim3d/morphology/_common_morphologies.py
def erode(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Erode an image. If method is either pygorpho.linear or pygorpho.flat, the erosion methods from [Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used. These methods require a GPU, and we therefore recommend using the [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
            vol (np.ndarray): The volume to erode.
            kernel (int or np.ndarray): The structuring element/kernel to use while performing erosion. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
            method (str, optional): Determines the method for erosion. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
            **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
            eroded_vol (np.ndarray): The eroded volume.


    Example:
        ```python
            import qim3d
            import numpy as np

            # Generate tubular synthetic blob
            vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

            # Visualize synthetic volume
            qim3d.viz.volumetric(vol)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_original.html" width="100%" height="500" frameborder="0"></iframe>
        ```python
            # Apply erosion
            vol_eroded = qim3d.morphology.erode(vol, kernel=(10,10,10), method='scipy.ndimage')

            # Visualize
            qim3d.viz.volumetric(vol_eroded)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_eroded.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.erode(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)
        return pg.flat.linear_erode(vol, linesteps, linelens, **kwargs)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.grey_erosion(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)

qim3d.morphology.opening

opening(vol, kernel, method='pygorpho.linear', **kwargs)

Morphologically open a volume. If method is either pygorpho.linear or pygorpho.flat, the open methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to open.

required
kernel int or ndarray

The structuring element/kernel to use while performing erosion. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for opening. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
eroded_vol ndarray

The eroded volume.

Example
import qim3d
import numpy as np

# Generate tubular synthetic blob
vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

# Add noise to the data
vol_noised = qim3d.generate.background(
    background_shape=vol.shape,
    apply_method = 'add',
    apply_to = vol
)

# Visualize synthetic volume
qim3d.viz.volumetric(vol_noised, grid_visible=True)
# Apply opening
vol_opened = qim3d.morphology.opening(vol_noised, kernel=(6,6,6), method='scipy.ndimage')

# Visualize
qim3d.viz.volumetric(vol_opened)
Source code in qim3d/morphology/_common_morphologies.py
def opening(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Morphologically open a volume.
    If method is either pygorpho.linear or pygorpho.flat, the open methods from [Zonohedral Approximation of Spherical Structuring Element for
    Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used.
    These methods require a GPU, and we therefore recommend using the [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
        vol (np.ndarray): The volume to open.
        kernel (int or np.ndarray): The structuring element/kernel to use while performing erosion. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
        method (str, optional): Determines the method for opening. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
        **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
        eroded_vol (np.ndarray): The eroded volume.


    Example:
        ```python
        import qim3d
        import numpy as np

        # Generate tubular synthetic blob
        vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

        # Add noise to the data
        vol_noised = qim3d.generate.background(
            background_shape=vol.shape,
            apply_method = 'add',
            apply_to = vol
        )

        # Visualize synthetic volume
        qim3d.viz.volumetric(vol_noised, grid_visible=True)
        ```

        <iframe src="https://platform.qim.dk/k3d/zonohedra_noised_volume.html" width="100%" height="500" frameborder="0"></iframe>

        ```python

        # Apply opening
        vol_opened = qim3d.morphology.opening(vol_noised, kernel=(6,6,6), method='scipy.ndimage')

        # Visualize
        qim3d.viz.volumetric(vol_opened)
        ```

        <iframe src="https://platform.qim.dk/k3d/zonohedra_opening.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.open(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)
        return pg.flat.linear_open(vol, linesteps, linelens, **kwargs)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.grey_opening(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)

qim3d.morphology.closing

closing(vol, kernel, method='pygorpho.linear', **kwargs)

Morphologically close a volume. If method is either pygorpho.linear or pygorpho.flat, the close methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to be closed.

required
kernel int or ndarray

The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for closing. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
closed_vol ndarray

The closed volume.

Example
import qim3d
import numpy as np

# Generate a cube with a hole through it
cube = np.zeros((110,110,110))
cube[10:90, 10:90, 10:90] = 1
cube[60:70,:,60:70]=0

# Visualize synthetic volume
qim3d.viz.volumetric(cube)
# Apply closing
cube_closed = qim3d.morphology.closing(cube, kernel=(15,15,15), method='scipy.ndimage')

# Visualize
qim3d.viz.volumetric(cube_closed)
Source code in qim3d/morphology/_common_morphologies.py
def closing(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Morphologically close a volume.
    If method is either pygorpho.linear or pygorpho.flat, the close methods from [Zonohedral Approximation of Spherical Structuring Element for
    Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used.
    These methods require a GPU, and we therefore recommend using the [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
        vol (np.ndarray): The volume to be closed.
        kernel (int or np.ndarray): The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
        method (str, optional): Determines the method for closing. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
        **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
        closed_vol (np.ndarray): The closed volume.


    Example:
        ```python
        import qim3d
        import numpy as np

        # Generate a cube with a hole through it
        cube = np.zeros((110,110,110))
        cube[10:90, 10:90, 10:90] = 1
        cube[60:70,:,60:70]=0

        # Visualize synthetic volume
        qim3d.viz.volumetric(cube)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_cube.html" width="100%" height="500" frameborder="0"></iframe>
        ```python
        # Apply closing
        cube_closed = qim3d.morphology.closing(cube, kernel=(15,15,15), method='scipy.ndimage')

        # Visualize
        qim3d.viz.volumetric(cube_closed)
        ```
        <iframe src="https://platform.qim.dk/k3d/zonohedra_cube_closed.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.close(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)
        return pg.flat.linear_close(vol, linesteps, linelens, **kwargs)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.grey_closing(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)

qim3d.morphology.black_tophat

black_tophat(vol, kernel, method='pygorpho.linear', **kwargs)

Perform black tophat operation on a volume. This operation is defined as bothat(x)=close(x)-x. If method is either pygorpho.linear or pygorpho.flat, the close methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to perform the black tophat on.

required
kernel int or ndarray

The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for black tophat. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
bothat_vol ndarray

The morphed volume.

Example
import qim3d
import numpy as np

# Generate tubular synthetic blob
vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

# Visualize synthetic volume
qim3d.viz.volumetric(vol)
# Apply the tophat
vol_black = qim3d.morphology.black_tophat(vol, kernel=(10,10,10), method='scipy.ndimage')

qim3d.viz.volumetric(vol_black)
Source code in qim3d/morphology/_common_morphologies.py
def black_tophat(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Perform black tophat operation on a volume.
    This operation is defined as bothat(x)=close(x)-x.
    If method is either pygorpho.linear or pygorpho.flat, the close methods from [Zonohedral Approximation of Spherical Structuring Element for
    Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used.
    These methods require a GPU, and we therefore recommend using the [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
        vol (np.ndarray): The volume to perform the black tophat on.
        kernel (int or np.ndarray): The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
        method (str, optional): Determines the method for black tophat. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
        **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
        bothat_vol (np.ndarray): The morphed volume.


    Example:
            ```python
            import qim3d
            import numpy as np

            # Generate tubular synthetic blob
            vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

            # Visualize synthetic volume
            qim3d.viz.volumetric(vol)
            ```
            <iframe src="https://platform.qim.dk/k3d/zonohedra_original.html" width="100%" height="500" frameborder="0"></iframe>
            ```python
            # Apply the tophat
            vol_black = qim3d.morphology.black_tophat(vol, kernel=(10,10,10), method='scipy.ndimage')

            qim3d.viz.volumetric(vol_black)
            ```
            <iframe src="https://platform.qim.dk/k3d/zonohedra_black_tophat.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.bothat(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)
        return pg.flat.bothat(vol, linesteps, linelens, **kwargs)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.black_tophat(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)

qim3d.morphology.white_tophat

white_tophat(vol, kernel, method='pygorpho.linear', **kwargs)

Perform white tophat operation on a volume. This operation is defined as tophat(x)=x-open(x). If method is either pygorpho.linear or pygorpho.flat, the open methods from Zonohedral Approximation of Spherical Structuring Element for Volumetric Morphology are used. These methods require a GPU, and we therefore recommend using the scipy implementation (scipy.ndimage) if no GPU is available on your current device.

Parameters:

Name Type Description Default
vol ndarray

The volume to perform the white tophat on.

required
kernel int or ndarray

The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.

required
method str

Determines the method for white tophat. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.

'pygorpho.linear'
**kwargs Any

Additional keyword arguments for the used method. See the documentation for more information.

{}

Returns:

Name Type Description
tophat_vol ndarray

The morphed volume.

Example
import qim3d
import numpy as np

# Generate tubular synthetic blob
vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

# Visualize synthetic volume
qim3d.viz.volumetric(vol)
# Apply tophat
vol_white = qim3d.morphology.white_tophat(vol, kernel=(10,10,10), method='scipy.ndimage')

qim3d.viz.volumetric(vol_white)
Source code in qim3d/morphology/_common_morphologies.py
def white_tophat(
    vol: np.ndarray, kernel: int | np.ndarray, method: str = 'pygorpho.linear', **kwargs
) -> np.ndarray:
    """
    Perform white tophat operation on a volume.
    This operation is defined as tophat(x)=x-open(x).
    If method is either pygorpho.linear or pygorpho.flat, the open methods from [Zonohedral Approximation of Spherical Structuring Element for
    Volumetric Morphology](https://backend.orbit.dtu.dk/ws/portalfiles/portal/172879029/SCIA19_Zonohedra.pdf) are used.
    These methods require a GPU, and we therefore recommend using the [scipy implementation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.grey_dilation.html) (scipy.ndimage) if no GPU is available on your current device.

    Args:
        vol (np.ndarray): The volume to perform the white tophat on.
        kernel (int or np.ndarray): The structuring element/kernel to use while performing opening. Note that the kernel should be 3D unless if the linear method is used. If this method is used, a kernel resembling a ball will be created with an integer radius.
        method (str, optional): Determines the method for white tophat. Use either 'pygorpho.linear', 'pygorpho.flat' or 'scipy.ndimage'. Defaults to 'pygorpho.linear'.
        **kwargs (Any): Additional keyword arguments for the used method. See the documentation for more information.

    Returns:
        tophat_vol (np.ndarray): The morphed volume.


    Example:
            ```python
            import qim3d
            import numpy as np

            # Generate tubular synthetic blob
            vol = qim3d.generate.volume(noise_scale=0.025, seed=50)

            # Visualize synthetic volume
            qim3d.viz.volumetric(vol)
            ```
            <iframe src="https://platform.qim.dk/k3d/zonohedra_original.html" width="100%" height="500" frameborder="0"></iframe>

            ```python
            # Apply tophat
            vol_white = qim3d.morphology.white_tophat(vol, kernel=(10,10,10), method='scipy.ndimage')

            qim3d.viz.volumetric(vol_white)
            ```
            <iframe src="https://platform.qim.dk/k3d/zonohedra_white_tophat.html" width="100%" height="500" frameborder="0"></iframe>

    """

    try:
        vol = np.asarray(vol)
    except TypeError as e:
        err = 'Input volume must be array-like.'
        raise TypeError(err) from e

    assert len(vol.shape) == 3, 'Volume must be three-dimensional.'

    if method == 'pygorpho.flat':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        return pg.flat.tophat(vol, kernel, **kwargs)

    elif method == 'pygorpho.linear':
        assert isinstance(
            kernel, int
        ), 'Kernel is generated within function and must therefore be an integer.'

        if not pg.cuda.get_device_count():
            err = 'no CUDA device available. Use method=scipy.ndimage.'
            raise RuntimeError(err)

        linesteps, linelens = pg.strel.flat_ball_approx(kernel)
        return pg.flat.tophat(vol, linesteps, linelens, **kwargs)

    elif method == 'scipy.ndimage':
        kernel = _create_kernel(kernel)
        assert kernel.ndim == 3, 'Kernel must a 3D np.ndarray.'

        return ndi.white_tophat(vol, footprint=kernel, **kwargs)

    else:
        err = 'Unknown closing method.'
        raise ValueError(err)