Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Fix Rendering Annotations with Holes #813

Merged
merged 3 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions tests/test_annotation_tilerendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
def cell_grid() -> list[Polygon]:
"""Generate a grid of fake cell boundary polygon annotations."""
return [
cell_polygon(((i + 0.5) * 100, (j + 0.5) * 100)) for i, j in np.ndindex(5, 5)
cell_polygon(((i + 0.5) * 100, (j + 0.5) * 100), radius=13)
for i, j in np.ndindex(5, 5)
]


Expand Down Expand Up @@ -168,7 +169,7 @@ def test_filter_by_expression(fill_store: Callable, tmp_path: Path) -> None:
tg = AnnotationTileGenerator(wsi.info, store, renderer, tile_size=256)
thumb = tg.get_thumb_tile()
_, num = label(np.array(thumb)[:, :, 1])
assert num == 25 # expect 25 cell objects, as the added one is too small
assert num == 25 # expect 25 cell objects


def test_zoomed_out_rendering(fill_store: Callable, tmp_path: Path) -> None:
Expand All @@ -190,7 +191,7 @@ def test_zoomed_out_rendering(fill_store: Callable, tmp_path: Path) -> None:

thumb = tg.get_tile(1, 0, 0)
_, num = label(np.array(thumb)[:, :, 1]) # default color is green
assert num == 25 # expect 25 cells in top left quadrant
assert num == 25 # expect 25 cells in top left quadrant (added one too small)


def test_decimation(fill_store: Callable, tmp_path: Path) -> None:
Expand Down Expand Up @@ -434,7 +435,7 @@ def test_unfilled_polys(fill_store: Callable, tmp_path: Path) -> None:
renderer = AnnotationRenderer(thickness=1)
tg = AnnotationTileGenerator(wsi.info, store, renderer, tile_size=256)
tile_outline = np.array(tg.get_tile(1, 0, 0))
tg.renderer.edge_thickness = -1
tg.renderer.thickness = -1
tile_filled = np.array(tg.get_tile(1, 0, 0))
# expect sum of filled polys to be much greater than sum of outlines
assert np.sum(tile_filled) > 2 * np.sum(tile_outline)
Expand Down
43 changes: 26 additions & 17 deletions tiatoolbox/utils/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,10 @@ def to_tile_coords(
Array of coordinates in tile space in the form [x, y].

"""
return ((np.reshape(coords, (-1, 2)) - top_left) / scale).astype(np.int32)
return [
((np.reshape(ring, (-1, 2)) - top_left) / scale).astype(np.int32)
for ring in coords
]

def get_color(
self: AnnotationRenderer,
Expand Down Expand Up @@ -756,19 +759,26 @@ def render_poly(
scale,
)
if self.thickness > -1:
cv2.drawContours(
cv2.polylines(
tile,
[cnt],
0,
col,
self.edge_thickness,
cnt,
isClosed=True,
color=col,
thickness=self.edge_thickness,
lineType=cv2.LINE_8,
)
else:
cv2.drawContours(tile, [cnt], 0, col, self.thickness, lineType=cv2.LINE_8)
cv2.fillPoly(tile, cnt, col)
if self.thickness == -1 and self.edge_thickness > 0:
edge_col = self.get_color(annotation, edge=True)
cv2.drawContours(tile, [cnt], 0, edge_col, 1, lineType=cv2.LINE_8)
cv2.polylines(
tile,
cnt,
isClosed=True,
color=edge_col,
thickness=1,
lineType=cv2.LINE_8,
)

def render_multipoly(
self: AnnotationRenderer,
Expand All @@ -782,7 +792,7 @@ def render_multipoly(
geoms = annotation.coords
for poly in geoms:
cnt = self.to_tile_coords(poly, top_left, scale)
cv2.drawContours(tile, [cnt], 0, col, self.thickness, lineType=cv2.LINE_8)
cv2.fillPoly(tile, cnt, col)

def render_pt(
self: AnnotationRenderer,
Expand Down Expand Up @@ -811,7 +821,7 @@ def render_pt(
annotation.coords,
top_left,
scale,
)[0],
)[0][0],
np.maximum(self.edge_thickness, 1),
col,
thickness=self.thickness,
Expand All @@ -838,15 +848,14 @@ def render_line(

"""
col = self.get_color(annotation, edge=False)
cnt = self.to_tile_coords(
list(annotation.coords),
top_left,
scale,
)
cv2.polylines(
tile,
[
self.to_tile_coords(
list(annotation.coords),
top_left,
scale,
),
],
[np.array(cnt)],
isClosed=False,
color=col,
thickness=3,
Expand Down
Loading