Skip to content

Commit

Permalink
Handle empty annotations (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
moerlemans authored Nov 23, 2023
1 parent 4506ae9 commit 7a92749
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
6 changes: 4 additions & 2 deletions dlup/data/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from numpy.typing import NDArray

from dlup import BoundaryMode, SlideImage
from dlup.annotations import WsiAnnotations
from dlup.annotations import Point, Polygon, WsiAnnotations
from dlup.background import is_foreground
from dlup.experimental_backends import ImageBackend # type: ignore
from dlup.tiling import Grid, GridOrder, TilingMode
Expand All @@ -28,6 +28,8 @@

MaskTypes = Union["SlideImage", npt.NDArray[np.int_], "WsiAnnotations"]

_AnnotationsTypes = Point | Polygon

T_co = TypeVar("T_co", covariant=True)
T = TypeVar("T")
_BaseAnnotationTypes = Union[SlideImage, WsiAnnotations]
Expand All @@ -42,7 +44,7 @@ class TileSample(TypedDict):
path: pathlib.Path
region_index: int
labels: dict[str, Any] | None
annotations: Any | None
annotations: Optional[Iterable[_AnnotationsTypes]]


PointType = tuple[float, float]
Expand Down
33 changes: 31 additions & 2 deletions dlup/data/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ class ConvertAnnotationsToMask:

def __init__(self, *, roi_name: str | None, index_map: dict[str, int], default_value: int = 0):
"""
Converts annotations given my `dlup.annotations.Polygon` or `dlup.annotations.Point` to a mask and a dictionary
of points. The mask is initialized with `default_value`, (i.e., background). The values in the mask are
subsequently determined by `index_map`, where each value is written to the mask according to this map, in the
order of the elements in the annotations. This means that if you have overlapping polygons, the last polygon
will overwrite the previous one. The sorting can be handled in the `dlup.annotations.WsiAnnotation` class.
In case there are no annotations present (i.e. the "annotations" key is None) a `ValueError` is
raised.
Parameters
----------
roi_name : str, optional
Expand All @@ -134,10 +143,30 @@ def __init__(self, *, roi_name: str | None, index_map: dict[str, int], default_v
self._default_value = default_value

def __call__(self, sample: TileSample) -> TileSampleWithAnnotationData:
if not sample["annotations"]:
raise ValueError("No annotations found to convert to mask.")
"""
Convert the annotations to a mask.
Parameters
----------
sample : TileSample
The input sample.
Raises
------
ValueError
If no annotations are found.
Returns
-------
TileSampleWithAnnotationData
The input sample with the annotation data added.
"""

_annotations = sample["annotations"]
if _annotations is None:
raise ValueError("No annotations found to convert to mask.")

points, boxes, mask, roi = convert_annotations(
_annotations,
sample["image"].size[::-1],
Expand Down

0 comments on commit 7a92749

Please sign in to comment.