Skip to content
Advertisement

How to make a nxn filter to perform custom opertions in image array?

I am working with various images and I wanted to implement a method but I have no idea where to start. So I am looking forward to some suggestions.

My idea as a method is to take an image array and after selecting a region of interest and then we say the selectedROI is 10×10 region of pixels as a array. Then how can I make a filter of size say for example 2×5 and after making the 2×5 filter how to move the filter throughout the selectedROI and comparing each 2×5 filters for min, max & mean values.

I have successfully achieved the selecting the ROI and printing the selecedROI as a array. All I want to do in simple words is to select a bunch of pixels and compare the bunch with another bunch within the whole selectedROI. How is it possible.

Advertisement

Answer

It sounds like you have an array of pixels with shape (10, 10), and want to slide a window of shape (2, 5) across the array, performing an operation at each position.

NumPy has operations to help with this (see here: https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html), however the documentation says sliding_window_view is generic and thus nonoptimal for your case. They suggest using scipy.ndimage operations instead, which I have shown examples of below. https://docs.scipy.org/doc/scipy/reference/reference/generated/scipy.ndimage.generic_filter.html

To start, I have imported the packages and defined a 10×10 array and 2×5 filter size.

>>> import numpy as np
>>> from scipy.ndimage import generic_filter
>>> selectedROI = np.array(range(100)).reshape((10, 10))
>>> selectedROI
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]])
>>> filter_size = (2, 5)

Any function can be applied in sliding-window fashion with generic_filter (np.average used here). Variables a,b,c,d were chosen because generic_filter produces values for all positions in your input array, including positions where the window does not fall entirely within the input array. For an explanation of the “or None” in the slicing, see here: numpy negative indexing a[:-0]

>>> a = filter_size[0]//2
>>> b = (1 - filter_size[0]%2) - (filter_size[0]//2)
>>> c = filter_size[1]//2
>>> d = (1 - filter_size[1]%2) - (filter_size[1]//2)
>>> generic_filter(selectedROI, np.average, filter_size)[a:b or None, c:d or None]
array([[ 7,  8,  9, 10, 11, 12],
       [17, 18, 19, 20, 21, 22],
       [27, 28, 29, 30, 31, 32],
       [37, 38, 39, 40, 41, 42],
       [47, 48, 49, 50, 51, 52],
       [57, 58, 59, 60, 61, 62],
       [67, 68, 69, 70, 71, 72],
       [77, 78, 79, 80, 81, 82],
       [87, 88, 89, 90, 91, 92]])

You can use other functions, such as np.min and np.max for your use case, or write your own custom functions as shown here: How do I use scipy.ndimage.filters.gereric_filter?

>>> generic_filter(selectedROI, np.min, filter_size)[a:b or None, c:d or None]
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55],
       [60, 61, 62, 63, 64, 65],
       [70, 71, 72, 73, 74, 75],
       [80, 81, 82, 83, 84, 85]])
>>> generic_filter(selectedROI, np.max, filter_size)[a:b or None, c:d or None]
array([[14, 15, 16, 17, 18, 19],
       [24, 25, 26, 27, 28, 29],
       [34, 35, 36, 37, 38, 39],
       [44, 45, 46, 47, 48, 49],
       [54, 55, 56, 57, 58, 59],
       [64, 65, 66, 67, 68, 69],
       [74, 75, 76, 77, 78, 79],
       [84, 85, 86, 87, 88, 89],
       [94, 95, 96, 97, 98, 99]])

These examples used 2D arrays for clarity, but the operations should extend to 3D pixel arrays.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement