chimm
chimm

Reputation: 13

How to identify / find a 1D numpy array pattern in a 2D numpy array?

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

Upvotes: 1

Views: 390

Answers (3)

Joe
Joe

Reputation: 7121

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.

Upvotes: 0

Woma
Woma

Reputation: 101

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 ;)

Upvotes: 0

CJR
CJR

Reputation: 3985

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.

Upvotes: 1

Related Questions