Ejemplo n.º 1
0
    def inverse(
            self, data: Mapping[Hashable,
                                np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))

        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = transform[InverseKeys.ORIG_SIZE.value]
            random_center = self.random_center
            pad_to_start = np.empty((len(orig_size)), dtype=np.int32)
            pad_to_end = np.empty((len(orig_size)), dtype=np.int32)
            if random_center:
                for i, _slice in enumerate(
                        transform[InverseKeys.EXTRA_INFO.value]["slices"]):
                    pad_to_start[i] = _slice[0]
                    pad_to_end[i] = orig_size[i] - _slice[1]
            else:
                current_size = d[key].shape[1:]
                for i, (o_s, c_s) in enumerate(zip(orig_size, current_size)):
                    pad_to_start[i] = pad_to_end[i] = (o_s - c_s) / 2
                    if o_s % 2 == 0 and c_s % 2 == 1:
                        pad_to_start[i] += 1
                    elif o_s % 2 == 1 and c_s % 2 == 0:
                        pad_to_end[i] += 1
            # interleave mins and maxes
            pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
            inverse_transform = BorderPad(pad)
            # Apply inverse transform
            d[key] = inverse_transform(d[key])
            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 2
0
    def inverse(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))
        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = np.array(transform[InverseKeys.ORIG_SIZE])
            current_size = np.array(d[key].shape[1:])
            # Unfortunately, we can't just use ResizeWithPadOrCrop with original size because of odd/even rounding.
            # Instead, we first pad any smaller dimensions, and then we crop any larger dimensions.

            # First, do pad
            if np.any((orig_size - current_size) > 0):
                pad_to_start = np.floor((orig_size - current_size) / 2).astype(int)
                # in each direction, if original size is even and current size is odd, += 1
                pad_to_start[np.logical_and(orig_size % 2 == 0, current_size % 2 == 1)] += 1
                pad_to_start[pad_to_start < 0] = 0
                pad_to_end = orig_size - current_size - pad_to_start
                pad_to_end[pad_to_end < 0] = 0
                pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
                d[key] = BorderPad(pad)(d[key])

            # Next crop
            if np.any((orig_size - current_size) < 0):
                if self.padcropper.padder.method == Method.SYMMETRIC:
                    roi_center = [floor(i / 2) if r % 2 == 0 else (i - 1) // 2 for r, i in zip(orig_size, current_size)]
                else:
                    roi_center = [floor(r / 2) if r % 2 == 0 else (r - 1) // 2 for r in orig_size]

                d[key] = SpatialCrop(roi_center, orig_size)(d[key])

            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 3
0
    def __init__(
        self,
        keys: KeysCollection,
        spatial_border: Union[Sequence[int], int],
        mode: NumpyPadModeSequence = NumpyPadMode.CONSTANT,
        allow_missing_keys: bool = False,
    ) -> None:
        """
        Args:
            keys: keys of the corresponding items to be transformed.
                See also: :py:class:`monai.transforms.compose.MapTransform`
            spatial_border: specified size for every spatial border. it can be 3 shapes:

                - single int number, pad all the borders with the same size.
                - length equals the length of image shape, pad every spatial dimension separately.
                  for example, image shape(CHW) is [1, 4, 4], spatial_border is [2, 1],
                  pad every border of H dim with 2, pad every border of W dim with 1, result shape is [1, 8, 6].
                - length equals 2 x (length of image shape), pad every border of every dimension separately.
                  for example, image shape(CHW) is [1, 4, 4], spatial_border is [1, 2, 3, 4], pad top of H dim with 1,
                  pad bottom of H dim with 2, pad left of W dim with 3, pad right of W dim with 4.
                  the result shape is [1, 7, 11].

            mode: {``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``,
                ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
                One of the listed string values or a user supplied function. Defaults to ``"constant"``.
                See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
                It also can be a sequence of string, each element corresponds to a key in ``keys``.
            allow_missing_keys: don't raise exception if key is missing.

        """
        super().__init__(keys, allow_missing_keys)
        self.mode = ensure_tuple_rep(mode, len(self.keys))
        self.padder = BorderPad(spatial_border=spatial_border)
Ejemplo n.º 4
0
    def inverse(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))
        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = np.asarray(transform[InverseKeys.ORIG_SIZE])
            cur_size = np.asarray(d[key].shape[1:])
            extra_info = transform[InverseKeys.EXTRA_INFO]
            box_start = np.asarray(extra_info["box_start"])
            box_end = np.asarray(extra_info["box_end"])
            # first crop the padding part
            roi_start = np.maximum(-box_start, 0)
            roi_end = cur_size - np.maximum(box_end - orig_size, 0)

            d[key] = SpatialCrop(roi_start=roi_start, roi_end=roi_end)(d[key])

            # update bounding box to pad
            pad_to_start = np.maximum(box_start, 0)
            pad_to_end = orig_size - np.minimum(box_end, orig_size)
            # interleave mins and maxes
            pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
            # second pad back the original size
            d[key] = BorderPad(pad)(d[key])
            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 5
0
    def inverse(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))
        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = np.array(transform[InverseKeys.ORIG_SIZE])
            extra_info = transform[InverseKeys.EXTRA_INFO]
            pad_to_start = np.array(extra_info["box_start"])
            pad_to_end = orig_size - np.array(extra_info["box_end"])
            # interleave mins and maxes
            pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
            inverse_transform = BorderPad(pad)
            # Apply inverse transform
            d[key] = inverse_transform(d[key])
            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 6
