-
Notifications
You must be signed in to change notification settings - Fork 1
/
patch.py
132 lines (100 loc) · 4.65 KB
/
patch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Class for slide patches
from enum import Enum
from PIL import Image
from matplotlib.path import Path
class Patch(object):
class Patch_Vertex(Enum):
TOP_LEFT = 1
TOP_RIGHT = 2
BOTTOM_LEFT = 3
BOTTOM_RIGHT = 4
def __init__(self, img, coords):
"""
Initializer for Patch object
Args:
img (numpy uint8 array): Image contents of our patch
coords: Coordinates of the image as returned by openslide DeepZoomGenerator's
get_tile_coordinates method (i.e., of the format
((x_topLeft, y_topLeft), level, (width, height))).
Returns:
Patch object
"""
self.img = img
self.coords = coords
self.top_left_vertex = coords[0]
top_left_x = self.top_left_vertex[0]
top_left_y = self.top_left_vertex[1]
patch_dimensions = coords[2]
self.width = patch_dimensions[0]
self.height = patch_dimensions[1]
self.top_right_vertex = (top_left_x + self.width, top_left_y)
self.bottom_left_vertex = (top_left_x, top_left_y + self.height)
self.bottom_right_vertex = (top_left_x + self.width, top_left_y + self.height)
def save_img_to_disk(self, outfile_name):
"""
Saves patch object's image contents to disk as a png file with name outfile_name
Args:
outfile_name (String): Name for resulting png file
Returns:
None (saves output to disk)
"""
pil_img = Image.fromarray(self.img)
pil_img.save(outfile_name + '.jpg')
def vertex_in_annotation(self, patch_vertex, annotation):
"""
Checks to see if a specific patch vertex is contained within a provided
annotation
Args:
patch_vertex (Patch_Vertex): Enum representing which vertex of our patch we want to check
annotation: (matplotlib.path.Path object): Path object representing the polygonal region enclosed
by a QuPath annotation
Returns:
in_annotation (bool): Is the given vertex in our polygon?
"""
in_annotation = False
if patch_vertex == Patch_Vertex.TOP_LEFT:
in_annotation = annotation.contains_point(self.top_left_vertex)
elif patch_vertex == Patch_Vertex.TOP_RIGHT:
in_annotation = annotation.contains_point(self.top_right_vertex)
elif patch_vertex == Patch_Vertex.BOTTOM_LEFT:
in_annotation = annotation.contains_point(self.bottom_left_vertex)
elif patch_vertex == Patch_Vertex.BOTTOM_RIGHT:
in_annotation = annotation.contains_point(self.bottom_right_vertex)
else:
raise TypeError("Invalid vertex type provided to vertex_in_annotation")
return in_annotation
def in_annotation(self, annotation):
"""
Checks to see if ALL of the patch's vertices are contained within a given annotation
as given by a path object
Args:
annotation (Path): Path object representing a given annotation
Returns:
in_annotation (Boolean): True if patch contained within annotation
"""
in_annotation = False
if (annotation.contains_point(self.top_left_vertex) and
annotation.contains_point(self.top_right_vertex) and
annotation.contains_point(self.bottom_left_vertex) and
annotation.contains_point(self.bottom_right_vertex)):
in_annotation = True
return in_annotation
def on_annotation_boundary(self, annotation):
"""
Checks to see if ANY of the patch's vertices are contained within a given annotation
as given by a Path object
Args:
annotation (Path): Path object representing a given annotation
Returns:
on_annotation_boundary (Boolean): True if patch lies on annotation boundary
"""
one_vertex_in = (annotation.contains_point(self.top_left_vertex) or
annotation.contains_point(self.top_right_vertex) or
annotation.contains_point(self.bottom_left_vertex) or
annotation.contains_point(self.bottom_right_vertex))
one_vertex_out = (not annotation.contains_point(self.top_left_vertex) or
not annotation.contains_point(self.top_right_vertex) or
not annotation.contains_point(self.bottom_left_vertex) or
not annotation.contains_point(self.bottom_right_vertex))
on_annotation_boundary = one_vertex_in and one_vertex_out
return on_annotation_boundary