I have the following code:
Shouldn't the center entry in the result(at index [1,1]) be (2+4+5+5+7)/9 = int(2.55) = 2
?
I am imagining that the following happens when viewed as a convolution:
import numpy as np
from skimage.filters.rank import mean
from skimage.morphology import disk
A = np.array([[1,2,3], [4,5,6], [7,8,9]])
print("A: {}".format(A))
print("disk(1): {}".format(disk(1)))
print("mean: {}".format(mean(A, disk(1))))
Our kernel is K = 1/9(disk(1))
and the input image is A
, resulting in the convolution(with arrays seen as discrete functions): A * K
. Hence, I would expect that the center pixel in A
would be turned into (2+4+5+5+7)/9 = int(2.55) = 2
by the definition of convolutions. Why is this not true?
skimage.filters.rank.mean
computes the mean over the pixels with value 1 in the selection element rather than over the entire window. If you pass in disk(1)
as the selection element, then the neighbourhood is formed by just 5 pixels, not 9. Hence, the normalising factor for the convolution kernel should be 1/5 instead of 1/9.
In [77]: import numpy as np
...: from skimage.filters.rank import mean
...: from skimage.morphology import disk
...: from scipy.signal import convolve2d
In [78]: A = np.arange(1, 17).reshape(4, 4)
In [79]: A
Out[79]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
In [80]: d = disk(1)
In [81]: d
Out[81]:
array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]], dtype=uint8)
In [82]: mean(A, d)[1:-1, 1:-1]
Out[82]:
array([[ 6, 7],
[10, 11]], dtype=uint8)
In [83]: convolve2d(A, d, mode='valid')/d.sum()
Out[83]:
array([[ 6., 7.],
[10., 11.]])
Notice that in the code above only valid pixels are considered, i.e. those pixels for which the selection element is fully contained within the image.