0

So I'm doing this course and there's this exercise where I have to blur an image using a 3x3 area of the array and swapping out all values to the average. So I wrote this function which I know is still does not work completely:

def replace_avg(img, block=3):
    x_dim, y_dim = img.shape
    for row in range(1,x_dim-block+2,3):
        for col in range(1,y_dim-block+2,3):
            img[row-(block-2):row+(block-1),col-(block-2):col+(block-1)] = np.average(img[row-(block-2):row+(block-1),col-(block-2):col+(block-1)])
    return img

My question is is there a more efficient way of looping through this array with a 3x3 filter using numpy?

menrva
  • 63
  • 7
  • 2
    lots of filter style questions that use numpy's stride_tricks https://stackoverflow.com/questions/4936620/using-strides-for-an-efficient-moving-average-filter – NaN Sep 03 '18 at 12:43
  • I would replace in your function `img[row-(block-2):row+(block-1),col-(block-2):col+(block-1)]` by `filtered[row, col]` where `filtered` is a initiated array of zeros the same shape as `img`, otherwise the average value for one pixel is function of the previously computed averages?... Also have a look at the numerous [`scipy.ndimage`](https://docs.scipy.org/doc/scipy/reference/ndimage.html) image filtering functions – xdze2 Sep 03 '18 at 12:46
  • Another method is to use `im2col` methods and transform the filtering operation into a matrix-vector multiplication: https://stackoverflow.com/questions/30109068/implement-matlabs-im2col-sliding-in-python/. – rayryeng Sep 04 '18 at 05:00

1 Answers1

0

The skimage package provides a function that does exactly what you want :

from skimage import transform
img_rescaled = transform.rescale(img,1/block)

Maybe you're looking for a solution specifically using Numpy, in that case you should look how that function is coded inside the skimage module

Lucas David
  • 102
  • 9