Part of the center in the middle of the numpy image

Let's say I have a numerical image of some width x and height y. I have to crop the center of the image to cropx width and height. Suppose cropx and yield are positive integers other than zero and smaller than the corresponding image size. What is the best way to apply slicing to the output image?

+20
python numpy image image-processing crop
source share
4 answers

Something in this direction -

def crop_center(img,cropx,cropy): y,x = img.shape startx = x//2-(cropx//2) starty = y//2-(cropy//2) return img[starty:starty+cropy,startx:startx+cropx] 

Run Example -

 In [45]: img Out[45]: array([[88, 93, 42, 25, 36, 14, 59, 46, 77, 13, 52, 58], [43, 47, 40, 48, 23, 74, 12, 33, 58, 93, 87, 87], [54, 75, 79, 21, 15, 44, 51, 68, 28, 94, 78, 48], [57, 46, 14, 98, 43, 76, 86, 56, 86, 88, 96, 49], [52, 83, 13, 18, 40, 33, 11, 87, 38, 74, 23, 88], [81, 28, 86, 89, 16, 28, 66, 67, 80, 23, 95, 98], [46, 30, 18, 31, 73, 15, 90, 77, 71, 57, 61, 78], [33, 58, 20, 11, 80, 25, 96, 80, 27, 40, 66, 92], [13, 59, 77, 53, 91, 16, 47, 79, 33, 78, 25, 66], [22, 80, 40, 24, 17, 85, 20, 70, 81, 68, 50, 80]]) In [46]: crop_center(img,4,6) Out[46]: array([[15, 44, 51, 68], [43, 76, 86, 56], [40, 33, 11, 87], [16, 28, 66, 67], [73, 15, 90, 77], [80, 25, 96, 80]]) 
+30
source share

More general solution based on @Divakar answer:

 def cropND(img, bounding): start = tuple(map(lambda a, da: a//2-da//2, img.shape, bounding)) end = tuple(map(operator.add, start, bounding)) slices = tuple(map(slice, start, end)) return img[slices] 

and if we have an array a

 >>> a = np.arange(100).reshape((10,10)) array([[ 0, 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]]) 

We can crop it with cropND(a, (5,5)) , you will get:

 >>> cropND(a, (5,5)) array([[33, 34, 35, 36, 37], [43, 44, 45, 46, 47], [53, 54, 55, 56, 57], [63, 64, 65, 66, 67], [73, 74, 75, 76, 77]]) 

It works not only with 2D images, but also with 3D images.

Have a nice day.

+14
source share

Thank you, Divacar.

Your answer made me go in the right direction. I came up with this using negative slice offsets to count from the end:

 def cropimread(crop, xcrop, ycrop, fn): "Function to crop center of an image file" img_pre= msc.imread(fn) if crop: ysize, xsize, chan = img_pre.shape xoff = (xsize - xcrop) // 2 yoff = (ysize - ycrop) // 2 img= img_pre[yoff:-yoff,xoff:-xoff] else: img= img_pre return img 
+1
source share

A simple modification to @Divakar's answer, which saves the image channel:

  def crop_center(self, img, cropx, cropy): _, y, x = img.shape startx = x // 2 - (cropx // 2) starty = y // 2 - (cropy // 2) return img[:, starty:starty + cropy, startx:startx + cropx] 
0
source share

All Articles