Reputation: 21914
I'm looking to do some basic clustering on a boolean numpy array and I'm basically just trying to do 2d averaging with a mask, but I feel like there must be a better solution than what I've got, since it's slow and inelegant:
def grab_window(location, array, window=(3,3)):
minimums = [min(0, i-a) for i, a in zip(location, window)]
maximums = [(i + a) for i, a in zip(location, window)]
answer = array
for i, _ in enumerate(location):
answer = answer[slice(minimums[i],maximums[i])]
return answer
And then I basically just iterate through the original array, multiplying each window by a kernel, and returning the mean of the modified window.
It seems like there must be a filter or something similar that would have the same effect, but I haven't been able to find one thus far.
edit: location is a tuple
of a form similar to window.
For instance, if we were to do the simplest version of this, with a uniform 1-ply mask I would be looking for something along these lines:
import numpy as np
test = np.arange(0,24).reshape(6, 4)
footprint = [
[1,1,1],
[1,0,1],
[1,1,1]
]
some_function(test, footprint)
array([[ 1, 2, 3, 4],
[ 4, 5, 6, 6],
[ 8, 9, 10, 10],
[12, 13, 14, 14],
[16, 17, 18, 18],
[18, 19, 20, 21]])
Upvotes: 1
Views: 212
Reputation: 21914
Turns out scipy
totally has a function that already does this. generic_filter
actually does exactly this in a much more stable way as mentioned in How to apply ndimage.generic_filter()
Example:
def some_avg(values):
return values.mean()
footprint = np.array([
[1,1,1],
[1,0,1],
[1,1,1]
])
test = test = np.arange(0,24).reshape(6, 4)
scipy.ndimage.filters.generic_filter(test, some_avg, footprint=footprint)
array([[ 1, 2, 3, 4],
[ 4, 5, 6, 6],
[ 8, 9, 10, 10],
[12, 13, 14, 14],
[16, 17, 18, 18],
[18, 19, 20, 21]])
Upvotes: 1