# Upsample a mask the same way that Slicer does

**URL:** https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053
**Category:** Algorithms
**Tags:** simpleitk
**Created:** [June 4, 2022, 8:16pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053 "2022-06-04T20:16:36Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![ibro45](https://discourse.itk.org/user_avatar/discourse.itk.org/ibro45/32/1639_2.png) [@ibro45](https://discourse.itk.org/u/ibro45)
#### Post date: [June 4, 2022, 8:16pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/1 "2022-06-04T20:16:36Z")

</div>

Hi all,

For each scan, I have a mask that was segmented out on a cropped and downsampled version of that scan. Loading such a mask in Slicer automatically upsamples it and places it correctly in the physical space of the original scan.

I wish to mimic that with SimpleITK. While I did manage to convert the mask to the same size and spacing as the original scan, the mask itself is grainy. How can I interpolate the mask to achieve the same quality as Slicer does?

---

<div class="post-metadata">

### Author: ![mauigna06](https://discourse.itk.org/letter_avatar_proxy/v4/letter/m/ccd318/32.png) [@mauigna06](https://discourse.itk.org/u/mauigna06)
#### Post date: [June 5, 2022, 10:51am UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/2 "2022-06-05T10:51:53Z")

</div>

I think you could try to use Slicer console execution to do this processing. You just need to use the Slicer’s CLI module "Crop Volume

Hope it helps

Mauro

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [June 5, 2022, 2:55pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/3 "2022-06-05T14:55:37Z")

</div>

Hello @ibro45,

Which [interpolator enumeration](https://simpleitk.org/doxygen/latest/html/namespaceitk_1_1simple.html#a7cb1ef8bd02c669c02ea2f9f5aa374e5) are you specifying when doing the resampling? For segmentation images you can either use `sitkNearestNeighbor` or `sitkLabelGaussian` for a smoother looking interpolation.

Another option is to use a distance map:

```auto
low_res_dist_map = sitk.SignedMaurerDistanceMap(low_res_binary_seg, squaredDistance=False, useImageSpacing=True)
high_res_distance_map = sitk.Resample(low_res_dist_map, high_res_image, interpolator = sitk.sitkLinear) # or use a higher order interpolator as desired.
high_res_binary_seg = high_res_distance_map<=0

```

---

<div class="post-metadata">

### Author: ![ibro45](https://discourse.itk.org/user_avatar/discourse.itk.org/ibro45/32/1639_2.png) [@ibro45](https://discourse.itk.org/u/ibro45)
#### Post date: [June 6, 2022, 7:05pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/4 "2022-06-06T19:05:44Z")

</div>

Hi @zivy ,

Thanks for the answer. I’m dealing with multi-label masks so I treated each mask as a separate binary mask and did what you proposed. However, the resulting labels overlap, and I would like to avoid that as that was not the case in the original mask. Do you have an idea of how to handle it gracefully?

Thank you!

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [June 6, 2022, 8:03pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/5 "2022-06-06T20:03:38Z")

</div>

> [@ibro45](#):
>
> Thanks for the answer. I’m dealing with multi-label masks so I treated each mask as a separate binary mask and did what you proposed.

The `sitkNearestNeighbor` or `sitkLabelGaussian` interpolators should be used on the multi-label mask not multiple binary masks.

Alternatively, if each mask is (0,id), where id it the label id, Then something as simple as a “max” filter could naively resolve the overlap.

---

<div class="post-metadata">

### Author: ![ibro45](https://discourse.itk.org/user_avatar/discourse.itk.org/ibro45/32/1639_2.png) [@ibro45](https://discourse.itk.org/u/ibro45)
#### Post date: [June 24, 2022, 10:29pm UTC](https://discourse.itk.org/t/upsample-a-mask-the-same-way-that-slicer-does/5053/6 "2022-06-24T22:29:30Z")

</div>

Thanks everyone, ended up diving into the slicer scripting for the first time and it was worth it. In case anyone’s interested:

```auto
from pathlib import Path

import slicer
import SimpleITK as sitk

def export_segmentation_with_adjusted_geometry(segmentation_path, reference_volume_path):
    """Process the given segmentation so that it matches the geometry of a reference volume.
    The adjusted segmentation is exported to the same folder as the input segmentation, and
    its filename is the same except for the additional `_adjusted` suffix.
    """
    segmentation_path = Path(segmentation_path)
    reference_volume_path = Path(reference_volume_path)
    
    # Ensures that the processed segmentation is saved in the same folder as the original
    slicer.mrmlScene.SetRootDirectory(str(segmentation_path.parent))

    # Load the reference volume and the segmentation
    volume = slicer.util.loadVolume(str(reference_volume_path))
    segmentation = slicer.util.loadSegmentation(str(segmentation_path))
    
    # Reference volume has to be a VTK's OrientedImageData object
    volume = slicer.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(volume)
    # Get the reference volume's geometry
    volume_geometry = slicer.vtkSegmentationConverter.SerializeImageGeometry(volume)
    param = slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName()
    # Resample the segmentation to the reference volume's geometry
    segmentation.GetSegmentation().SetConversionParameter(param, volume_geometry)
    
    # The destination folder is defined at the start of this function using SetRootDirectory()
    filename = segmentation_path.name.split('.')[0] + "_adjusted.seg.nrrd"
    slicer.util.saveNode(segmentation, filename)
    slicer.mrmlScene.Clear()

```
