Resample `data` using the affine transformation defined by ``matrix``. Args: data: input data to be resampled. matrix: affine transformation matrix. kwargs: currently supports (see also: ``monai.utils.enums.LazyAttr``) - "lazy_shape" for output spatial
(data: torch.Tensor, matrix: NdarrayOrTensor, kwargs: dict | None = None)
| 156 | |
| 157 | |
| 158 | def resample(data: torch.Tensor, matrix: NdarrayOrTensor, kwargs: dict | None = None): |
| 159 | """ |
| 160 | Resample `data` using the affine transformation defined by ``matrix``. |
| 161 | |
| 162 | Args: |
| 163 | data: input data to be resampled. |
| 164 | matrix: affine transformation matrix. |
| 165 | kwargs: currently supports (see also: ``monai.utils.enums.LazyAttr``) |
| 166 | |
| 167 | - "lazy_shape" for output spatial shape |
| 168 | - "lazy_padding_mode" |
| 169 | - "lazy_interpolation_mode" (this option might be ignored when ``mode="auto"``.) |
| 170 | - "lazy_align_corners" |
| 171 | - "lazy_dtype" (dtype for resampling computation; this might be ignored when ``mode="auto"``.) |
| 172 | - "atol" for tolerance for matrix floating point comparison. |
| 173 | - "lazy_resample_mode" for resampling backend, default to `"auto"`. Setting to other values will use the |
| 174 | `monai.transforms.SpatialResample` for resampling. |
| 175 | |
| 176 | See Also: |
| 177 | :py:class:`monai.transforms.SpatialResample` |
| 178 | """ |
| 179 | if not Affine.is_affine_shaped(matrix): |
| 180 | raise NotImplementedError(f"Calling the dense grid resample API directly not implemented, {matrix.shape}.") |
| 181 | if isinstance(data, monai.data.MetaTensor) and data.pending_operations: |
| 182 | warnings.warn("data.pending_operations is not empty, the resampling output may be incorrect.") |
| 183 | kwargs = kwargs or {} |
| 184 | for k in kwargs: |
| 185 | look_up_option(k, __override_lazy_keywords) |
| 186 | atol = kwargs.get("atol", AFFINE_TOL) |
| 187 | mode = kwargs.get(LazyAttr.RESAMPLE_MODE, "auto") |
| 188 | |
| 189 | init_kwargs = { |
| 190 | "dtype": kwargs.get(LazyAttr.DTYPE, data.dtype), |
| 191 | "align_corners": kwargs.get(LazyAttr.ALIGN_CORNERS, False), |
| 192 | } |
| 193 | ndim = len(matrix) - 1 |
| 194 | img = convert_to_tensor(data=data, track_meta=monai.data.get_track_meta()) |
| 195 | init_affine = monai.data.to_affine_nd(ndim, img.affine) |
| 196 | spatial_size = kwargs.get(LazyAttr.SHAPE, None) |
| 197 | out_spatial_size = img.peek_pending_shape() if spatial_size is None else spatial_size |
| 198 | out_spatial_size = convert_to_numpy(out_spatial_size, wrap_sequence=True) |
| 199 | call_kwargs = { |
| 200 | "spatial_size": out_spatial_size, |
| 201 | "dst_affine": init_affine @ monai.utils.convert_to_dst_type(matrix, init_affine)[0], |
| 202 | "mode": kwargs.get(LazyAttr.INTERP_MODE), |
| 203 | "padding_mode": kwargs.get(LazyAttr.PADDING_MODE), |
| 204 | } |
| 205 | |
| 206 | axes = requires_interp(matrix, atol=atol) |
| 207 | if axes is not None and mode == "auto" and not init_kwargs["align_corners"]: |
| 208 | matrix_np = np.round(convert_to_numpy(matrix, wrap_sequence=True)) |
| 209 | full_transpose = np.argsort(axes).tolist() |
| 210 | if not np.allclose(full_transpose, np.arange(len(full_transpose))): |
| 211 | img = img.permute(full_transpose[: len(img.shape)]) |
| 212 | in_shape = img.shape[1 : ndim + 1] # requires that ``img`` has empty pending operations |
| 213 | matrix_np[:ndim] = matrix_np[[x - 1 for x in full_transpose[1:]]] |
| 214 | flip = [idx + 1 for idx, val in enumerate(matrix_np[:ndim]) if val[idx] == -1] |
| 215 | if flip: |
searching dependent graphs…