2

I start with two images of the same size. I convert them to binary black/white numpy arrays (0 = black 1 = white). I'd like to find how many of the black pixels overlap (0 value at same position in both arrays).

I know how to do this with for loops, but I'm trying to learn how to use numpy properly, and I imagine there's a much better way of doing this.

A minimal example would be as follows:

ArrayA:

[ 1 1 0 ]
[ 1 0 0 ]
[ 0 1 1 ]

ArrayB:

[ 1 0 0 ]
[ 1 1 0 ]
[ 0 1 1 ]

I want to know how many times both arrays have a '0' value in the same position.

In this case, once in the 1st row 3rd column, once in the 2nd rows 3rd column, and once in the 3rd row 1st column. Total overlap of '0' values: 3.

I was thinking of something along the lines of

np.where(arrayA == 0 and arrayB == 0)

but that doesn't work.

Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Can you add a minimal and verifiable example to your question? – Mazdak Sep 16 '16 at 17:51
  • What did you try ? Did you check the numpy documentation ? I imagine it can be some boolean operation like these : https://docs.scipy.org/doc/numpy/reference/routines.bitwise.html#elementwise-bit-operations. Something like `invert(bitwise_and(x1, x2))` – Gabriel Glenn Sep 16 '16 at 17:57
  • @Kasramvd Of course. Added it to the original question. – Janek Nikicicz Sep 16 '16 at 17:58
  • If you are counting, you can use `np.count_nonzero` for efficient counting on the mask as created in the accepted solution. That would be much faster than using `.sum()`. Here's a runtime test I did recently on it - http://stackoverflow.com/a/38687313/3293881 – Divakar Sep 16 '16 at 18:17
  • @Divakar thanks for that extra info! – Janek Nikicicz Sep 16 '16 at 18:57

2 Answers2

4

You can use a simple comparison with a logical and:

>>> A
array([[1, 1, 0],
       [1, 0, 0],
       [0, 1, 1]])
>>> B
array([[1, 0, 0],
       [1, 1, 0],
       [0, 1, 1]])
>>> np.logical_and(A == 0, B == 0)
array([[False, False,  True],
       [False, False,  True],
       [ True, False, False]], dtype=bool)

And use np.where() and column_stack() in order to get the indices of the intended items:

>>> np.column_stack(np.where(np.logical_and(A == 0, B == 0)))
array([[0, 2],
       [1, 2],
       [2, 0]])

Or as a pretty Numpythonic way as suggested in comment use np.argwhere:

>>> np.argwhere(np.logical_and(A == 0, B == 0))
array([[0, 2],
       [1, 2],
       [2, 0]])
Mazdak
  • 105,000
  • 18
  • 159
  • 188
3

For the record, your original try just lacked the right operator and some parentesis:

np.where( (arrayA==0) & (arrayB==0))
jadsq
  • 3,033
  • 3
  • 20
  • 32