Apply augmentations. Parameters ---------- images : torch.Tensor Input tensor of shape ``[N, C, H, W]``. params : dict | None, default = None *If given*, the function will **reuse** these tensors instead of sampling fresh randomnes
(self, images: torch.Tensor, *, params: Optional[Dict[str, torch.Tensor]] = None,
return_params: bool = False)
| 193 | # Forward pass with optional deterministic parameters. |
| 194 | # --------------------------------------------------------------------- |
| 195 | def __call__(self, images: torch.Tensor, *, params: Optional[Dict[str, torch.Tensor]] = None, |
| 196 | return_params: bool = False) -> Tuple[torch.Tensor, torch.Tensor, Optional[Dict[str, torch.Tensor]]]: |
| 197 | """Apply augmentations. |
| 198 | |
| 199 | Parameters |
| 200 | ---------- |
| 201 | images : torch.Tensor |
| 202 | Input tensor of shape ``[N, C, H, W]``. |
| 203 | params : dict | None, default = None |
| 204 | *If given*, the function will **reuse** these tensors instead of |
| 205 | sampling fresh randomness. The expected dictionary keys are listed |
| 206 | in the source; passing fewer keys simply disables the missing |
| 207 | augmentations. |
| 208 | return_params : bool, default = False |
| 209 | If ``True``, the function also returns the dictionary that contains |
| 210 | *all* random tensors used during this call (both supplied and |
| 211 | newly‑sampled). This can be cached by the caller and reused later. |
| 212 | |
| 213 | Returns |
| 214 | ------- |
| 215 | images : torch.Tensor |
| 216 | Augmented images with the same shape as the input. |
| 217 | labels : torch.Tensor |
| 218 | Per‑image labels recording the effective augmentation parameters |
| 219 | (identical to the original StyleGAN‑ADA implementation). |
| 220 | params : dict | None |
| 221 | Only returned when ``return_params=True``. |
| 222 | """ |
| 223 | |
| 224 | N, C, H, W = images.shape |
| 225 | device = images.device |
| 226 | |
| 227 | # Internal helper -------------------------------------------------- |
| 228 | rnd: Dict[str, torch.Tensor] = OrderedDict() # we will fill this |
| 229 | |
| 230 | def _get(name: str, tensor_fn, batch_dim: int = 0): |
| 231 | """Retrieve a random tensor by name, sampling if necessary.""" |
| 232 | if params is not None and name in params: |
| 233 | return params[name].transpose(0, batch_dim) |
| 234 | t = tensor_fn() |
| 235 | rnd[name] = t.transpose(0, batch_dim) |
| 236 | return t |
| 237 | |
| 238 | labels: List[torch.Tensor] = [torch.zeros([images.shape[0], 0], device=device)] |
| 239 | |
| 240 | # ------------------------------- |
| 241 | # Pixel blitting : xflip / yflip |
| 242 | # ------------------------------- |
| 243 | if self.xflip > 0: |
| 244 | w = _get('xflip', lambda: torch.randint(2, [N, 1, 1, 1], device=device)) |
| 245 | w = _get('xflip_rand', lambda: torch.where(torch.rand_like(w, dtype=torch.float32) < self.xflip * self.p, w, torch.zeros_like(w))) |
| 246 | images = torch.where(w == 1, images.flip(3), images) |
| 247 | labels += [w] |
| 248 | |
| 249 | if self.yflip > 0: |
| 250 | w = _get('yflip', lambda: torch.randint(2, [N, 1, 1, 1], device=device)) |
| 251 | w = _get('yflip_rand', lambda: torch.where(torch.rand_like(w, dtype=torch.float32) < self.yflip * self.p, w, torch.zeros_like(w))) |
| 252 | images = torch.where(w == 1, images.flip(2), images) |
nothing calls this directly
no test coverage detected