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
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
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)
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
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
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
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
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)