|
a |
|
b/Serialized/helper/myio.py |
|
|
1 |
''' |
|
|
2 |
I/O functions for RSNA 2019 |
|
|
3 |
Updated: Yuval 12/10/19 |
|
|
4 |
''' |
|
|
5 |
|
|
|
6 |
|
|
|
7 |
import os |
|
|
8 |
from skimage.io import imread |
|
|
9 |
import numpy as np |
|
|
10 |
import torch |
|
|
11 |
import pydicom |
|
|
12 |
import SimpleITK as sitk |
|
|
13 |
|
|
|
14 |
DEFAULT_IMAGES_BASE_PATH = '/media/nvme/data/RSNA/' |
|
|
15 |
train_path='stage_1_train_images/' |
|
|
16 |
test_path='stage_1_test_images/' |
|
|
17 |
file_format='ID_{}.dcm' |
|
|
18 |
|
|
|
19 |
def load_one_image(pid, |
|
|
20 |
equalize=False, |
|
|
21 |
base_path=DEFAULT_IMAGES_BASE_PATH, |
|
|
22 |
file_path=train_path, |
|
|
23 |
file_format=file_format, |
|
|
24 |
window_eq=False,rescale=False): |
|
|
25 |
''' |
|
|
26 |
Load one image from a DICOM file |
|
|
27 |
Args: |
|
|
28 |
pid : string, image id |
|
|
29 |
equalize : Equalize - return (image-mean)/std |
|
|
30 |
base_path : Base File path for the images |
|
|
31 |
file_path : file path for the images (from base_path) |
|
|
32 |
file_format : format string to get from pid to file name. default='ID_{}.dcm' |
|
|
33 |
window_eq=False : Do window equaliztion: (for backward competability, don't use it anymore use WSO) |
|
|
34 |
False - No equalization |
|
|
35 |
True - Do equalization with window = [(40,80),(80,200),(600,2800)] |
|
|
36 |
tuple/list shaped as above |
|
|
37 |
rescale=False : Use DICOM parameters for rescale, done automaticaly if windows_eq!=False |
|
|
38 |
Update:Yuval 12/10/19 |
|
|
39 |
|
|
|
40 |
''' |
|
|
41 |
dcm_data = pydicom.dcmread(base_path+ file_path+ file_format.format(pid)) |
|
|
42 |
try: |
|
|
43 |
pixels = dcm_data.pixel_array |
|
|
44 |
except: |
|
|
45 |
try: |
|
|
46 |
read_image = sitk.ReadImage(base_path+ file_path+ file_format.format(pid)) |
|
|
47 |
pixels = sitk.GetArrayFromImage(read_image)[0].astype(np.float32) |
|
|
48 |
except: |
|
|
49 |
print('got some error with pid {} {}'.format(pid,base_path+ file_path+ file_format.format(pid))) |
|
|
50 |
pixels = np.zeros((512,512)) |
|
|
51 |
m = max(pixels.shape) |
|
|
52 |
p = np.ones((m,m),dtype=np.float)*pixels[0,0] |
|
|
53 |
p[(m-pixels.shape[0])//2:(m-pixels.shape[0])//2+pixels.shape[0], |
|
|
54 |
(m-pixels.shape[1])//2:(m-pixels.shape[1])//2+pixels.shape[1]]=pixels |
|
|
55 |
pixels = p |
|
|
56 |
if window_eq: |
|
|
57 |
if window_eq==3: |
|
|
58 |
pixels = dcm_window3(dcm_data,pixels) |
|
|
59 |
if equalize: |
|
|
60 |
for i in range(3): |
|
|
61 |
pixels[i] = (pixels[i]-pixels[i].mean())/(pixels[i].std()+1e-6) |
|
|
62 |
else: |
|
|
63 |
pixels = dcm_window(dcm_data,pixels) |
|
|
64 |
else: |
|
|
65 |
if rescale: |
|
|
66 |
b = dcm_data.RescaleIntercept |
|
|
67 |
m = dcm_data.RescaleSlope |
|
|
68 |
pixels = m * pixels + b |
|
|
69 |
if equalize: |
|
|
70 |
pixels = (pixels-pixels.mean())/(pixels.std()+1e-6) |
|
|
71 |
|
|
|
72 |
return pixels |
|
|
73 |
|
|
|
74 |
def dcm_window(dcm,pixel_array,window = None): |
|
|
75 |
''' |
|
|
76 |
return a windowed image. |
|
|
77 |
if now window is provided, use the DICOM first window data |
|
|
78 |
if window length ==3, use window data |
|
|
79 |
''' |
|
|
80 |
ymin=0 |
|
|
81 |
ymax=255 |
|
|
82 |
if window is None: |
|
|
83 |
c = int(dcm.WindowCenter[0] if type(dcm.WindowCenter) == pydicom.multival.MultiValue else dcm.WindowCenter) |
|
|
84 |
w = int(dcm.WindowWidth[0] if type(dcm.WindowWidth) == pydicom.multival.MultiValue else dcm.WindowWidth) |
|
|
85 |
else: |
|
|
86 |
c , w = window |
|
|
87 |
b = dcm.RescaleIntercept |
|
|
88 |
m = dcm.RescaleSlope |
|
|
89 |
x = m * pixel_array + b |
|
|
90 |
# windowing C.11.2.1.2.1 Default LINEAR Function |
|
|
91 |
y = np.zeros_like(x) |
|
|
92 |
y[x <= (c - 0.5 - (w - 1) / 2)] = ymin |
|
|
93 |
# ymin + np.tanh(((x[x <= (c - 0.5 - (w - 1) / 2)] - (c - 0.5)) / (w - 1) + 0.5))* (ymax - ymin) |
|
|
94 |
y[x > (c - 0.5 + (w - 1) / 2)] = ymax |
|
|
95 |
# ymax + np.tanh(((x[x > (c - 0.5 + (w - 1) / 2)] - (c - 0.5)) / (w - 1) + 0.5))* (ymax - ymin) |
|
|
96 |
y[(x > (c - 0.5 - (w - 1) / 2)) & (x <= (c - 0.5 + (w - 1) / 2))] = \ |
|
|
97 |
((x[(x > (c - 0.5 - (w - 1) / 2)) & (x <= (c - 0.5 + (w - 1) / 2))] - (c - 0.5)) / (w - 1) + 0.5) * (ymax - ymin) + ymin |
|
|
98 |
# y = ((x - (c - 0.5)) / (w - 1) + 0.5) * (ymax - ymin) + ymin |
|
|
99 |
return y/255.0 |
|
|
100 |
|
|
|
101 |
def dcm_window3(dcm,pixel_array,windows = None): |
|
|
102 |
y = np.zeros((3,)+pixel_array.shape,dtype=np.float) |
|
|
103 |
if windows is None: |
|
|
104 |
windows=[(40,80),(80,200),(600,2800)] |
|
|
105 |
for i in range(3): |
|
|
106 |
y[i]=dcm_window(dcm,pixel_array,window = windows[i]) |
|
|
107 |
return y |
|
|
108 |
|