|
a |
|
b/Utilities/show_segmentations.py |
|
|
1 |
import os |
|
|
2 |
import nibabel as nib |
|
|
3 |
import numpy as np |
|
|
4 |
from overlay_ims import overlay_image, save_overlay_im |
|
|
5 |
from PIL import Image |
|
|
6 |
|
|
|
7 |
|
|
|
8 |
def make_montage(sname_ims, sname_mont='montage.png', crop=None): |
|
|
9 |
""" |
|
|
10 |
Make images |
|
|
11 |
Args: |
|
|
12 |
sname_ims (list): list of image names |
|
|
13 |
sname_mont (str): name of output file |
|
|
14 |
crop (None or list of length 4): Crop coordinates (x, y, x_width, y_width) |
|
|
15 |
|
|
|
16 |
Returns: |
|
|
17 |
|
|
|
18 |
""" |
|
|
19 |
|
|
|
20 |
rows = len(sname_ims) |
|
|
21 |
y = 0 |
|
|
22 |
for i in range(rows): |
|
|
23 |
x = 0 |
|
|
24 |
# Load first row of images |
|
|
25 |
im = Image.open(sname_ims[i]) |
|
|
26 |
msk = Image.open(sname_msks[i]) |
|
|
27 |
seg = Image.open(sname_segs[i]) |
|
|
28 |
diff = Image.open(sname_diffs[i]) |
|
|
29 |
|
|
|
30 |
# Apply crops |
|
|
31 |
if crop: |
|
|
32 |
bbox = (crop[0], crop[1], im.width + crop[2], im.height + crop[3]) |
|
|
33 |
im = im.crop(bbox) |
|
|
34 |
msk = msk.crop(bbox) |
|
|
35 |
seg = seg.crop(bbox) |
|
|
36 |
diff = diff.crop(bbox) |
|
|
37 |
print(im.height) |
|
|
38 |
|
|
|
39 |
if i == 0: |
|
|
40 |
mont = Image.new('RGB', size=(im.width * 4, im.height * rows)) |
|
|
41 |
|
|
|
42 |
mont.paste(im, (x, y)) |
|
|
43 |
x += im.width |
|
|
44 |
mont.paste(msk, (x, y)) |
|
|
45 |
x += im.width |
|
|
46 |
mont.paste(seg, (x, y)) |
|
|
47 |
x += im.width |
|
|
48 |
mont.paste(diff, (x, y)) |
|
|
49 |
|
|
|
50 |
# Increment row |
|
|
51 |
y += im.height |
|
|
52 |
|
|
|
53 |
# Save montage image |
|
|
54 |
sname_mont = os.path.join(save_path, sname_mont) |
|
|
55 |
mont.save(sname_mont) |
|
|
56 |
|
|
|
57 |
|
|
|
58 |
def make_montage_init(sname_ims, sname_mont='montage.png'): |
|
|
59 |
""" |
|
|
60 |
Make a montage with one row |
|
|
61 |
Args: |
|
|
62 |
sname_ims (str): montage save name |
|
|
63 |
sname_mont (list): lits of image files |
|
|
64 |
|
|
|
65 |
Returns: |
|
|
66 |
|
|
|
67 |
""" |
|
|
68 |
# Make montage |
|
|
69 |
cols = len(sname_ims) |
|
|
70 |
x = 0 |
|
|
71 |
y = 0 |
|
|
72 |
for i in range(cols): |
|
|
73 |
# Load first row of images |
|
|
74 |
im = Image.open(sname_ims[i]) |
|
|
75 |
|
|
|
76 |
if i == 0: |
|
|
77 |
mont = Image.new('RGB', size=(im.width * cols, im.height)) |
|
|
78 |
|
|
|
79 |
mont.paste(im, (x, y)) |
|
|
80 |
x += im.width |
|
|
81 |
|
|
|
82 |
# Save montage image |
|
|
83 |
sname_mont = os.path.join(save_path, sname_mont) |
|
|
84 |
mont.save(sname_mont) |
|
|
85 |
|
|
|
86 |
|
|
|
87 |
def load_label_show(files, sz): |
|
|
88 |
""" |
|
|
89 |
Load and prep label file |
|
|
90 |
Args: |
|
|
91 |
files (str): label filename |
|
|
92 |
sz (list of length 2): size of MR image (may not always match label) |
|
|
93 |
|
|
|
94 |
Returns: |
|
|
95 |
|
|
|
96 |
""" |
|
|
97 |
from skimage.transform import resize |
|
|
98 |
from scipy.ndimage.morphology import binary_closing |
|
|
99 |
|
|
|
100 |
# Load image |
|
|
101 |
label = nib.load(files).get_data().astype('float32').squeeze() |
|
|
102 |
|
|
|
103 |
# Resize image |
|
|
104 |
label /= label.max() |
|
|
105 |
label = resize(label, (sz[0], sz[1])) |
|
|
106 |
|
|
|
107 |
# Make binary |
|
|
108 |
label[label < 0.5] = 0 |
|
|
109 |
label[label > 0.5] = 1 |
|
|
110 |
|
|
|
111 |
# Close the mask |
|
|
112 |
# label = binary_closing(label, structure=np.ones(shape=(3, 3, 3))) |
|
|
113 |
|
|
|
114 |
return 255 * label.astype(np.uint8) |
|
|
115 |
|
|
|
116 |
|
|
|
117 |
""" |
|
|
118 |
Goal: remake segmentation images to show a control and a PD1 animal before and after segmentation. |
|
|
119 |
""" |
|
|
120 |
|
|
|
121 |
# Set up save paths |
|
|
122 |
save_path = '/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/Analysis/Segmentation_images' |
|
|
123 |
|
|
|
124 |
snames = [ |
|
|
125 |
['control_1', |
|
|
126 |
'control_2'], |
|
|
127 |
['pd1_1', |
|
|
128 |
'pd1_2'] |
|
|
129 |
] |
|
|
130 |
|
|
|
131 |
# Data paths |
|
|
132 |
image_files = [ |
|
|
133 |
['/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520552/20180510/T2_cor.nii.gz', |
|
|
134 |
'/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520552/20180517/T2_cor.nii.gz'], # Control |
|
|
135 |
['/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180503/T2_cor.nii.gz', |
|
|
136 |
'/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180510/T2_cor.nii.gz'] |
|
|
137 |
] |
|
|
138 |
|
|
|
139 |
seg_files = [ |
|
|
140 |
['/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520552/20180510/tumor_seg.nii.gz', |
|
|
141 |
'/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520552/20180517/tumor_seg.nii.gz'], |
|
|
142 |
['/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180503/tumor_seg.nii.gz', |
|
|
143 |
'/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180510/tumor_seg.nii.gz'] |
|
|
144 |
] |
|
|
145 |
|
|
|
146 |
mask_files = [ |
|
|
147 |
['/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/520552/Seg_520552-1-label.nii', |
|
|
148 |
'/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/520552/Seg_520552-2-label.nii'], |
|
|
149 |
['/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/520457/Seg_520457-1-label.nii', |
|
|
150 |
'/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/520457/Seg_520457-2-label.nii'] |
|
|
151 |
] |
|
|
152 |
|
|
|
153 |
slices = [[27, 19], |
|
|
154 |
[27, 19] |
|
|
155 |
] |
|
|
156 |
|
|
|
157 |
# Change paths if in windows |
|
|
158 |
if 'nt' in os.name: |
|
|
159 |
save_path = save_path.replace('/media/matt/Seagate Expansion Drive/', 'E://') |
|
|
160 |
|
|
|
161 |
for i in range(len(image_files)): |
|
|
162 |
image_files[i] = [i.replace('/media/matt/Seagate Expansion Drive/', 'E://') for i in image_files[i]] |
|
|
163 |
seg_files[i] = [i.replace('/media/matt/Seagate Expansion Drive/', 'E://') for i in seg_files[i]] |
|
|
164 |
mask_files[i] = [i.replace('/media/matt/Seagate Expansion Drive/', 'E://') for i in mask_files[i]] |
|
|
165 |
|
|
|
166 |
if not os.path.exists(save_path): |
|
|
167 |
os.mkdir(save_path) |
|
|
168 |
|
|
|
169 |
# Colormap |
|
|
170 |
colormap_mask = ['black', 'red'] |
|
|
171 |
colormap_seg = ['black', 'green'] |
|
|
172 |
colormap_comb = ['black', 'red', 'green'] |
|
|
173 |
|
|
|
174 |
# Histogram clipping |
|
|
175 |
top_pct = 0.05 / 100 |
|
|
176 |
bot_pct = 15 / 100 |
|
|
177 |
|
|
|
178 |
sname_ims, sname_msks, sname_segs, sname_diffs = [], [], [], [] |
|
|
179 |
for i in range(len(image_files)): |
|
|
180 |
|
|
|
181 |
for ii in range(len(image_files[i])): |
|
|
182 |
# Read image |
|
|
183 |
im = nib.load(image_files[i][ii]).get_data().astype(np.float) |
|
|
184 |
msk = nib.load(mask_files[i][ii]).get_data().astype(np.float) |
|
|
185 |
seg = nib.load(seg_files[i][ii]).get_data().astype(np.float) |
|
|
186 |
|
|
|
187 |
# Scale the image |
|
|
188 |
im_s = sorted(im.reshape(-1)) |
|
|
189 |
top_thresh = im_s[-round(len(im_s) * top_pct)] |
|
|
190 |
bot_thresh = im_s[round(len(im_s) * bot_pct)] |
|
|
191 |
im[im > top_thresh] = top_thresh |
|
|
192 |
im[im < bot_thresh] = bot_thresh |
|
|
193 |
|
|
|
194 |
# Select slice |
|
|
195 |
s = slices[i][ii] |
|
|
196 |
im = im[:, :, s].T |
|
|
197 |
msk = msk[:, :, s].T |
|
|
198 |
seg = seg[:, :, s].T |
|
|
199 |
|
|
|
200 |
# Normalize |
|
|
201 |
|
|
|
202 |
# Set up save name |
|
|
203 |
save_name = os.path.join(save_path, snames[i][ii]) |
|
|
204 |
|
|
|
205 |
# Create overlay image - no masks |
|
|
206 |
sname_im = save_name + 'im.png' |
|
|
207 |
over_im = overlay_image(base_image=im, |
|
|
208 |
overlay_image=np.zeros_like(msk), |
|
|
209 |
colormap=colormap_mask, |
|
|
210 |
sname=sname_im |
|
|
211 |
) |
|
|
212 |
|
|
|
213 |
# Create overlay image - mask |
|
|
214 |
sname_msk = save_name + 'msk.png' |
|
|
215 |
over_im = overlay_image(base_image=im, |
|
|
216 |
overlay_image=msk, |
|
|
217 |
colormap=colormap_mask, |
|
|
218 |
sname=sname_msk |
|
|
219 |
) |
|
|
220 |
|
|
|
221 |
# Create overlay image - segmentation |
|
|
222 |
sname_seg = save_name + 'seg.png' |
|
|
223 |
over_im = overlay_image(base_image=im, |
|
|
224 |
overlay_image=seg, |
|
|
225 |
colormap=colormap_seg, |
|
|
226 |
sname=sname_seg |
|
|
227 |
) |
|
|
228 |
|
|
|
229 |
# Create overlay image - combined |
|
|
230 |
# Green = false positive, 1.0 |
|
|
231 |
# Red = false negative, 0.5 |
|
|
232 |
|
|
|
233 |
# False positives |
|
|
234 |
fp = seg - msk |
|
|
235 |
fp[fp < 0] = 0 |
|
|
236 |
|
|
|
237 |
# False negatives |
|
|
238 |
fn = msk - seg |
|
|
239 |
fn[fn < 0] = 0 |
|
|
240 |
|
|
|
241 |
# Combined |
|
|
242 |
comb = fp + 0.5 * fn |
|
|
243 |
|
|
|
244 |
sname_diff = save_name + 'diff.png' |
|
|
245 |
over_im = overlay_image(base_image=im, |
|
|
246 |
overlay_image=comb, |
|
|
247 |
colormap=colormap_comb, |
|
|
248 |
sname=sname_diff |
|
|
249 |
) |
|
|
250 |
|
|
|
251 |
sname_ims.append(sname_im) |
|
|
252 |
sname_msks.append(sname_msk) |
|
|
253 |
sname_segs.append(sname_seg) |
|
|
254 |
sname_diffs.append(sname_diff) |
|
|
255 |
|
|
|
256 |
make_montage(sname_ims, crop=(35, 10, -35, -70)) |
|
|
257 |
|
|
|
258 |
""" Initial images """ |
|
|
259 |
# Show modal images and segmentation |
|
|
260 |
files = ['/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/3/180420-3b-2_T1.nii', |
|
|
261 |
'/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/3/180420-3b-2_T1wC.nii', |
|
|
262 |
'/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/3/180420-3B-2_T2.nii'] |
|
|
263 |
ims = [] |
|
|
264 |
seg_file = '/media/matt/Seagate Expansion Drive/MR Data/MR_Images_Sarcoma/3/180420-3B-2-label.nii' |
|
|
265 |
snames = ['T1', 'T1C', 'T2', 'seg'] |
|
|
266 |
snames = [os.path.join(save_path, i + '_2.png') for i in snames] |
|
|
267 |
slice = 33 |
|
|
268 |
|
|
|
269 |
# Change paths if in windows |
|
|
270 |
if 'nt' in os.name: |
|
|
271 |
seg_file = seg_file.replace('/media/matt/Seagate Expansion Drive/', 'E://') |
|
|
272 |
files = [i.replace('/media/matt/Seagate Expansion Drive/', 'E://') for i in files] |
|
|
273 |
|
|
|
274 |
for file, sname in zip(files, snames[:-1]): |
|
|
275 |
# Load the file and select slice |
|
|
276 |
im = nib.load(file).get_data().astype(np.float) |
|
|
277 |
im = im[:, :, slice].T |
|
|
278 |
|
|
|
279 |
# Remove outliers |
|
|
280 |
im_s = sorted(im.reshape(-1)) |
|
|
281 |
top_thresh = im_s[-round(len(im_s) * top_pct)] |
|
|
282 |
bot_thresh = im_s[round(len(im_s) * bot_pct)] |
|
|
283 |
im[im > top_thresh] = top_thresh |
|
|
284 |
im[im < bot_thresh] = bot_thresh |
|
|
285 |
|
|
|
286 |
# Convert to 8 bit |
|
|
287 |
im -= im.min() |
|
|
288 |
im /= im.max() |
|
|
289 |
im *= 255 |
|
|
290 |
im = im.astype(np.uint8) |
|
|
291 |
|
|
|
292 |
# Save image |
|
|
293 |
save_overlay_im(im, sname) |
|
|
294 |
|
|
|
295 |
# Save the segmenation image |
|
|
296 |
seg = nib.load(seg_file).get_data().astype(np.uint8) |
|
|
297 |
seg = seg[:, :, slice].T |
|
|
298 |
seg -= seg.min() |
|
|
299 |
seg = seg / seg.max() |
|
|
300 |
seg *= 255 |
|
|
301 |
seg = seg.astype(np.uint8) |
|
|
302 |
|
|
|
303 |
# Apply colormap |
|
|
304 |
seg = np.repeat(seg[:, :, np.newaxis], 3, 2) |
|
|
305 |
seg[:, :, 1:] = 0 |
|
|
306 |
|
|
|
307 |
# Save |
|
|
308 |
save_overlay_im(seg, snames[-1]) |
|
|
309 |
|
|
|
310 |
# Save montage |
|
|
311 |
make_montage_init(snames, sname_mont='mont_init1.png') |
|
|
312 |
|
|
|
313 |
# Save second sample images |
|
|
314 |
files = ['/media/matt/Seagate Expansion Drive/MR Data/SarcomaSegmentations/Mouse IV/Mouse IV T1 FLASH.nii', |
|
|
315 |
'/media/matt/Seagate Expansion Drive/MR Data/SarcomaSegmentations/Mouse IV/Mouse IV T1FLASH with Contrast.nii', |
|
|
316 |
'/media/matt/Seagate Expansion Drive/MR Data/SarcomaSegmentations/Mouse IV/Bias Corrected Images/Mouse IV T2TurboRARE New Bias Correction.nii'] |
|
|
317 |
seg_file = '/media/matt/Seagate Expansion Drive/MR Data/SarcomaSegmentations/Mouse IV/Mouse IV ROI Black and White Volume.nii' |
|
|
318 |
snames = ['T1', 'T1C', 'T2', 'seg'] |
|
|
319 |
snames = [os.path.join(save_path, i + '.png') for i in snames] |
|
|
320 |
slice = 25 |
|
|
321 |
|
|
|
322 |
# Change paths if in windows |
|
|
323 |
if 'nt' in os.name: |
|
|
324 |
seg_file = seg_file.replace('/media/matt/Seagate Expansion Drive/', 'E://') |
|
|
325 |
files = [i.replace('/media/matt/Seagate Expansion Drive/', 'E://') for i in files] |
|
|
326 |
|
|
|
327 |
for file, sname in zip(files, snames[:-1]): |
|
|
328 |
# Load the file and select slice |
|
|
329 |
im = nib.load(file).get_data().astype(np.float) |
|
|
330 |
sz = im.shape |
|
|
331 |
im = im[:, :, slice].T |
|
|
332 |
|
|
|
333 |
# Remove outliers |
|
|
334 |
im_s = sorted(im.reshape(-1)) |
|
|
335 |
top_thresh = im_s[-round(len(im_s) * top_pct)] |
|
|
336 |
bot_thresh = im_s[round(len(im_s) * bot_pct)] |
|
|
337 |
im[im > top_thresh] = top_thresh |
|
|
338 |
im[im < bot_thresh] = bot_thresh |
|
|
339 |
|
|
|
340 |
# Convert to 8 bit |
|
|
341 |
im -= im.min() |
|
|
342 |
im /= im.max() |
|
|
343 |
im *= 255 |
|
|
344 |
im = im.astype(np.uint8) |
|
|
345 |
|
|
|
346 |
# Save image |
|
|
347 |
save_overlay_im(im, sname) |
|
|
348 |
|
|
|
349 |
# Save the segmenation image |
|
|
350 |
seg = load_label_show(seg_file, sz) |
|
|
351 |
seg = seg[:, :, slice].T |
|
|
352 |
|
|
|
353 |
# Apply colormap |
|
|
354 |
seg = np.repeat(seg[:, :, np.newaxis], 3, 2) |
|
|
355 |
seg[:, :, 1:] = 0 |
|
|
356 |
|
|
|
357 |
# Save |
|
|
358 |
save_overlay_im(seg, snames[-1]) |
|
|
359 |
|
|
|
360 |
# Save montage |
|
|
361 |
make_montage_init(snames, sname_mont='mont_init2.png') |
|
|
362 |
|
|
|
363 |
""" Show tumor, edge, and bed segmentations """ |
|
|
364 |
from Radiomics.radiomic_maps_190501 import dilate_masks |
|
|
365 |
|
|
|
366 |
mask_tumor = '/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180510/tumor_seg.nii.gz' |
|
|
367 |
image_name = '/media/matt/Seagate Expansion Drive/b7TData_19/b7TData/Results/K520457/20180510/T2_cor.nii.gz' |
|
|
368 |
snames = ['area_tumor.png', 'area_edge.png', 'area_bed.png'] |
|
|
369 |
snames = [os.path.join(save_path, i) for i in snames] |
|
|
370 |
descriptor = 'area' |
|
|
371 |
slices = [29] |
|
|
372 |
|
|
|
373 |
top_pct = 1 / 100 |
|
|
374 |
bot_pct = 15 / 100 |
|
|
375 |
|
|
|
376 |
# Compute masks |
|
|
377 |
mask_bed_file = dilate_masks(mask_tumor, image_name, save_path, diff=False, name=descriptor) |
|
|
378 |
mask_edge_file = dilate_masks(mask_tumor, image_name, save_path, diff=True, name=descriptor) |
|
|
379 |
|
|
|
380 |
# Load image data |
|
|
381 |
im = nib.load(image_name).get_data().astype(np.float32) |
|
|
382 |
mask_tumor = nib.load(mask_tumor).get_data().astype(np.uint8) |
|
|
383 |
mask_bed = nib.load(mask_bed_file).get_data().astype(np.uint8) |
|
|
384 |
mask_edge = nib.load(mask_edge_file).get_data().astype(np.uint8) |
|
|
385 |
|
|
|
386 |
# Delete dilated masks |
|
|
387 |
# os.remove(mask_bed_file) |
|
|
388 |
# os.remove(mask_edge_file) |
|
|
389 |
|
|
|
390 |
# Preprocess image |
|
|
391 |
# Remove outliers |
|
|
392 |
# Remove by pct |
|
|
393 |
im_s = sorted(im.reshape(-1)) |
|
|
394 |
top_thresh = im_s[-round(len(im_s) * top_pct)] |
|
|
395 |
bot_thresh = im_s[round(len(im_s) * bot_pct)] |
|
|
396 |
im[im > top_thresh] = top_thresh |
|
|
397 |
im[im < bot_thresh] = bot_thresh |
|
|
398 |
|
|
|
399 |
# Convert to 8 bit |
|
|
400 |
# im -= im.min() |
|
|
401 |
# im /= im.max() |
|
|
402 |
# im *= 255 |
|
|
403 |
# im = im.astype(np.uint8) |
|
|
404 |
|
|
|
405 |
colormap_seg2 = ['black', 'green'] |
|
|
406 |
rows = range(20, im.shape[0] - 20) |
|
|
407 |
cols = range(10, im.shape[1] - 10) |
|
|
408 |
# Make image overlays |
|
|
409 |
for i, mask in enumerate([mask_tumor, mask_edge, mask_bed]): |
|
|
410 |
overlay_image(base_image=im[rows, :, slices[0]].T, |
|
|
411 |
overlay_image=mask[rows, :, slices[0]].T, |
|
|
412 |
colormap=colormap_seg2, |
|
|
413 |
sname=snames[i]) |
|
|
414 |
|
|
|
415 |
# Combine images into a montage |
|
|
416 |
make_montage_init(snames, sname_mont='area_montage.png') |