Skip to content

Commit 1ed4537

Browse files
committed
ENH: crop_image to bounds, adding margin
1 parent 2c4a3e1 commit 1ed4537

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

nibabel/funcs.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -221,37 +221,42 @@ def _aff_is_diag(aff):
221221
return np.allclose(rzs_aff, np.diag(np.diag(rzs_aff)))
222222

223223

224-
def crop_image(img, mask=None):
225-
''' Crop ``img`` to smallest region that contains all non-zero data
224+
def crop_image(img, bounds, margin=0):
225+
''' Crop ``img`` to specified bounds
226226
227-
The image is cropped in the current orientation; no rotations or resampling
228-
are performed.
227+
The image is cropped in the current orientation; no rotation or resampling
228+
is performed.
229229
The affine matrix is updated with the new intercept, so that all values are
230230
found at the same RAS locations.
231231
232232
Parameters
233233
----------
234234
img : ``spatialimage``
235-
mask : ``spatialimage``, optional
236-
If supplied, use the bounding box of ``mask``, rather than ``img``
235+
Image to be cropped
236+
bounds : (3, 2) array-like
237+
Minimum and maximum (inclusive) voxel indices, in each dimension, to be
238+
included in cropped image
239+
margin : int, optional
240+
Margin, in voxels, to include on each side of cropped image
237241
238242
Returns
239243
-------
240244
cropped_img : ``spatialimage``
241245
Version of `img` with cropped data array and updated affine matrix
242246
'''
243-
if mask is None:
244-
mask = img
245-
elif not np.allclose(img.affine == mask.affine):
246-
raise ValueError('Affine for image does not match affine for mask')
247247

248-
bounds = np.sort(np.vstack(np.nonzero(mask.get_data())))[:, [0, -1]]
248+
try:
249+
bounds = np.asanyarray(bounds) + np.array([-margin, margin])
250+
assert bounds.shape == (3, 2)
251+
except (ValueError, AssertionError) as err:
252+
raise ValueError("bounds must be interpretable as a 3x2 array")
253+
249254
x, y, z = bounds
250-
new_origin = np.vstack((bounds[:, [0]], [1]))
255+
new_origin = np.vstack((bounds[:, [0]], 1))
251256

252-
new_data = img.get_data()[x[0]:x[1] + 1, y[0]:y[1] + 1, z[0]:z[1] + 1]
257+
bounded_data = img.get_data()[x[0]:x[1] + 1, y[0]:y[1] + 1, z[0]:z[1] + 1]
253258

254259
new_aff = img.affine.copy()
255260
new_aff[:, [3]] = img.affine.dot(new_origin)
256261

257-
return img.__class__(new_data, new_aff, img.header)
262+
return img.__class__(bounded_data, new_aff, img.header)

0 commit comments

Comments
 (0)