Beispiel #1
0
    def _map_source_images_to_segmentation(
            self, segmentation: sitk.Image,
            source_images: List[pydicom.Dataset]
    ) -> List[List[pydicom.Dataset]]:
        """Maps an list of source image datasets to the slices of a
        SimpleITK image.

        Args:
            segmentation: A `SimpleITK.Image` with integer labels and a single
                component per spatial location.
            source_images: A list of `pydicom.Dataset` which are the
                source images for the segmentation image.

        Returns:
            A `list` with a `list` for each slice, which contains the mapped
            `pydicom.Dataset` instances for that slice location. Slices can
            have zero or more matched datasets.
        """
        result: List[List[pydicom.Dataset]] = [
            list() for _ in range(segmentation.GetDepth())
        ]
        for source_image in source_images:
            position = [float(x) for x in source_image.ImagePositionPatient]
            index = segmentation.TransformPhysicalPointToIndex(position)
            if index[2] < 0 or index[2] >= segmentation.GetDepth():
                continue
            # TODO Add reverse check if segmentation is contained in image
            result[index[2]].append(source_image)
        slices_mapped = sum(len(x) > 0 for x in result)
        logger.info(f"{slices_mapped} of {segmentation.GetDepth()} slices"
                    "mapped to source DICOM images")
        return result
 def __init__(self, data: sitk.Image, segmentation: sitk.Image, bb_size):
     self.segmentation = segmentation
     # place bb so that the segmentation is centered
     self.offset = (
         (np.array(bb_size) - np.array(self.segmentation.GetSize())) /
         2).astype(int)
     # adjust offset if resulting bb is out of bounds
     segmentation_origin_in_data = data.TransformPhysicalPointToIndex(
         segmentation.GetOrigin())
     self.offset = [
         seg_or if seg_or - off < 0 else off
         for seg_or, off in zip(segmentation_origin_in_data, self.offset)
     ]
     self.offset = [
         off + ((seg_or - off + bb_sz) - data_sz)
         if seg_or - off + bb_sz > data_sz else off for seg_or, off, bb_sz,
         data_sz in zip(segmentation_origin_in_data, self.offset, bb_size,
                        data.GetSize())
     ]
     cropped_origin = np.array(segmentation_origin_in_data) - self.offset
     assert all(cr_or >= 0 for cr_or in cropped_origin), \
         f"Data size: {data.GetSize()}, BB size: {bb_size}, BB origin: {cropped_origin}"
     assert all(cr_or + bb_s <= data_s for cr_or, bb_s, data_s in zip(cropped_origin, bb_size, data.GetSize())), \
         f"Data size: {data.GetSize()}, BB size: {bb_size}, BB origin: {cropped_origin}"
     self.data = data[cropped_origin[0]:cropped_origin[0] + bb_size[0],
                      cropped_origin[1]:cropped_origin[1] + bb_size[1],
                      cropped_origin[2]:cropped_origin[2] + bb_size[2]]
Beispiel #3
0
def centroid(mask: sitk.Image,
             label: int = 1,
             world_coordinates: bool = False) -> tuple:
    """Find the centroid of a labelled region specified by a segmentation mask.

    Parameters
    ----------
    mask
        Segmentation mask describing the region of interest. Can be an image of
        type unsigned int representing a label map or `segmentation.Segmentation`.

    label, optional
        Label to use when computing the centroid if segmentation mask contains
        more than 1 labelled region.

    world_coordinates, optional
        If True, return centroid in world coordinates, otherwise in image
        (voxel) coordinates (default).

    Returns
    -------
    tuple
        The centroid coordinates.
    """

    if isinstance(mask, Segmentation):
        seg = Segmentation(mask)
        mask = seg.get_label(label=label, relabel=True)

    filter_ = sitk.LabelShapeStatisticsImageFilter()
    filter_.Execute(mask)
    centroid_coords = filter_.GetCentroid(label)
    if not world_coordinates:
        centroid_coords = mask.TransformPhysicalPointToIndex(centroid_coords)
    return centroid_coords
Beispiel #4
0
def get_cuboid_image(radii_world, reference: sitk.Image, center_ras):
    r, a, s = center_ras
    center_lps = -r, -a, s
    center_voxel = reference.TransformPhysicalPointToIndex(center_lps)
    spacing = np.array(reference.GetSpacing())
    radii_voxel = np.array(radii_world) / spacing
    radii_voxel = radii_voxel.round().astype(np.uint16)
    axes_voxel = 2 * radii_voxel
    cuboid = sitk.Image(*axes_voxel.tolist(), sitk.sitkUInt8) + 1
    result = reference * 0
    destination = (center_voxel - radii_voxel).tolist()
    paste = sitk.PasteImageFilter()
    paste.SetDestinationIndex(destination)
    paste.SetSourceSize(cuboid.GetSize())
    result = paste.Execute(result, cuboid)
    return result
Beispiel #5
0
def find_centroid(mask: sitk.Image) -> np.ndarray:
    """Find the centroid of a binary image in image
    coordinates.

    Parameters
    ----------
    mask
        The binary mask image.

    Returns
    -------
    np.ndarray
        The (x, y, z) coordinates of the centroid
        in image space.
    """
    stats = sitk.LabelShapeStatisticsImageFilter()
    stats.Execute(mask)
    centroid_coords = stats.GetCentroid(1)
    centroid_idx = mask.TransformPhysicalPointToIndex(centroid_coords)
    return np.asarray(centroid_idx, dtype=np.float64)