Extract the patches (sweeping the entire image in a row-major sliding-window manner with possible overlaps). Args: array: a input image as `numpy.ndarray` or `torch.Tensor` Return: MetaTensor: the extracted patches as a single tensor (with patch dim
(self, array: NdarrayOrTensor)
| 3363 | return image_np, locations |
| 3364 | |
| 3365 | def __call__(self, array: NdarrayOrTensor) -> MetaTensor: |
| 3366 | """ |
| 3367 | Extract the patches (sweeping the entire image in a row-major sliding-window manner with possible overlaps). |
| 3368 | |
| 3369 | Args: |
| 3370 | array: a input image as `numpy.ndarray` or `torch.Tensor` |
| 3371 | |
| 3372 | Return: |
| 3373 | MetaTensor: the extracted patches as a single tensor (with patch dimension as the first dimension), |
| 3374 | with defined `PatchKeys.LOCATION` and `PatchKeys.COUNT` metadata. |
| 3375 | """ |
| 3376 | # create the patch iterator which sweeps the image row-by-row |
| 3377 | patch_iterator = iter_patch( |
| 3378 | array, |
| 3379 | patch_size=(None,) + self.patch_size, # expand to have the channel dim |
| 3380 | start_pos=(0,) + self.offset, # expand to have the channel dim |
| 3381 | overlap=self.overlap, |
| 3382 | copy_back=False, |
| 3383 | mode=self.pad_mode, |
| 3384 | **self.pad_kwargs, |
| 3385 | ) |
| 3386 | patches = list(zip(*patch_iterator)) |
| 3387 | patched_image: NdarrayOrTensor |
| 3388 | patched_image = np.stack(patches[0]) if isinstance(array, np.ndarray) else torch.stack(patches[0]) |
| 3389 | locations = np.stack(patches[1])[:, 1:, 0] # only keep the starting location |
| 3390 | |
| 3391 | # Apply threshold filtering |
| 3392 | if self.threshold is not None: |
| 3393 | patched_image, locations = self.filter_threshold(patched_image, locations) |
| 3394 | |
| 3395 | # Apply count filtering |
| 3396 | if self.num_patches: |
| 3397 | # Limit number of patches |
| 3398 | patched_image, locations = self.filter_count(patched_image, locations) |
| 3399 | # Pad the patch list to have the requested number of patches |
| 3400 | if self.threshold is None: |
| 3401 | padding = self.num_patches - len(patched_image) |
| 3402 | if padding > 0: |
| 3403 | # pad constant patches to the end of the first dim |
| 3404 | constant_values = self.pad_kwargs.get("constant_values", 0) |
| 3405 | padding_shape = (padding, *list(patched_image.shape)[1:]) |
| 3406 | constant_padding: NdarrayOrTensor |
| 3407 | if isinstance(patched_image, np.ndarray): |
| 3408 | constant_padding = np.full(padding_shape, constant_values, dtype=patched_image.dtype) |
| 3409 | patched_image = np.concatenate([patched_image, constant_padding], axis=0) |
| 3410 | else: |
| 3411 | constant_padding = torch.full( |
| 3412 | padding_shape, |
| 3413 | constant_values, |
| 3414 | dtype=patched_image.dtype, |
| 3415 | layout=patched_image.layout, |
| 3416 | device=patched_image.device, |
| 3417 | ) |
| 3418 | patched_image = torch.cat([patched_image, constant_padding], dim=0) |
| 3419 | locations = np.pad(locations, [[0, padding], [0, 0]], constant_values=0) |
| 3420 | |
| 3421 | # Convert to MetaTensor |
| 3422 | metadata = array.meta if isinstance(array, MetaTensor) else MetaTensor.get_default_meta() |
nothing calls this directly
no test coverage detected