crop center portion of a numpy image

后端 未结 5 1420
醉梦人生
醉梦人生 2020-12-08 13:52

Let\'s say I have a numpy image of some width x and height y. I have to crop the center portion of the image to width cropx and height cropy. Let\'s assume that cropx and cr

相关标签:
5条回答
  • 2020-12-08 14:03

    A simple modification from @Divakar 's answer that preserves 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 讨论(0)
  • 2020-12-08 14:06

    A more general solution based on @Divakar 's 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 clip 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 not only works with 2D image but also 3D image.

    Have a nice day.

    0 讨论(0)
  • 2020-12-08 14:15

    Another simple modification from @Divakar's answer to preserve color channels:

    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,:]
    
    0 讨论(0)
  • 2020-12-08 14:21

    Something along these lines -

    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]
    

    Sample run -

    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]])
    
    0 讨论(0)
  • 2020-12-08 14:25

    Thanks, Divakar.

    Your answer got me going 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
    
    0 讨论(0)
提交回复
热议问题