DiGuaQiu commited on
Commit
fb0ea94
1 Parent(s): 737e510

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +147 -0
utils.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import SimpleITK as sitk
3
+
4
+ channels = [
5
+ "background",
6
+ "spleen",
7
+ "right_kidney",
8
+ "left_kidney",
9
+ "gallbladder",
10
+ "liver",
11
+ "stomach",
12
+ "pancreas",
13
+ "right_adrenal_gland",
14
+ "left_adrenal_gland",
15
+ "left_lung",
16
+ "right_lung",
17
+ "heart",
18
+ "aorta",
19
+ "inferior_vena_cava",
20
+ "portal_vein_and_splenic_vein",
21
+ "left_iliac_artery",
22
+ "right_iliac_artery",
23
+ "left_iliac_vena",
24
+ "right_iliac_vena",
25
+ "esophagus",
26
+ "small_bowel",
27
+ "duodenum",
28
+ "colon",
29
+ "urinary_bladder",
30
+ "spine",
31
+ "sacrum",
32
+ "left_hip",
33
+ "right_hip",
34
+ "left_femur",
35
+ "right_femur",
36
+ "left_autochthonous_muscle",
37
+ "right_autochthonous_muscle",
38
+ "left_iliopsoas_muscle",
39
+ "right_iliopsoas_muscle",
40
+ "left_gluteus_maximus",
41
+ "right_gluteus_maximus",
42
+ "left_gluteus_medius",
43
+ "right_gluteus_medius",
44
+ "left_gluteus_minimus",
45
+ "right_gluteus_minimus",
46
+ ]
47
+
48
+
49
+ def make_isotropic(image, interpolator=sitk.sitkLinear, spacing=None):
50
+ """
51
+ Many file formats (e.g. jpg, png,...) expect the pixels to be isotropic, same
52
+ spacing for all axes. Saving non-isotropic data in these formats will result in
53
+ distorted images. This function makes an image isotropic via resampling, if needed.
54
+ Args:
55
+ image (SimpleITK.Image): Input image.
56
+ interpolator: By default the function uses a linear interpolator. For
57
+ label images one should use the sitkNearestNeighbor interpolator
58
+ so as not to introduce non-existant labels.
59
+ spacing (float): Desired spacing. If none given then use the smallest spacing from
60
+ the original image.
61
+ Returns:
62
+ SimpleITK.Image with isotropic spacing which occupies the same region in space as
63
+ the input image.
64
+ """
65
+ original_spacing = image.GetSpacing()
66
+ # Image is already isotropic, just return a copy.
67
+ if all(spc == original_spacing[0] for spc in original_spacing):
68
+ return sitk.Image(image)
69
+ # Make image isotropic via resampling.
70
+ original_size = image.GetSize()
71
+ if spacing is None:
72
+ spacing = min(original_spacing)
73
+ new_spacing = [spacing] * image.GetDimension()
74
+ new_size = [int(round(osz * ospc / spacing)) for osz, ospc in zip(original_size, original_spacing)]
75
+ return sitk.Resample(
76
+ image,
77
+ new_size,
78
+ sitk.Transform(),
79
+ interpolator,
80
+ image.GetOrigin(),
81
+ new_spacing,
82
+ image.GetDirection(),
83
+ 0, # default pixel value
84
+ image.GetPixelID(),
85
+ )
86
+
87
+
88
+ def label_mapper(seg):
89
+
90
+ labels = []
91
+ for _class in np.unique(seg):
92
+ if _class == 0:
93
+ continue
94
+ labels.append((seg == _class, channels[_class]))
95
+
96
+ return labels
97
+
98
+
99
+ def sitk2numpy(img, normalize=False):
100
+ img = sitk.DICOMOrient(img, "LPS")
101
+ # img = make_isotropic(img)
102
+ img = sitk.GetArrayFromImage(img)
103
+ if normalize:
104
+ minval, maxval = np.min(img), np.max(img)
105
+ img = ((img - minval) / (maxval - minval)).clip(0, 1) * 255
106
+ img = img.astype(np.uint8)
107
+ return img
108
+
109
+
110
+ def read_image(path, normalize=False):
111
+
112
+ img = sitk.ReadImage(path)
113
+ return sitk2numpy(img, normalize)
114
+
115
+
116
+ def display(image, seg=None, _slice=50):
117
+
118
+ # Image
119
+ if image is None or (isinstance(image, list) and len(image) == 0):
120
+ return None
121
+ if isinstance(image, list):
122
+ image = image[-1]
123
+ x = int(_slice * (image.shape[0] / 100))
124
+ image = image[x, :, :]
125
+
126
+ # Segmentation
127
+ if seg is None or (isinstance(seg, list) and len(seg) == 0):
128
+ seg = []
129
+ else:
130
+ if isinstance(seg, list):
131
+ seg = seg[-1]
132
+ seg = label_mapper(seg[x, :, :])
133
+
134
+ return image, seg
135
+
136
+
137
+ def read_and_display(path, image_state, seg_state):
138
+
139
+ image_state.clear()
140
+ seg_state.clear()
141
+
142
+ if path is not None:
143
+ image = read_image(path, normalize=True)
144
+ image_state.append(image)
145
+ return display(image), image_state, seg_state
146
+ else:
147
+ return None, image_state, seg_state