Filter out indices of every class of the input label data, return the indices after fattening. It can handle both One-Hot format label and Argmax format label, must provide `num_classes` for Argmax label. For example: ``label = np.array([[[0, 1, 2], [2, 0, 1], [1, 2, 0]]])`` an
(
label: NdarrayOrTensor,
num_classes: int | None = None,
image: NdarrayOrTensor | None = None,
image_threshold: float = 0.0,
max_samples_per_class: int | None = None,
)
| 480 | |
| 481 | |
| 482 | def map_classes_to_indices( |
| 483 | label: NdarrayOrTensor, |
| 484 | num_classes: int | None = None, |
| 485 | image: NdarrayOrTensor | None = None, |
| 486 | image_threshold: float = 0.0, |
| 487 | max_samples_per_class: int | None = None, |
| 488 | ) -> list[NdarrayOrTensor]: |
| 489 | """ |
| 490 | Filter out indices of every class of the input label data, return the indices after fattening. |
| 491 | It can handle both One-Hot format label and Argmax format label, must provide `num_classes` for |
| 492 | Argmax label. |
| 493 | |
| 494 | For example: |
| 495 | ``label = np.array([[[0, 1, 2], [2, 0, 1], [1, 2, 0]]])`` and `num_classes=3`, will return a list |
| 496 | which contains the indices of the 3 classes: |
| 497 | ``[np.array([0, 4, 8]), np.array([1, 5, 6]), np.array([2, 3, 7])]`` |
| 498 | |
| 499 | Args: |
| 500 | label: use the label data to get the indices of every class. |
| 501 | num_classes: number of classes for argmax label, not necessary for One-Hot label. |
| 502 | image: if image is not None, only return the indices of every class that are within the valid |
| 503 | region of the image (``image > image_threshold``). |
| 504 | image_threshold: if enabled `image`, use ``image > image_threshold`` to |
| 505 | determine the valid image content area and select class indices only in this area. |
| 506 | max_samples_per_class: maximum length of indices in each class to reduce memory consumption. |
| 507 | Default is None, no subsampling. |
| 508 | |
| 509 | """ |
| 510 | check_non_lazy_pending_ops(label, name="map_classes_to_indices") |
| 511 | img_flat: NdarrayOrTensor | None = None |
| 512 | if image is not None: |
| 513 | check_non_lazy_pending_ops(image, name="map_classes_to_indices") |
| 514 | img_flat = ravel((image > image_threshold).any(0)) # type: ignore |
| 515 | |
| 516 | # assuming the first dimension is channel |
| 517 | channels = len(label) |
| 518 | |
| 519 | num_classes_: int = channels |
| 520 | if channels == 1: |
| 521 | if num_classes is None: |
| 522 | raise ValueError("channels==1 indicates not using One-Hot format label, must provide ``num_classes``.") |
| 523 | num_classes_ = num_classes |
| 524 | |
| 525 | indices: list[NdarrayOrTensor] = [] |
| 526 | for c in range(num_classes_): |
| 527 | if channels > 1: |
| 528 | label_flat = ravel(convert_data_type(label[c], dtype=bool)[0]) |
| 529 | else: |
| 530 | label_flat = ravel(label == c) |
| 531 | if img_flat is not None: |
| 532 | label_flat = img_flat & label_flat |
| 533 | # no need to save the indices in GPU, otherwise, still need to move to CPU at runtime when crop by indices |
| 534 | output_type = torch.Tensor if isinstance(label, monai.data.MetaTensor) else None |
| 535 | cls_indices: NdarrayOrTensor = convert_data_type( |
| 536 | nonzero(label_flat), output_type=output_type, device=torch.device("cpu") |
| 537 | )[0] |
| 538 | if max_samples_per_class and len(cls_indices) > max_samples_per_class and len(cls_indices) > 1: |
| 539 | sample_id = np.round(np.linspace(0, len(cls_indices) - 1, max_samples_per_class)).astype(int) |
searching dependent graphs…