5

I'd like to make a local mean filter of an image stored as a numpy array. The image has some missing pixels near the edges, represented with a valid mask (a bool array).

I could use skimage.filters.rank, but my images are outside of the [-1, 1] range, and for some reason scikit-image has that as a requirement.

There's also astropy.convolution, but it interpolates missing data. For a simple mean there's no need to interpolate. Just average only valid pixels. The input and output valid masks are the same.

Simply setting invalid pixels to zero is not an option as it would contaminate valid pixels averages nearby.

There's also this question, but it's not a duplicate since it asks about the more generic convolution (this is just averaging).

fouronnes
  • 3,838
  • 23
  • 41
  • Not sure about your approach, but the requirement of ```-1,1``` should not be a problem at all. Just scale your image to this format. mean-calculations are of float-math nature by concept and at some point you will surely need castings (if you were scared of losing information). You speficifally asked for this simple operation, but what's wrong with ```inpaint_biharmonic``` for example? – sascha Oct 26 '17 at 12:35
  • Neither scikit-image nor scipy.ndimage supports missing values in filters. That said, scipy.ndimage.generic_filter can be taught to do this, and can be made fast as shown here: https://ilovesymposia.com/2017/03/15/prettier-lowlevelcallables-with-numba-jit-and-decorators/ – Stefan van der Walt Oct 30 '17 at 19:28

1 Answers1

1

The approach that @stefan-van-der-walt is referring to, i.e. using a scipy.ndimage.generic_filter together with numpy.nanmean (not optimised for speed yet).

import numpy as np
from scipy.ndimage import generic_filter

def nanmean_filter(input_array, *args, **kwargs):
    """
    Arguments:
    ----------
    input_array : ndarray
        Input array to filter.
    size : scalar or tuple, optional
        See footprint, below
    footprint : array, optional
        Either `size` or `footprint` must be defined.  `size` gives
        the shape that is taken from the input array, at every element
        position, to define the input to the filter function.
        `footprint` is a boolean array that specifies (implicitly) a
        shape, but also which of the elements within this shape will get
        passed to the filter function.  Thus ``size=(n,m)`` is equivalent
        to ``footprint=np.ones((n,m))``.  We adjust `size` to the number
        of dimensions of the input array, so that, if the input array is
        shape (10,10,10), and `size` is 2, then the actual size used is
        (2,2,2).
    output : array, optional
        The `output` parameter passes an array in which to store the
        filter output. Output array should have different name as compared
        to input array to avoid aliasing errors.
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0
    origin : scalar, optional
        The `origin` parameter controls the placement of the filter.
        Default 0.0.

    See also:
    ---------
    scipy.ndimage.generic_filter
    """
    return generic_filter(input_array, function=np.nanmean, *args, **kwargs)
Paul Brodersen
  • 11,221
  • 21
  • 38