4

Past midnight and maybe someone has an idea how to tackle a problem of mine. I want to count the number of adjacent cells (which means the number of array fields with other values eg. zeroes in the vicinity of array values) as sum for each valid value!.

Example:

import numpy, scipy
s = ndimage.generate_binary_structure(2,2) # Structure can vary
a = numpy.zeros((6,6), dtype=numpy.int) # Example array
a[2:4, 2:4] = 1;a[2,4] = 1 # with example value structure
print a 
>[[0 0 0 0 0 0]
  [0 0 0 0 0 0]
  [0 0 1 1 1 0]
  [0 0 1 1 0 0]
  [0 0 0 0 0 0]
  [0 0 0 0 0 0]]
# The value at position [2,4] is surrounded by 6 zeros, while the one at
# position [2,2] has 5 zeros in the vicinity if 's' is the assumed binary structure. 
# Total sum of surrounding zeroes is therefore sum(5+4+6+4+5) == 24

How can i count the number of zeroes in such way if the structure of my values vary? I somehow believe to must take use of the binary_dilation function of SciPy, which is able to enlarge the value structure, but simple counting of overlaps can't lead me to the correct sum or does it?

print ndimage.binary_dilation(a,s).astype(a.dtype)
[[0 0 0 0 0 0]
 [0 1 1 1 1 1]
 [0 1 1 1 1 1]
 [0 1 1 1 1 1]
 [0 1 1 1 1 0]
 [0 0 0 0 0 0]]
1
  • I'm not entirely clear on what you want here. So given a position, you want to know the number of neighbors whose value == 0? If you know the shape of the array (to find discover the edges) you can use simple math... annoying, time consuming (to write and process), but pretty straight forward. Commented Sep 27, 2012 at 2:16

2 Answers 2

9

Use a convolution to count neighbours:

import numpy
import scipy.signal

a = numpy.zeros((6,6), dtype=numpy.int) # Example array
a[2:4, 2:4] = 1;a[2,4] = 1 # with example value structure

b = 1-a
c = scipy.signal.convolve2d(b, numpy.ones((3,3)), mode='same')

print numpy.sum(c * a)

b = 1-a allows us to count each zero while ignoring the ones.

We convolve with a 3x3 all-ones kernel, which sets each element to the sum of it and its 8 neighbouring values (other kernels are possible, such as the + kernel for only orthogonally adjacent values). With these summed values, we mask off the zeros in the original input (since we don't care about their neighbours), and sum over the whole array.

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

2 Comments

I was just about to post almost the same answer: (a * ndimage.convolve((a == 0).astype(int), s)).sum()
yeah, that exactly want i wanted. Great!
1

I think you already got it. after dilation, the number of 1 is 19, minus 5 of the starting shape, you have 14. which is the number of zeros surrounding your shape. Your total of 24 has overlaps.

2 Comments

This can't be the right answer. Consider a 1 surrounded by 8 zeros. The correct answer is 8, but you will see 9 1s in the output, and your approach would add one to give 10.
Oh, sorry. You were counting surrounding zeros without overlaps. I think the poster wanted overlaps. But your solution is right for counting without overlap.

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.