Search code examples
pythonscikit-image

skimage mean is not returning expected result?


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?


Solution

  • 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.

    Demo

    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.