Divide an image into 5x5 blocks in python and compute histogram for each block

后端 未结 5 629
北恋
北恋 2020-12-28 19:32

Using Python, I have to:

  • Divide a Test_Image and Reference_image into 5x5 blocks,
  • Compute a histogram for each block, and
5条回答
  •  我在风中等你
    2020-12-28 20:24

    If your images are large, you can improve performance by manipulating the array's strides to produce the windows you need. The following will use a generalized sliding window function found at Efficient Overlapping Windows with Numpy - I will include it at the end.

    import numpy as np
    image1 = np.arange(100).reshape(10,10)
    image2 = np.arange(100).reshape(10,10)
    
    from itertools import izip
    window_size = (5,5)
    windows1 = sliding_window(image1, window_size)
    windows2 = sliding_window(image2, window_size)
    histograms = [(np.histogram(window1,bins=256),np.histogram(window2,bins=256))
                  for window1, window2 in izip(windows1, windows2)]
    
    for h1, h2 in histograms:
        print np.all(h1[0] == h2[0])
    

    sliding window function(s):

    from numpy.lib.stride_tricks import as_strided as ast
    from itertools import product
    
    def norm_shape(shape):
        '''
        Normalize numpy array shapes so they're always expressed as a tuple, 
        even for one-dimensional shapes.
    
        Parameters
            shape - an int, or a tuple of ints
    
        Returns
            a shape tuple
        '''
        try:
            i = int(shape)
            return (i,)
        except TypeError:
            # shape was not a number
            pass
    
        try:
            t = tuple(shape)
            return t
        except TypeError:
            # shape was not iterable
            pass
    
        raise TypeError('shape must be an int, or a tuple of ints')
    
    
    def sliding_window(a,ws,ss = None,flatten = True):
        '''
        Return a sliding window over a in any number of dimensions
    
        Parameters:
            a  - an n-dimensional numpy array
            ws - an int (a is 1D) or tuple (a is 2D or greater) representing the size 
                 of each dimension of the window
            ss - an int (a is 1D) or tuple (a is 2D or greater) representing the 
                 amount to slide the window in each dimension. If not specified, it
                 defaults to ws.
            flatten - if True, all slices are flattened, otherwise, there is an 
                      extra dimension for each dimension of the input.
    
        Returns
            an array containing each n-dimensional window from a
    
        from http://www.johnvinyard.com/blog/?p=268
        '''
    
        if None is ss:
            # ss was not provided. the windows will not overlap in any direction.
            ss = ws
        ws = norm_shape(ws)
        ss = norm_shape(ss)
    
        # convert ws, ss, and a.shape to numpy arrays so that we can do math in every 
        # dimension at once.
        ws = np.array(ws)
        ss = np.array(ss)
        shape = np.array(a.shape)
    
    
        # ensure that ws, ss, and a.shape all have the same number of dimensions
        ls = [len(shape),len(ws),len(ss)]
        if 1 != len(set(ls)):
            raise ValueError(\
            'a.shape, ws and ss must all have the same length. They were %s' % str(ls))
    
        # ensure that ws is smaller than a in every dimension
        if np.any(ws > shape):
            raise ValueError('ws cannot be larger than a in any dimension. a.shape was %s and ws was %s' % (str(a.shape),str(ws)))
    
        # how many slices will there be in each dimension?
        newshape = norm_shape(((shape - ws) // ss) + 1)
        # the shape of the strided array will be the number of slices in each dimension
        # plus the shape of the window (tuple addition)
        newshape += norm_shape(ws)
        # the strides tuple will be the array's strides multiplied by step size, plus
        # the array's strides (tuple addition)
        newstrides = norm_shape(np.array(a.strides) * ss) + a.strides
        strided = ast(a,shape = newshape,strides = newstrides)
        if not flatten:
            return strided
    
        # Collapse strided so that it has one more dimension than the window.  I.e.,
        # the new array is a flat list of slices.
        meat = len(ws) if ws.shape else 0
        firstdim = (np.product(newshape[:-meat]),) if ws.shape else ()
        dim = firstdim + (newshape[-meat:])
        # remove any dimensions with size 1
        dim = filter(lambda i : i != 1,dim)
        return strided.reshape(dim)
    

    If you want to divide an image into four parts, you need to calculate the ws and ss paramaters. If both dimensions are divisible by two then ws and ss are the same value (ss defaults to ws when not specified). Numpy has the ability to treat array dimensions as (column, row) or (row, column) - I haven't changed any defaults and mine is (row, column). For an 18x26 picture, ws = (26/2, 18/2) - each window will be 13x9 and the adjacent windows are obtained by siliding the window by an equal amount, no overlap. If a dimension is not divisable by two, ss will also need to be determined and there will be some overlap in the windows. For an 18x33 image:

    >>> 
    >>> rows = 33
    >>> columns = 18
    >>> divisor = 2
    >>> col_size, col_overlap = divmod(columns, divisor)
    >>> row_size, row_overlap = divmod(rows, divisor)
    >>> ws = (row_size, col_size)
    >>> ss = (row_size - row_overlap, col_size - col_overlap)
    >>> ws, ss
    ((16, 9), (15, 9))
    >>> 
    

    For 3d windows (data from images with a color dimension) ws and ss need to have three dimensions. A 15x15 image will have 9 5x5x3 windows

    from PIL import Image
    import numpy as np
    
    img = Image.open('15by15.bmp')
    a = np.asarray(img)
    window_size = (5,5,3)
    windows = sliding_window(a, window_size)
    print windows.shape
    
    >>> (9, 5, 5, 3)
    
    for window in windows:
        print window.shape
    
    >>> (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3)
    

提交回复
热议问题