Compute an affine matrix according to the input shape. The transform normalizes the homogeneous image coordinates to the range of `[-1, 1]`. Currently the following source coordinates are supported: - `align_corners=False`, `zero_centered=False`, normalizing from ``[-0.5, d-0.
(
shape,
device: torch.device | str | None = None,
dtype: torch.dtype | None = None,
align_corners: bool = False,
zero_centered: bool = False,
)
| 241 | |
| 242 | |
| 243 | def normalize_transform( |
| 244 | shape, |
| 245 | device: torch.device | str | None = None, |
| 246 | dtype: torch.dtype | None = None, |
| 247 | align_corners: bool = False, |
| 248 | zero_centered: bool = False, |
| 249 | ) -> torch.Tensor: |
| 250 | """ |
| 251 | Compute an affine matrix according to the input shape. |
| 252 | The transform normalizes the homogeneous image coordinates to the |
| 253 | range of `[-1, 1]`. Currently the following source coordinates are supported: |
| 254 | |
| 255 | - `align_corners=False`, `zero_centered=False`, normalizing from ``[-0.5, d-0.5]``. |
| 256 | - `align_corners=True`, `zero_centered=False`, normalizing from ``[0, d-1]``. |
| 257 | - `align_corners=False`, `zero_centered=True`, normalizing from ``[-(d-1)/2, (d-1)/2]``. |
| 258 | - `align_corners=True`, `zero_centered=True`, normalizing from ``[-d/2, d/2]``. |
| 259 | |
| 260 | Args: |
| 261 | shape: input spatial shape, a sequence of integers. |
| 262 | device: device on which the returned affine will be allocated. |
| 263 | dtype: data type of the returned affine |
| 264 | align_corners: if True, consider -1 and 1 to refer to the centers of the |
| 265 | corner pixels rather than the image corners. |
| 266 | See also: https://pytorch.org/docs/stable/nn.functional.html#torch.nn.functional.grid_sample |
| 267 | zero_centered: whether the coordinates are normalized from a zero-centered range, default to `False`. |
| 268 | Setting this flag and `align_corners` will jointly specify the normalization source range. |
| 269 | """ |
| 270 | shape = convert_to_tensor(shape, torch.float64, device=device, wrap_sequence=True, track_meta=False) |
| 271 | norm = shape.clone().detach().to(dtype=torch.float64, device=device) # no in-place change |
| 272 | if align_corners: |
| 273 | norm[norm <= 1.0] = 2.0 |
| 274 | norm = 2.0 / (norm if zero_centered else norm - 1.0) |
| 275 | norm = torch.diag(torch.cat((norm, torch.ones((1,), dtype=torch.float64, device=device)))) |
| 276 | if not zero_centered: # else shift is 0 |
| 277 | norm[:-1, -1] = -1.0 |
| 278 | else: |
| 279 | norm[norm <= 0.0] = 2.0 |
| 280 | norm = 2.0 / (norm - 1.0 if zero_centered else norm) |
| 281 | norm = torch.diag(torch.cat((norm, torch.ones((1,), dtype=torch.float64, device=device)))) |
| 282 | if not zero_centered: |
| 283 | norm[:-1, -1] = 1.0 / shape - 1.0 |
| 284 | norm = norm.unsqueeze(0).to(dtype=dtype) |
| 285 | norm.requires_grad = False |
| 286 | return norm # type: ignore |
| 287 | |
| 288 | |
| 289 | def to_norm_affine( |
searching dependent graphs…