forked from MICLab-Unicamp/inCCsight
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsegmfuncs.py
281 lines (201 loc) · 7.62 KB
/
segmfuncs.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
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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# coding: utf-8
'''
Segmentation functions, positional args have to be (wFA_ms, eigenvects_ms)
'''
def segm_watershed(wFA_ms, eigenvects_ms, gaussian_sigma=0.5):
import numpy as np
from scipy import ndimage
import siamxt
from libcc.preprocess import run_analysis, grad_morf
from libcc.gets import getTheCC
from skimage.morphology import disk, square, erosion, dilation
from skimage.segmentation import watershed
from skimage.measure import label, regionprops
## MORPHOLOGICAL GRADIENT
# Gaussian filter
wFA_gauss = ndimage.gaussian_filter(wFA_ms, sigma=gaussian_sigma)
# Structuring element
se1 = np.zeros((3,3)).astype('bool')
se1[1,:] = True
se1[:,1] = True
# Gradient
grad_wFA = grad_morf(wFA_gauss, se1)
## MAX-TREE
#Structuring element. connectivity-4
se2 = se1.copy()
# Computing Max Tree by volume
mxt = siamxt.MaxTreeAlpha(((grad_wFA)*255).astype("uint8"), se2)
attr = "volume"
leaves_volume = mxt.computeExtinctionValues(mxt.computeVolume(),attr)
# Create canvas
segm_markers = np.zeros(grad_wFA.shape, dtype = np.int16)
# Labeling canvas
indexes = np.argsort(leaves_volume)[::-1]
counter = 1
for i in indexes[:85]:
segm_markers = segm_markers + mxt.recConnectedComponent(i)*(counter)
counter+=1
## SEGMENTING CC
# Watershed
wc_wfa = watershed(grad_wFA, segm_markers)
# Thresholding regions by FA
seg_wFA = np.zeros((wFA_ms).shape).astype(bool)
segs = seg_wFA
listAll = np.unique(wc_wfa)
for i in listAll:
media = np.mean(wFA_ms[wc_wfa == i])
if media > 0.2*wFA_ms.max():
seg_wFA[wc_wfa == i] = 1
# Getting the CC
seg_wFA, ymed, xmed = getTheCC(seg_wFA)
return seg_wFA
def segm_roqs(wFA_ms, eigvects_ms):
import numpy as np
from scipy.ndimage.morphology import binary_fill_holes, binary_closing, binary_erosion, binary_opening
from skimage.measure import label
from skimage import measure
# Seed grid search - get highest FA seed within central area
h,w = wFA_ms.shape
# Define region to make search
region = np.zeros((h,w))
region[int(h/3):int(2*h/3), int(w/2):int(2*w/3)] = 1
region = wFA_ms * region
# Get the indices of maximum element in numpy array
fa_seed = np.amax(region)
seedx, seedy = np.where(region == fa_seed)
# Defining seeds positions
seed = [seedx, seedy]
# Get principal eigenvector (direction of maximal diffusivity)
max_comp_in = np.argmax(eigvects_ms[:,seed[0],seed[1]],axis=0)
max_comp_in = np.argmax(np.bincount(max_comp_in.ravel()))
# Max component value
Cmax_seed = eigvects_ms[max_comp_in,seed[0],seed[1]]
# First selection criterion
# Get pixels with the same maximum component (x,y or z) of the principal eigenvector
princ = np.argmax(eigvects_ms,axis=0)
fsc = princ == max_comp_in
# Calculate magnification array (MA)
alpha = 0.3
beta = 0.3
gamma = 0.5
MA = (wFA_ms-np.amax(wFA_ms)*alpha)/(np.amax(wFA_ms)*beta)+gamma
# Apply MA to eigenvector
ssc = np.clip(np.amax(eigvects_ms*MA, axis=0), 0, 1)
ssc = ssc*fsc
# Keep only pixels with Cmax greater than Cmax_seed-0.1
mask_cc = ssc > Cmax_seed-0.1
labels = label(mask_cc)
mask_cc = labels == np.argmax(np.bincount(labels.flat)[1:])+1
segm = binary_fill_holes(mask_cc)
# Post processing
contours = measure.find_contours(segm, 0.1)
contour = sorted(contours, key=lambda x: len(x))[-1]
return segm
def segm_staple(path, fissure, segm_import=None):
import tempfile
import numpy as np
import nibabel as nib
import SimpleITK as sitk
staple = sitk.STAPLEImageFilter()
writer = sitk.ImageFileWriter()
reader = sitk.ImageFileReader()
name_dict = {'ROQS': 'roqs',
'Watershed': 'watershed'}
nii_list = []
for segmentation_method in name_dict.keys():
folderpath = path + 'inCCsight/'
filename = 'segm_' + name_dict[segmentation_method] + '.nii.gz'
reader.SetFileName(folderpath + filename)
nii_list.append(reader.Execute())
if segm_import is not None:
filename = 'segm_import.nii.gz'
reader.SetFileName(folderpath + filename)
nii_list.append(reader.Execute())
nii_staple = staple.Execute(nii_list)
writer.SetFileName('{}/segm_staple.nii.gz'.format(folderpath))
writer.Execute(nii_staple)
seg_staple = nib.load('{}/segm_staple.nii.gz'.format(folderpath)).get_data()
seg_staple = seg_staple[fissure,:,:]
seg_staple[seg_staple == np.min(seg_staple)] = 0
seg_staple[seg_staple > 0] = 1
seg_staple = np.array(seg_staple, dtype='int32')
return seg_staple
def segm_mask(path, threshold=0):
import nibabel as nib
import numpy as np
import os
volume = nib.load(path).get_data()
# Normalize
vol = np.array(volume, dtype='int32')
vol[vol > threshold] = 1
vol = np.squeeze(vol)
if np.max(vol) != 0:
# Find direction
mask = None
fissure = None
for i in range(3):
for j in range(2):
if np.sum(np.max(np.max(vol, axis=i),axis=j)) == 1:
fissure = np.argmax(np.max(np.max(vol,axis=i),axis=j))
axis = 0
# Obtain mask from direction
if (i==1 and j==1) or (i==2 and j==1):
mask = vol[fissure,:,:]
axis = 0
elif (i==0 and j==1) or (i==2 and j==0):
mask = vol[:,fissure,:]
axis = 1
elif (i==0 and j==0) or (i==1 and j==0):
mask = vol[:,:,fissure]
axis = 2
return mask, fissure, axis
else:
print('> Warning: Invalid mask (all values = 0) for subject {}.'.format(os.path.basename(os.path.dirname(path))))
return None, None, None
def segm_watershed_3d(wFA, gaussian_sigma=0.3):
import numpy as np
from scipy import ndimage
import siamxt
from libcc.preprocess import run_analysis, grad_morf
from libcc.gets import getTheCC, getLargestConnectedComponent
from skimage.morphology import disk, square, erosion, dilation
from skimage.segmentation import watershed
from skimage.measure import label, regionprops
## MORPHOLOGICAL GRADIENT
# Gaussian filter
wFA_gauss = ndimage.gaussian_filter(wFA, sigma=gaussian_sigma)
# Structuring element
se1 = np.zeros((3,3,3)).astype('bool')
se1[1,:,:] = True
se1[:,1,:] = True
se1[:,:,1] = True
# Gradient
grad_wFA = grad_morf(wFA_gauss, se1)
## MAX-TREE
#Structuring element. connectivity-4
se2 = se1.copy()
# Computing Max Tree by volume
mxt = siamxt.MaxTreeAlpha(((grad_wFA)*255).astype("uint8"), se2)
attr = "volume"
leaves_volume = mxt.computeExtinctionValues(mxt.computeVolume(),attr)
# Create canvas
segm_markers = np.zeros(grad_wFA.shape, dtype = np.int16)
# Labeling canvas
indexes = np.argsort(leaves_volume)[::-1]
counter = 1
for i in indexes[:85]:
segm_markers = segm_markers + mxt.recConnectedComponent(i)*(counter)
counter+=1
## SEGMENTING CC
# Watershed
wc_wfa = watershed(grad_wFA, segm_markers)
# Thresholding regions by FA
seg_wFA = np.zeros((grad_wFA).shape).astype(bool)
listAll = np.unique(wc_wfa)
for i in listAll:
media = np.mean(wFA[wc_wfa == i])
if media > 0.2*wFA.max():
seg_wFA[wc_wfa == i] = 1
# Getting the CC
seg_wFA_3d = getLargestConnectedComponent(seg_wFA)
return seg_wFA_3d