diff --git a/monai/data/utils.py b/monai/data/utils.py index 4c024f0d5a..2f395c9065 100644 --- a/monai/data/utils.py +++ b/monai/data/utils.py @@ -875,17 +875,19 @@ def compute_shape_offset( corners_out = inv_mat @ corners corners_out = corners_out[:-1] / corners_out[-1] out_shape = np.round(corners_out.ptp(axis=1)) if scale_extent else np.round(corners_out.ptp(axis=1) + 1.0) - mat = inv_mat[:-1, :-1] - i = 0 + all_dist = inv_mat[:-1, :-1] @ corners[:-1, :] + offset = None for i in range(corners.shape[1]): - min_corner = np.min(mat @ corners[:-1, :] - mat @ corners[:-1, i : i + 1], 1) + min_corner = np.min(all_dist - all_dist[:, i : i + 1], 1) if np.allclose(min_corner, 0.0, rtol=AFFINE_TOL): + offset = corners[:-1, i] # corner is the smallest, shift the corner to origin break - offset = corners[:-1, i] + if offset is None: # otherwise make output image center aligned with the input image center + offset = in_affine_[:-1, :-1] @ (shape / 2.0) + in_affine_[:-1, -1] - out_affine_[:-1, :-1] @ (out_shape / 2.0) if scale_extent: in_offset = np.append(0.5 * (shape / out_shape - 1.0), 1.0) offset = np.abs((in_affine_ @ in_offset / in_offset[-1])[:-1]) * np.sign(offset) - return out_shape.astype(int, copy=False), offset + return out_shape.astype(int, copy=False), offset # type: ignore def to_affine_nd(r: Union[np.ndarray, int], affine: NdarrayTensor, dtype=np.float64) -> NdarrayTensor: diff --git a/tests/test_spacing.py b/tests/test_spacing.py index 6dde57efd9..c260171d02 100644 --- a/tests/test_spacing.py +++ b/tests/test_spacing.py @@ -230,6 +230,24 @@ *device, ] ) + TESTS.append( # 5D input + [ + {"pixdim": 0.5, "padding_mode": "zeros", "mode": "nearest", "scale_extent": True}, + torch.ones((1, 368, 336, 368)), # data + torch.tensor( + [ + [0.41, 0.005, 0.008, -79.7], + [-0.0049, 0.592, 0.0664, -57.4], + [-0.0073, -0.0972, 0.404, -32.1], + [0.0, 0.0, 0.0, 1.0], + ] + ), + {}, + torch.ones((1, 302, 403, 301)), + *device, + ] + ) + TESTS_TORCH = [] for track_meta in (False, True):