[5d12a0]: / ants / ops / bias_correction.py

Download this file

331 lines (277 with data), 10.1 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
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
__all__ = ["n3_bias_field_correction",
"n3_bias_field_correction2",
"n4_bias_field_correction",
"abp_n4"]
import ants
from ants.decorators import image_method
from ants.internal import get_lib_fn, get_pointer_string, process_arguments
@image_method
def n3_bias_field_correction(image, downsample_factor=3):
"""
N3 Bias Field Correction
ANTsR function: `n3BiasFieldCorrection`
Arguments
---------
image : ANTsImage
image to be bias corrected
downsample_factor : scalar
how much to downsample image before performing bias correction
Returns
-------
ANTsImage
Example
-------
>>> import ants
>>> image = ants.image_read( ants.get_ants_data('r16') )
>>> image_n3 = ants.n3_bias_field_correction(image)
"""
outimage = image.clone()
args = [image.dimension, image, outimage, downsample_factor]
processed_args = process_arguments(args)
libfn = get_lib_fn("N3BiasFieldCorrection")
libfn(processed_args)
return outimage
@image_method
def n3_bias_field_correction2(
image,
mask=None,
rescale_intensities=False,
shrink_factor=4,
convergence={"iters": 50, "tol": 1e-7},
spline_param=None,
number_of_fitting_levels=4,
return_bias_field=False,
verbose=False,
weight_mask=None,
):
"""
N3 Bias Field Correction
ANTsR function: `n3BiasFieldCorrection2`
Arguments
---------
image : ANTsImage
image to bias correct
mask : ANTsImage
Input mask. If not specified, the entire image is used.
rescale_intensities : boolean
At each iteration, a new intensity mapping is
calculated and applied but there is nothing which constrains the new
intensity range to be within certain values. The result is that the
range can "drift" from the original at each iteration. This option
rescales to the [min,max] range of the original image intensities within
the user-specified mask. A mask is required to perform rescaling. Default
is False in ANTsR/ANTsPy but True in ANTs.
shrink_factor : scalar
Shrink factor for multi-resolution correction, typically integer less than 4
convergence : dict w/ keys `iters` and `tol`
iters : maximum number of iterations
tol : the convergence tolerance. Default tolerance is 1e-7 in ANTsR/ANTsPy but 0.0 in ANTs.
spline_param : float or vector Parameter controlling number of control
points in spline. Either single value, indicating the spacing in each
direction, or vector with one entry per dimension of image, indicating
the mesh size. If None, defaults to mesh size of 1 in all dimensions.
number_of_fitting_levels : integer
Number of fitting levels per iteration.
return_bias_field : boolean
Return bias field instead of bias corrected image.
verbose : boolean
enables verbose output.
weight_mask : ANTsImage (optional)
antsImage of weight mask
Returns
-------
ANTsImage
Example
-------
>>> image = ants.image_read( ants.get_ants_data('r16') )
>>> image_n3 = ants.n3_bias_field_correction2(image)
"""
if image.pixeltype != "float":
image = image.clone("float")
iters = convergence["iters"]
tol = convergence["tol"]
if mask is None:
mask = image * 0 + 1
if spline_param is None:
spline_param = [1] * image.dimension
N3_CONVERGENCE_1 = "[%i,%.10f]" % (iters, tol)
N3_SHRINK_FACTOR_1 = str(shrink_factor)
if (not isinstance(spline_param, (list, tuple))) or (len(spline_param) == 1):
N3_BSPLINE_PARAMS = "[%i,%i]" % (spline_param, number_of_fitting_levels)
elif (isinstance(spline_param, (list, tuple))) and (
len(spline_param) == image.dimension
):
N3_BSPLINE_PARAMS = "[%s,%i]" % (("x".join([str(sp) for sp in spline_param])), number_of_fitting_levels)
else:
raise ValueError(
"Length of splineParam must either be 1 or dimensionality of image"
)
if weight_mask is not None:
if not ants.is_image(weight_mask):
raise ValueError("Weight Image must be an antsImage")
outimage = image.clone("float")
outbiasfield = image.clone("float")
i = get_pointer_string(outimage)
b = get_pointer_string(outbiasfield)
output = "[%s,%s]" % (i, b)
kwargs = {
"d": outimage.dimension,
"i": image,
"w": weight_mask,
"s": N3_SHRINK_FACTOR_1,
"c": N3_CONVERGENCE_1,
"b": N3_BSPLINE_PARAMS,
"x": mask,
"r": int(rescale_intensities),
"o": output,
"v": int(verbose),
}
processed_args = process_arguments(kwargs)
libfn = get_lib_fn("N3BiasFieldCorrection")
libfn(processed_args)
if return_bias_field == True:
return outbiasfield
else:
return outimage
@image_method
def n4_bias_field_correction(
image,
mask=None,
rescale_intensities=False,
shrink_factor=4,
convergence={"iters": [50, 50, 50, 50], "tol": 1e-7},
spline_param=None,
return_bias_field=False,
verbose=False,
weight_mask=None,
):
"""
N4 Bias Field Correction
ANTsR function: `n4BiasFieldCorrection`
Arguments
---------
image : ANTsImage
image to bias correct
mask : ANTsImage
Input mask. If not specified, the entire image is used.
rescale_intensities : boolean
At each iteration, a new intensity mapping is
calculated and applied but there is nothing which constrains the new
intensity range to be within certain values. The result is that the
range can "drift" from the original at each iteration. This option
rescales to the [min,max] range of the original image intensities within
the user-specified mask. A mask is required to perform rescaling. Default
is False in ANTsR/ANTsPy but True in ANTs.
shrink_factor : scalar
Shrink factor for multi-resolution correction, typically integer less than 4
convergence : dict w/ keys `iters` and `tol`
iters : vector of maximum number of iterations for each level
tol : the convergence tolerance. Default tolerance is 1e-7 in ANTsR/ANTsPy but 0.0 in ANTs.
spline_param : float or vector
Parameter controlling number of control points in spline. Either single value,
indicating the spacing in each direction, or vector with one entry per
dimension of image, indicating the mesh size. If None, defaults to mesh size of 1 in all
dimensions.
return_bias_field : boolean
Return bias field instead of bias corrected image.
verbose : boolean
enables verbose output.
weight_mask : ANTsImage (optional)
antsImage of weight mask
Returns
-------
ANTsImage
Example
-------
>>> image = ants.image_read( ants.get_ants_data('r16') )
>>> image_n4 = ants.n4_bias_field_correction(image)
"""
if image.pixeltype != "float":
image = image.clone("float")
iters = convergence["iters"]
tol = convergence["tol"]
if mask is None:
mask = image * 0 + 1
if spline_param is None:
spline_param = [1] * image.dimension
N4_CONVERGENCE_1 = "[%s, %.10f]" % ("x".join([str(it) for it in iters]), tol)
N4_SHRINK_FACTOR_1 = str(shrink_factor)
if (not isinstance(spline_param, (list, tuple))) or (len(spline_param) == 1):
N4_BSPLINE_PARAMS = "[%i]" % spline_param
elif (isinstance(spline_param, (list, tuple))) and (
len(spline_param) == image.dimension
):
N4_BSPLINE_PARAMS = "[%s]" % ("x".join([str(sp) for sp in spline_param]))
else:
raise ValueError(
"Length of splineParam must either be 1 or dimensionality of image"
)
if weight_mask is not None:
if not ants.is_image(weight_mask):
raise ValueError("Weight Image must be an antsImage")
outimage = image.clone("float")
outbiasfield = image.clone("float")
i = get_pointer_string(outimage)
b = get_pointer_string(outbiasfield)
output = "[%s,%s]" % (i, b)
kwargs = {
"d": outimage.dimension,
"i": image,
"w": weight_mask,
"s": N4_SHRINK_FACTOR_1,
"c": N4_CONVERGENCE_1,
"b": N4_BSPLINE_PARAMS,
"x": mask,
"r": int(rescale_intensities),
"o": output,
"v": int(verbose),
}
processed_args = process_arguments(kwargs)
libfn = get_lib_fn("N4BiasFieldCorrection")
libfn(processed_args)
if return_bias_field == True:
return outbiasfield
else:
return outimage
@image_method
def abp_n4(image, intensity_truncation=(0.025, 0.975, 256), mask=None, usen3=False):
"""
Truncate outlier intensities and bias correct with the N4 algorithm.
ANTsR function: `abpN4`
Arguments
---------
image : ANTsImage
image to correct and truncate
intensity_truncation : 3-tuple
quantiles for intensity truncation
mask : ANTsImage (optional)
mask for bias correction
usen3 : boolean
if True, use N3 bias correction instead of N4
Returns
-------
ANTsImage
Example
-------
>>> import ants
>>> image = ants.image_read(ants.get_ants_data('r16'))
>>> image2 = ants.abp_n4(image)
"""
if (not isinstance(intensity_truncation, (list, tuple))) or (
len(intensity_truncation) != 3
):
raise ValueError("intensity_truncation must be list/tuple with 3 values")
outimage = ants.iMath(
image,
"TruncateIntensity",
intensity_truncation[0],
intensity_truncation[1],
intensity_truncation[2],
)
if usen3 == True:
outimage = n3_bias_field_correction(outimage, 4)
outimage = n3_bias_field_correction(outimage, 2)
return outimage
else:
outimage = n4_bias_field_correction(outimage, mask)
return outimage