Reputation: 2426
I have this code below which is almost working - only thing I need here is the output of the convolution has to be devided by 9 and rounded down. Is this somehow possible with convolve2d?
import scipy
import scipy.signal
import numpy as np
def boxBlur(image):
matrix = np.array(image)
W = np.array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
np.pad(matrix, 1, mode='constant')
return scipy.signal.convolve2d(matrix, W, mode='valid')
So for this example:
boxBlur([[1,1,1],[1,7,1],[1,1,1]])
The output right now is [[15]] but it should be [[1]] (15/9=1,6666 rounded down=1)
Is there a way to not only use the convolve image on the matrix, but also do something else.
Right now the way I managed the problem is to manually go over the array and devide every cell by 9 rounding it down
Upvotes: 2
Views: 1253
Reputation: 221564
That's called uniform filtetring, hence use SciPy's uniform_filter
, which should be faster as well -
from scipy.ndimage import uniform_filter
uniform_filter(image.astype(float))[1:-1,1:-1]
Sample run -
In [38]: np.random.seed(0)
...: image = np.random.randint(0,9,(7,7))
In [39]: boxBlur(image)/9.0
Out[39]:
array([[4.55555556, 5. , 5.55555556, 5.44444444, 5.11111111],
[4.44444444, 5. , 5. , 4.88888889, 4.22222222],
[4.33333333, 4.44444444, 3.44444444, 3.44444444, 3.77777778],
[2.22222222, 2.55555556, 2.88888889, 3.44444444, 3.55555556],
[2.44444444, 2.11111111, 2.44444444, 3.55555556, 4.33333333]])
In [40]: uniform_filter(image.astype(float))[1:-1,1:-1]
Out[40]:
array([[4.55555556, 5. , 5.55555556, 5.44444444, 5.11111111],
[4.44444444, 5. , 5. , 4.88888889, 4.22222222],
[4.33333333, 4.44444444, 3.44444444, 3.44444444, 3.77777778],
[2.22222222, 2.55555556, 2.88888889, 3.44444444, 3.55555556],
[2.44444444, 2.11111111, 2.44444444, 3.55555556, 4.33333333]])
Timings -
In [42]: np.random.seed(0)
...: image = np.random.randint(0,9,(7000,7000))
In [43]: %timeit boxBlur(image)/9.0
1 loop, best of 3: 2.11 s per loop
In [44]: %timeit uniform_filter(image.astype(float))[1:-1,1:-1]
1 loop, best of 3: 612 ms per loop
Rounding down
For rounding it down, with the original solution, it would be : boxBlur(image)//9
. The equivalent one here would be with floor-ing, so use np.floor()
, but that might have precision issues. So, we might instead use np.round
with a given number of decimal places for the precision and then floor with .astype(int)
-
n = 10 # number of decimal places for precision
np.around(uniform_filter(image.astype(float))[1:-1,1:-1], decimals=n).astype(int)
For an input with ints, another way could be to scale up by 9
and round and then floor -
np.round(uniform_filter(image.astype(float))[1:-1,1:-1]*9)//9
Upvotes: 1