Pixel neighbors in 2d array (image) using Python Pixel neighbors in 2d array (image) using Python numpy numpy

Pixel neighbors in 2d array (image) using Python


Have a look at scipy.ndimage.generic_filter.

As an example:

import numpy as npimport scipy.ndimage as ndimagedef test_func(values):    print(values)    return values.sum()x = np.array([[1,2,3],[4,5,6],[7,8,9]])footprint = np.array([[1,1,1],                      [1,0,1],                      [1,1,1]])results = ndimage.generic_filter(x, test_func, footprint=footprint)

By default, it will "reflect" the values at the boundaries. You can control this with the mode keyword argument.

However, if you're wanting to do something like this, there's a good chance that you can express your problem as a convolution of some sort. If so, it will be much faster to break it down into convolutional steps and use more optimized functions (e.g. most of scipy.ndimage).


EDIT: ah crap, my answer is just writing im[i-d:i+d+1, j-d:j+d+1].flatten() but written in a incomprehensible way :)


The good old sliding window trick may help here:

import numpy as npfrom numpy.lib.stride_tricks import as_strideddef sliding_window(arr, window_size):    """ Construct a sliding window view of the array"""    arr = np.asarray(arr)    window_size = int(window_size)    if arr.ndim != 2:        raise ValueError("need 2-D input")    if not (window_size > 0):        raise ValueError("need a positive window size")    shape = (arr.shape[0] - window_size + 1,             arr.shape[1] - window_size + 1,             window_size, window_size)    if shape[0] <= 0:        shape = (1, shape[1], arr.shape[0], shape[3])    if shape[1] <= 0:        shape = (shape[0], 1, shape[2], arr.shape[1])    strides = (arr.shape[1]*arr.itemsize, arr.itemsize,               arr.shape[1]*arr.itemsize, arr.itemsize)    return as_strided(arr, shape=shape, strides=strides)def cell_neighbors(arr, i, j, d):    """Return d-th neighbors of cell (i, j)"""    w = sliding_window(arr, 2*d+1)    ix = np.clip(i - d, 0, w.shape[0]-1)    jx = np.clip(j - d, 0, w.shape[1]-1)    i0 = max(0, i - d - ix)    j0 = max(0, j - d - jx)    i1 = w.shape[2] - max(0, d - i + ix)    j1 = w.shape[3] - max(0, d - j + jx)    return w[ix, jx][i0:i1,j0:j1].ravel()x = np.arange(8*8).reshape(8, 8)print xfor d in [1, 2]:    for p in [(0,0), (0,1), (6,6), (8,8)]:        print "-- d=%d, %r" % (d, p)        print cell_neighbors(x, p[0], p[1], d=d)

Didn't do any timings here, but it's possible this version has reasonable performance.

For more info, search the net with phrases "rolling window numpy" or "sliding window numpy".


I don't know about any library functions for this, but you can easily write something like this yourself using the great slicing functionality of numpy:

import numpy as npdef neighbors(im, i, j, d=1):    n = im[i-d:i+d+1, j-d:j+d+1].flatten()    # remove the element (i,j)    n = np.hstack((b[:len(b)//2],b[len(b)//2+1:] ))    return n

Of course you should do some range checks to avoid out-of-bounds access.