-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
132 lines (114 loc) · 3.89 KB
/
utils.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
import numpy as np
from skimage.exposure import rescale_intensity
from skimage.transform import resize
from PIL import Image
import PIL
def dsc(y_pred, y_true):
y_pred = np.round(y_pred).astype(int)
y_true = np.round(y_true).astype(int)
pred_sum = np.sum(y_pred)
true_sum = np.sum(y_true)
if pred_sum == 0 and true_sum == 0:
return 1
return np.sum(y_pred[y_true == 1]) * 2.0 / (pred_sum + true_sum)
def dsc_per_volume(validation_pred, validation_true, patient_slice_index):
dsc_list = []
num_slices = np.bincount([p[0] for p in patient_slice_index])
index = 0
for p in range(len(num_slices)):
y_pred = np.array(validation_pred[index : index + num_slices[p]])
y_true = np.array(validation_true[index : index + num_slices[p]])
dsc_list.append(dsc(y_pred, y_true))
index += num_slices[p]
return dsc_list
def crop_sample(x):
volume, mask = x
volume[volume < np.max(volume) * 0.1] = 0
z_projection = np.max(np.max(np.max(volume, axis=-1), axis=-1), axis=-1)
z_nonzero = np.nonzero(z_projection)
z_min = np.min(z_nonzero)
z_max = np.max(z_nonzero) + 1
y_projection = np.max(np.max(np.max(volume, axis=0), axis=-1), axis=-1)
y_nonzero = np.nonzero(y_projection)
y_min = np.min(y_nonzero)
y_max = np.max(y_nonzero) + 1
x_projection = np.max(np.max(np.max(volume, axis=0), axis=0), axis=-1)
x_nonzero = np.nonzero(x_projection)
x_min = np.min(x_nonzero)
x_max = np.max(x_nonzero) + 1
return (
volume[z_min:z_max, y_min:y_max, x_min:x_max],
mask[z_min:z_max, y_min:y_max, x_min:x_max],
)
def pad_sample(x):
volume, mask = x
a = volume.shape[1]
b = volume.shape[2]
if a == b:
return volume, mask
diff = (max(a, b) - min(a, b)) / 2.0
if a > b:
padding = ((0, 0), (0, 0), (int(np.floor(diff)), int(np.ceil(diff))))
else:
padding = ((0, 0), (int(np.floor(diff)), int(np.ceil(diff))), (0, 0))
mask = np.pad(mask, padding, mode="constant", constant_values=0)
padding = padding + ((0, 0),)
volume = np.pad(volume, padding, mode="constant", constant_values=0)
return volume, mask
def resize_sample(x, size=256):
volume, mask = x
v_shape = volume.shape
out_shape = (v_shape[0], size, size)
mask = resize(
mask,
output_shape=out_shape,
order=0,
mode="constant",
cval=0,
anti_aliasing=False,
)
out_shape = out_shape + (v_shape[3],)
volume = resize(
volume,
output_shape=out_shape,
order=1,
mode="constant",
cval=0,
anti_aliasing=False,
)
return volume, mask
def normalize_volume(volume):
p10 = np.percentile(volume, 10)
p99 = np.percentile(volume, 99)
volume = rescale_intensity(volume, in_range=(p10, p99))
m = np.mean(volume, axis=(0, 1, 2))
s = np.std(volume, axis=(0, 1, 2))
volume = (volume - m) / s
return volume
def gray2rgb(image):
w, h = image.shape
image += np.abs(np.min(image))
image_max = np.abs(np.max(image))
if image_max > 0:
image /= image_max
ret = np.empty((w, h, 3), dtype=np.uint8)
ret[:, :, 2] = ret[:, :, 1] = ret[:, :, 0] = image * 255
return ret
def outline(image, mask, color):
mask = np.round(mask).astype(bool)
m = np.zeros_like(image)
m[mask] = color
im = PIL.Image.fromarray(image)
m = PIL.Image.fromarray(m)
return np.array(PIL.Image.blend(im, m, alpha=0.3))
def log_images(x, y_true, y_pred, channel=1):
images = []
x_np = x.cpu().numpy()[:, channel]
y_true_np = y_true.cpu().numpy()[:, 0]
y_pred_np = y_pred.cpu().numpy()[:, 0]
for i in range(x_np.shape[0]):
image = gray2rgb(np.squeeze(x_np[i]))
image = outline(image, y_pred_np[i], color=[255, 0, 0])
image = outline(image, y_true_np[i], color=[0, 255, 0])
images.append(image)
return images