r""" This transform fills holes in the image and can be used to remove artifacts inside segments. An enclosed hole is defined as a background pixel/voxel which is only enclosed by a single class. The definition of enclosed can be defined with the connectivity parameter:: 1-conn
| 509 | |
| 510 | |
| 511 | class FillHoles(Transform): |
| 512 | r""" |
| 513 | This transform fills holes in the image and can be used to remove artifacts inside segments. |
| 514 | |
| 515 | An enclosed hole is defined as a background pixel/voxel which is only enclosed by a single class. |
| 516 | The definition of enclosed can be defined with the connectivity parameter:: |
| 517 | |
| 518 | 1-connectivity 2-connectivity diagonal connection close-up |
| 519 | |
| 520 | [ ] [ ] [ ] [ ] [ ] |
| 521 | | \ | / | <- hop 2 |
| 522 | [ ]--[x]--[ ] [ ]--[x]--[ ] [x]--[ ] |
| 523 | | / | \ hop 1 |
| 524 | [ ] [ ] [ ] [ ] |
| 525 | |
| 526 | It is possible to define for which labels the hole filling should be applied. |
| 527 | The input image is assumed to be a PyTorch Tensor or numpy array with shape [C, spatial_dim1[, spatial_dim2, ...]]. |
| 528 | If C = 1, then the values correspond to expected labels. |
| 529 | If C > 1, then a one-hot-encoding is expected where the index of C matches the label indexing. |
| 530 | |
| 531 | Note: |
| 532 | |
| 533 | The label 0 will be treated as background and the enclosed holes will be set to the neighboring class label. |
| 534 | |
| 535 | The performance of this method heavily depends on the number of labels. |
| 536 | It is a bit faster if the list of `applied_labels` is provided. |
| 537 | Limiting the number of `applied_labels` results in a big decrease in processing time. |
| 538 | |
| 539 | For example: |
| 540 | |
| 541 | Use FillHoles with default parameters:: |
| 542 | |
| 543 | [1, 1, 1, 2, 2, 2, 3, 3] [1, 1, 1, 2, 2, 2, 3, 3] |
| 544 | [1, 0, 1, 2, 0, 0, 3, 0] => [1, 1 ,1, 2, 0, 0, 3, 0] |
| 545 | [1, 1, 1, 2, 2, 2, 3, 3] [1, 1, 1, 2, 2, 2, 3, 3] |
| 546 | |
| 547 | The hole in label 1 is fully enclosed and therefore filled with label 1. |
| 548 | The background label near label 2 and 3 is not fully enclosed and therefore not filled. |
| 549 | """ |
| 550 | |
| 551 | backend = [TransformBackends.NUMPY] |
| 552 | |
| 553 | def __init__(self, applied_labels: Iterable[int] | int | None = None, connectivity: int | None = None) -> None: |
| 554 | """ |
| 555 | Initialize the connectivity and limit the labels for which holes are filled. |
| 556 | |
| 557 | Args: |
| 558 | applied_labels: Labels for which to fill holes. Defaults to None, that is filling holes for all labels. |
| 559 | connectivity: Maximum number of orthogonal hops to consider a pixel/voxel as a neighbor. |
| 560 | Accepted values are ranging from 1 to input.ndim. Defaults to a full connectivity of ``input.ndim``. |
| 561 | """ |
| 562 | super().__init__() |
| 563 | self.applied_labels = ensure_tuple(applied_labels) if applied_labels else None |
| 564 | self.connectivity = connectivity |
| 565 | |
| 566 | def __call__(self, img: NdarrayOrTensor) -> NdarrayOrTensor: |
| 567 | """ |
| 568 | Fill the holes in the provided image. |
no outgoing calls
searching dependent graphs…