@@ -245,16 +245,41 @@ def crop_image(img, bounds, margin=0):
245
245
Version of `img` with cropped data array and updated affine matrix
246
246
'''
247
247
248
- try :
249
- bounds = np .asanyarray (bounds ) + np .array ([- margin , margin ])
250
- assert bounds .shape == (3 , 2 )
251
- except (ValueError , AssertionError ):
248
+ shape = np .reshape (img .shape [:3 ], (3 , 1 ))
249
+ bounds = np .asanyarray (bounds )
250
+ if bounds .shape != (3 , 2 ):
252
251
raise ValueError ("bounds must be interpretable as a 3x2 array" )
252
+ elif np .any (bounds > shape ):
253
+ raise ValueError ("bounds must not exceed image dimensions" )
254
+
255
+ # Permit negative bounds
256
+ if np .any (bounds < 0 ):
257
+ bounds = (bounds + shape ) % shape
258
+
259
+ if np .any (bounds < 0 ):
260
+ raise ValueError ("negative bounds may not exceed image dimensions" )
261
+ elif np .any (bounds [:, 0 ] > bounds [:, 1 ]):
262
+ raise ValueError ("degenerate (0 width) crops are not permitted" )
263
+
264
+ # Add margin in all directions
265
+ bounds += np .array ([- margin , margin ])
266
+
267
+ # Set min/max
268
+ bounds [bounds < 0 ] = 0
269
+ over = bounds [:, 1 ] > shape .reshape (- 1 ) - 1
270
+ bounds [over , 1 ] = shape [over , 0 ] - 1
271
+
272
+ # Include upper bounds
273
+ bounds [:, 1 ] += 1
274
+
275
+ # Return original image if no cropping required
276
+ if np .array_equal (bounds , np .hstack (([[0 ], [0 ], [0 ]], shape ))):
277
+ return img
253
278
254
279
x , y , z = bounds
255
280
new_origin = np .vstack ((bounds [:, [0 ]], 1 ))
256
281
257
- bounded_data = img .get_data ()[x [0 ]:x [1 ] + 1 , y [0 ]:y [1 ] + 1 , z [0 ]:z [1 ] + 1 ]
282
+ bounded_data = img .get_data ()[x [0 ]:x [1 ], y [0 ]:y [1 ], z [0 ]:z [1 ]]
258
283
259
284
new_aff = img .affine .copy ()
260
285
new_aff [:, [3 ]] = img .affine .dot (new_origin )
0 commit comments