[8271d0]: / utils / utils_mri.py

Download this file

242 lines (183 with data), 8.0 kB

  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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# -*- coding: utf-8 -*-
"""
Acknowledgement: alberts,tetteh
"""
from __future__ import print_function
import os as os
import SimpleITK as itk
import numpy as np
def make_itk_image(imageArray, protoImage=None):
""" Create an itk image given an image numpy ndarray (imageArray) and an
itk proto-image (protoImage) to provide Origin, Spacing and Direction."""
image = itk.GetImageFromArray(imageArray)
if protoImage != None:
image.CopyInformation(protoImage)
return image
def make_itk_image_series(imageArray4D, protoImage):
""" Create a 4D itk image given a 4-dimensional image numpy ndarray
(imageArray4D) and a 3-dimensional itk proto-image (protoImage) for the
3D volumes within the 4D array."""
if len(imageArray4D.shape) is not 4:
print('This function is written for 4dimensional input arrays only')
return
mainDim = imageArray4D.shape[0]
imageList = []
for dim in range(mainDim):
imageArray = imageArray4D[dim, :]
image = make_itk_image(imageArray, protoImage)
imageList.append(image)
image4D = itk.JoinSeries(*imageList)
return image4D
def write_itk_imageArray(imageArray, filename, src_nii=None):
img = make_itk_image(imageArray, src_nii)
write_itk_image(img, filename)
def write_itk_image(image, filename):
""" Write an itk image to a specified filename."""
writer = itk.ImageFileWriter()
writer.SetFileName(filename)
if filename.endswith('.nii'):
Warning('You are converting nii, be careful with type conversions')
writer.Execute(image)
return
def get_itk_image(filename):
""" Get an itk image given an image filename of extionsion *TIFF, JPEG,
PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti, Analyze, SDT/SPR (Stimulate),
Nrrd or VTK images*."""
reader = itk.ImageFileReader()
reader.SetFileName(filename)
image = reader.Execute()
return image
def get_itk_array(filenameOrImage, normalize=False):
""" Get an image array given an image filename of extension *TIFF, JPEG,
PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti, Analyze, SDT/SPR (Stimulate),
Nrrd or VTK images*."""
if isinstance(filenameOrImage, str):
image = get_itk_image(filenameOrImage)
else:
image = filenameOrImage
imageArray = itk.GetArrayFromImage(image)
if normalize:
imageArray = imageArray - np.min(imageArray)
imageArray = imageArray * 1.0 / np.max(imageArray)
return imageArray
def get_itk_data(filenameOrImage, verbose=False):
""" Get the image array, image size and pixel dimensions of a certain itk
image or an image specified by a certain filename (filenameOrImage)."""
if isinstance(filenameOrImage, str):
image = get_itk_image(filenameOrImage)
else:
image = filenameOrImage
imageData = itk.GetArrayFromImage(image)
imageSize = imageData.shape
imageSpaces = image.GetSpacing()[::-1]
imageDataType = imageData.dtype
if verbose:
print('\t image size: ' + str(imageSize))
print('\t image spacing: ' + str(imageSpaces))
print('\t image data type: ' + str(imageDataType))
return imageData, imageSize, imageSpaces
def convert_to_nii(filenames):
""" Convert image files to nifti image files."""
for filename in filenames:
image = get_itk_image(filename)
nii_filename = os.path.splitext(filename)[0] + '.nii'
write_itk_image(image, nii_filename)
return
def convert_dicom(source_path, save_path):
"""
converts dicom series to image format specified in path.
Parameters
----------
source_path : string
path to dicom series.
path : string
path to save new image (extension determines image format)
"""
image = read_dicom(source_path, verbose=True)
write_itk_image(image, save_path)
def read_dicom(source_path, verbose=True):
"""
reads dicom series.
Parameters
----------
source_path : string
path to dicom series.
verbose : boolean
print out all series file names.
Returns
-------
image : itk image
image volume.
"""
reader = itk.ImageSeriesReader()
names = reader.GetGDCMSeriesFileNames(source_path)
if len(names) < 1:
raise IOError('No Series can be found at the specified path!')
elif verbose:
print('image series found in :\n\t %s' % source_path)
reader.SetFileNames(names)
image = reader.Execute()
if verbose:
get_itk_data(image, verbose=True)
return image
def read_images(data_path, name_dict, img_index=0):
patients = os.listdir(data_path)
patients.sort()
print("Found %i patients in the data path" % len(patients))
data = []
for p in patients:
img = get_itk_image(data_path + p + "/" + name_dict[img_index])
data.append(img)
return data
def get_2d_images(input_filename, output_folder, ext):
vol = get_itk_array(input_filename)
import matplotlib.pyplot as plt
for index, img in enumerate(vol):
output_filename = output_folder + '/' + str(index) + '.' + ext
plt.imsave(fname=output_filename, arr=img, cmap='gray')
def get_patch_data(volume4d, divs=(2, 2, 2, 1), offset=(5, 5, 5, 0)):
patches = []
shape = volume4d.shape
widths = [int(s / d) for s, d in zip(shape, divs)]
patch_shape = [w + o * 2 for w, o in zip(widths, offset)]
for x in np.arange(0, shape[0], widths[0]):
for y in np.arange(0, shape[1], widths[1]):
for z in np.arange(0, shape[2], widths[2]):
for t in np.arange(0, shape[3], widths[3]):
patch = np.zeros(patch_shape, dtype=volume4d.dtype)
x_s = x - offset[0] if x - offset[0] >= 0 else 0
x_e = x + widths[0] + offset[0] if x + widths[0] + offset[0] <= shape[0] else shape[0]
y_s = y - offset[1] if y - offset[1] >= 0 else 0
y_e = y + widths[1] + offset[1] if y + widths[1] + offset[1] <= shape[1] else shape[1]
z_s = z - offset[2] if z - offset[2] >= 0 else 0
z_e = z + widths[2] + offset[2] if z + widths[2] + offset[2] <= shape[2] else shape[2]
t_s = t - offset[3] if t - offset[3] >= 0 else 0
t_e = t + widths[3] + offset[3] if t + widths[3] + offset[3] <= shape[3] else shape[3]
vp = volume4d[x_s:x_e, y_s:y_e, z_s:z_e, t_s:t_e]
px_s = offset[0] - (x - x_s)
px_e = px_s + (x_e - x_s)
py_s = offset[1] - (y - y_s)
py_e = py_s + (y_e - y_s)
pz_s = offset[2] - (z - z_s)
pz_e = pz_s + (z_e - z_s)
pt_s = offset[3] - (t - t_s)
pt_e = pt_s + (t_e - t_s)
patch[px_s:px_e, py_s:py_e, pz_s:pz_e, pt_s:pt_e] = vp
patches.append(patch)
return np.array(patches, dtype=volume4d.dtype)
def get_volume_from_patches(patches5d, divs=(2, 2, 2, 1), offset=(5, 5, 5, 0)):
new_shape = [(ps - of * 2) * d for ps, of, d in zip(patches5d.shape[-4:], offset, divs)]
volume4d = np.zeros(new_shape, dtype=patches5d.dtype)
shape = volume4d.shape
widths = [int(s / d) for s, d in zip(shape, divs)]
index = 0
for x in np.arange(0, shape[0], widths[0]):
for y in np.arange(0, shape[1], widths[1]):
for z in np.arange(0, shape[2], widths[2]):
for t in np.arange(0, shape[3], widths[3]):
patch = patches5d[index]
index = index + 1
volume4d[x:x + widths[0], y:y + widths[1], z:z + widths[2], t:t + widths[3]] = \
patch[offset[0]:offset[0] + widths[0], offset[1]:offset[1] + widths[1],
offset[2]:offset[2] + widths[2], offset[3]:offset[3] + widths[3]]
return volume4d