0
    def inverse(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))

        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = np.array(transform[InverseKeys.ORIG_SIZE])
            current_size = np.array(d[key].shape[1:])
            pad_to_start = np.floor((orig_size - current_size) / 2).astype(int)
            # in each direction, if original size is even and current size is odd, += 1
            pad_to_start[np.logical_and(orig_size % 2 == 0, current_size % 2 == 1)] += 1
            pad_to_end = orig_size - current_size - pad_to_start
            pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
            inverse_transform = BorderPad(pad)
            # Apply inverse transform
            d[key] = inverse_transform(d[key])
            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 7
0
    def inverse(self, data: Mapping[Hashable, np.ndarray]) -> Dict[Hashable, np.ndarray]:
        d = deepcopy(dict(data))

        for key in self.key_iterator(d):
            transform = self.get_most_recent_transform(d, key)
            # Create inverse transform
            orig_size = np.array(transform[InverseKeys.ORIG_SIZE])
            current_size = np.array(d[key].shape[1:])
            # get required pad to start and end
            pad_to_start = np.array([s.indices(o)[0] for s, o in zip(self.cropper.slices, orig_size)])
            pad_to_end = orig_size - current_size - pad_to_start
            # interleave mins and maxes
            pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
            inverse_transform = BorderPad(pad)
            # Apply inverse transform
            d[key] = inverse_transform(d[key])
            # Remove the applied transform
            self.pop_transform(d, key)

        return d
Ejemplo n.º 8
0
    def __init__(self, keys: KeysCollection, spatial_border, mode="constant"):
        """
        Args:
            spatial_border (int or sequence of int): specified size for every spatial border. it can be 3 shapes:
                - single int number, pad all the borders with the same size.
                - length equals the length of image shape, pad every spatial dimension separately.
                    for example, image shape(CHW) is [1, 4, 4], spatial_border is [2, 1],
                    pad every border of H dim with 2, pad every border of W dim with 1, result shape is [1, 8, 6].
                - length equals 2 x (length of image shape), pad every border of every dimension separately.
                    for example, image shape(CHW) is [1, 4, 4], spatial_border is [1, 2, 3, 4], pad top of H dim with 1,
                    pad bottom of H dim with 2, pad left of W dim with 3, pad right of W dim with 4.
                    the result shape is [1, 7, 11].
            mode (str or sequence of str): one of the following string values or a user supplied function:
                {'constant', 'edge', 'linear_ramp', 'maximum', 'mean', 'median', 'minimum', 'reflect',
                'symmetric', 'wrap', 'empty', <function>}
                user can set a sequence of mode values corresponding to every item specified by `keys`.
                for more details, please check: https://docs.scipy.org/doc/numpy/reference/generated/numpy.pad.html

        """
        super().__init__(keys)
        self.mode = ensure_tuple_rep(mode, len(self.keys))
        self.padder = BorderPad(spatial_border=spatial_border)