Commoner
Commoner

Reputation: 1768

Replace elements in numpy matrix by taking average of neighboring elements

I am trying to replace values in a numpy matrix which are below a certain threshold with the average of the values of matrix cells which are near the concerned cells (i.e. the ones with values below the threshold.

As an example, let's consider this 10*10 matrix (say matrx):

matrx = np.array([[1,4,9,2,2,5,1,1,9,1],[2,4,3,5,2,2,1,2,1,1],
              [3,4,-2,-3,4,2,3,5,1,2],[2,3,-3,-5,3,3,7,8,-4,1],[3,4,2,3,4,2,3,7,3,2],
             [1,4,9,3,4,3,3,2,9,4],[2,1,3,5,2,2,3,2,3,3],
             [3,6,8,3,7,2,3,5,3,2],[5,-2,-3,5,2,3,7,8,4,3],[4,-2,-3,1,1,2,3,7,3,5]])

print matrx
[[ 1  4  9  2  2  5  1  1  9  1]
 [ 2  4  3  5  2  2  1  2  1  1]
 [ 3  4 -2 -3  4  2  3  5  1  2]
 [ 2  3 -3 -5  3  3  7  8 -4  1]
 [ 3  4  2  3  4  2  3  7  3  2]
 [ 1  4  9  3  4  3  3  2  9  4]
 [ 2  1  3  5  2  2  3  2  3  3]
 [ 3  6  8  3  7  2  3  5  3  2]
 [ 5 -2 -3  5  2  3  7  8  4  3]
 [ 4 -2 -3  1  1  2  3  7  3  5]]

And, let's suppose that the threshold is zero. Presently, I am finding the (2d) locations of the cells where the values are below zero using the following:

threshold = 0
mark_x = np.where( matrx<0 )[0]
mark_y = np.where( matrx<0 )[1]

Below, is a picture of the aforesaid matrix. enter image description here

In my work, cells whose values are below the threshold mostly occur in blocks (as one can see in the matrix). At present, I am replacing all the cells where the values are below the threshold with the mean of the matrix (matrx).

But, I would like do better and replace the values of elements which are below the threshold with the mean values of good neighboring elements adjoining the concerned cells. Here, "good" neighboring cells will be those neighboring cells whose values are above the threshold. I am a bit flexible with the selection of sizes of neighboring cells around cells which are below the threshold (the size of the neighboring cell will be the same for each cell which is below the threshold.)

The picture below gives a pictorial idea of what I want to achieve. In the picture given below, the red boundaries around each blob with values below the threshold, represent nearest neighbors. Inside each of these bounded boxes, cells with red tick marks are the ones whose average we will like to consider while replacing the values of the cells whose values are below the threshold. enter image description here

When we find cells with values below the threshold, we are expecting to see blobs of unequal sizes; and also blobs which are near the boundary.

In Python, what is the best way to achieve this desired aim? I will very much appreciate any answer.

Upvotes: 5

Views: 2356

Answers (1)

lenik
lenik

Reputation: 23556

This might work, however, you may prefer to keep the original matrix and make changes to a copy to make it more precise:

for x, y in zip(mark_x, mark_y) :
    slice = matrx[max(0, x-2):x+2, max(0,y-2):y+2] # assuming you want 5x5 square
    matrx[x,y] = np.mean([i for i in slice.flatten() if i > 0])  # threshold is 0

gives the result:

array([[1, 4, 9, 2, 2, 5, 1, 1, 9, 1],
       [2, 4, 3, 5, 2, 2, 1, 2, 1, 1],
       [3, 4, 3, 3, 4, 2, 3, 5, 1, 2],
       [2, 3, 3, 3, 3, 3, 7, 8, 3, 1],
       [3, 4, 2, 3, 4, 2, 3, 7, 3, 2],
       [1, 4, 9, 3, 4, 3, 3, 2, 9, 4],
       [2, 1, 3, 5, 2, 2, 3, 2, 3, 3],
       [3, 6, 8, 3, 7, 2, 3, 5, 3, 2],
       [5, 4, 3, 5, 2, 3, 7, 8, 4, 3],
       [4, 4, 4, 1, 1, 2, 3, 7, 3, 5]])

Upvotes: 5

Related Questions