-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpatch_inference_support.py
132 lines (104 loc) · 5.33 KB
/
patch_inference_support.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
__author__ = "Bibhabasu Mohapatra"
__copyright__ = "Copyright 2023,"
__credits__ = ["Bibhabasu Mohapatra", "OpenSlide: A Vendor-Neutral Software Foundation for Digital Pathology"]
import numpy as np
from skimage.filters import threshold_li
from skimage import color, measure, io, transform
import cv2
import openslide
class ImageReader:
def __init__(self, image_path : str, tile_size : int, padding : int = None):
self.reader = openslide.open_slide(image_path)
self.max_mag = int(self.reader.properties['aperio.AppMag'])
self.tile_size = tile_size
self.padding = padding
if self.max_mag == 40:
self.level_10 = 1
self.level_2_5 = 2
self.level_shift = 16
elif self.max_mag == 20:
self.level_10 = 0
self.level_2_5 = 1
self.level_shift = 8
def pad(self, mask , left : int, right : int, top : int, bottom : int):
mask = np.pad(
mask,
((top, bottom), (left, right)),
mode="constant",
constant_values=0,
)
return mask
def get_mask(self, magnification : int ):
if self.max_mag == 20:
wsi_2_5x = self.reader.read_region((0,0),self.level_2_5,self.reader.level_dimensions[self.level_2_5])
shape_2_5 = wsi_2_5x.shape
wsi_2_5x = wsi_2_5x.resize(shape_2_5[0]//2,shape_2_5[1]//2)
else:
wsi_2_5x = self.reader.read_region((0,0),self.level_2_5,self.reader.level_dimensions[self.level_2_5])
wsi_2_5x = np.asarray(wsi_2_5x)
mask_g = wsi_2_5x[:,:,1] < threshold_li(wsi_2_5x[:,:,1]).astype(np.uint8)
mask = mask_g.astype(np.uint8)*255
#closing
kernel = np.ones((5,5),np.uint8)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel,iterations=15)
## opening
kernel = np.ones((3,3),np.uint8)
mask = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel,iterations=75)
infer_tile_list = []
scaling = (magnification/2.5)
steps = int(self.tile_size/scaling)
## padding
org_shape = mask.shape
H, W = org_shape
extra_bottom = int(np.ceil(H/steps)*steps - H)
extra_right = int(np.ceil(W/steps)*steps - W)
mask = self.pad(mask, 0, extra_right, 0, extra_bottom)
# update H,W
H,W = mask.shape
for height in range(0,H,steps):
for width in range(0, W,steps):
if np.sum(mask[height:height+steps, width:width+steps]) > 0:
infer_tile_list.append([int(height*scaling),int(width*scaling),])
return {
"img":wsi_2_5x,
"mask": mask,
"list_indices":infer_tile_list,
"shape": mask.shape,
"step_size": steps,
"scaling":scaling,
}
def get_tiles(self, y:int, x:int):
if self.max_mag==20:
if self.padding is not None:
Tile_array = self.reader.read_region(((x - self.padding)*self.level_shift,(y - self.padding)*self.level_shift),self.level_10,((self.tile_size + self.padding)*2,(self.tile_size + self.padding)*2)) ## (1024)
Tile_array = Tile_array.resize((self.tile_size + self.padding),(self.tile_size + self.padding))
Tile_array = np.asarray(Tile_array)
else:
Tile_array = self.reader.read_region((x*self.level_shift,y*self.level_shift),self.level_10,(self.tile_size*2,self.tile_size*2))
Tile_array = Tile_array.resize((self.tile_size,self.tile_size))
Tile_array = np.asarray(Tile_array)
if self.max_mag==40:
if self.padding is not None:
Tile_array = self.reader.read_region(((x - self.padding)*self.level_shift,(y - self.padding)*self.level_shift),self.level_10,(self.tile_size + self.padding,self.tile_size + self.padding)) ## (1024)
Tile_array = np.asarray(Tile_array)
else:
Tile_array = self.reader.read_region((x*self.level_shift,y*self.level_shift),self.level_10,(self.tile_size,self.tile_size))
Tile_array = np.asarray(Tile_array)
Tile_array = Tile_array[:, :, :3]
return Tile_array
def get_stitiched(self,image_list, coords_list, mask_shape, step_size, scaling):
empty_mask = np.zeros(mask_shape)
for indx,coords in enumerate(coords_list):
if self.padding is not None:
image_cropped = image_list[indx][self.padding:self.padding+self.tile_size, self.padding:self.padding+self.tile_size]
patch = transform.resize(image=image_cropped,output_shape=(step_size,step_size),
order=0,
preserve_range=True,
mode="constant")
else:
patch = transform.resize(image=image_list[indx],output_shape=(step_size,step_size),
order=0,
preserve_range=True,
mode="constant")
empty_mask[int(coords[0]/scaling):int(coords[0]/scaling) + step_size,int(coords[1]/scaling):int(coords[1]/scaling) + step_size] = patch
return empty_mask