1

I have a 2D numpy array, and am trying to find the entries where it is equal to a 1D array, but the dimensions of these two arrays prohibit broadcasting. Specifically, my 2D array is like 300x400, and I want to see where it's equal to a 2 element row vector [1, -1].

I am trying to find the location of pixels in an image that are on the border of segmentations. This is denoted in this mask by a 1 being adjacent to the foreground and -1 to the background. So I need to find locations where [1,-1] occurs in the rows of the mask, let's say a.

I have tried a == [1,-1] but this just performs object-level equality and returns False.

I guess I could do this with

for i in range(a.shape[0]): 
    for j in range(a.shape[1]-1): 
        if a[i,j] == 1: 
            if a[i,j+1] == -1: 
                print(i)

but is there not some cute way to do this with a numpy method or something? I hate loops

3 Answers 3

1
arr = np.array([[1,1,-1],[1,-1,-1]])
arr_idx = (arr==1)[:,:-1] & (arr==-1)[:,1:]

Gives

>>> arr_idx
array([[False,  True],
       [ True, False]])

Which is an index for things that meet your criteria. Note that this is shaped with one fewer column than your input matrix (for obvious reasons).

You can add a column on one side or the other to change the indexing to either side of the pair you're looking for.

arr_idx = np.concatenate((np.zeros(shape=(2, 1), dtype=bool), arr_idx), axis=1)
>>> arr_idx
array([[False, False,  True],
       [False,  True, False]])

Sticking a new column on the left gives the index for the -1 component of the pair.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use a 2d cross-correlation for this.

There is a function in scipy for this: signal.correlate2d()

import numpy as np
from scipy import signal

arr = np.array([[1,1,-1],
                [1,-1,-1]])

# the pattern you are looking for, has to be 2d
krn = np.array([[1,-1]]) 

res = signal.correlate2d(arr, krn, mode='same')

print(res)

The result is

[[ 0  2 -1]
 [ 2  0 -1]]

it is the higher the better the match. In your case the 2 indicates the positions where your pattern is found.

Comments

0

Check for a 1 starting with the first index (drop the last as no -1 can be after it)

 tmp1 = a[:,0:-1]
 t1 = tmp1==1

t1 is True wherever the shifted a is 1 Check for -1 starting from the first till the last index

  tmp2 = a[:,1:]
  t2 = tmp2 ==-1

t1 and t2 contain True and False (shifted according to your goal) t1*t2 will give you True in the rows where your condition is fulfilled. Summing over the rows gives you a number above zero at every row index i

res = np.sum(t1*t2,axis=1) 
desired_Indices = np.where(res>0)

... everybody hates loops ;)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.