Source code for porespy.filters._fftmorphology

import numpy as np
from scipy.signal import fftconvolve

__all__ = [
    "fftmorphology",
]


[docs] def fftmorphology(im, strel, mode='opening'): r""" Perform morphological operations on binary images using fft approach for improved performance Parameters ---------- im : ndarray The binary image on which to perform the morphological operation strel : ndarray The structuring element to use. Must have the same dims as ``im``. mode : string The type of operation to perform. Options are 'dilation', 'erosion', 'opening' and 'closing'. Returns ------- image : ndarray A copy of the image with the specified moropholgical operation applied using the fft-based methods available in ``scipy.signal.fftconvolve``. Notes ----- This function uses ``scipy.signal.fftconvolve`` which *can* be more than 10x faster than the standard binary morphology operation in ``scipy.ndimage``. This speed up may not always be realized, depending on the scipy distribution used. Examples -------- >>> import porespy as ps >>> from numpy import array_equal >>> import scipy.ndimage as spim >>> from skimage.morphology import disk >>> im = ps.generators.blobs(shape=[100, 100], porosity=0.8) Check that erosion, dilation, opening, and closing are all the same as the ``scipy.ndimage`` functions: >>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='erosion') >>> temp = spim.binary_erosion(im, structure=disk(5)) >>> array_equal(result, temp) True >>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='dilation') >>> temp = spim.binary_dilation(im, structure=disk(5)) >>> array_equal(result, temp) True >>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='opening') >>> temp = spim.binary_opening(im, structure=disk(5)) >>> array_equal(result, temp) True >>> result = ps.filters.fftmorphology(im, strel=disk(5), mode='closing') >>> temp = spim.binary_closing(im, structure=disk(5)) >>> array_equal(result, temp) True """ def erode(im, strel): t = fftconvolve(im, strel, mode='same') > (strel.sum() - 0.1) return t def dilate(im, strel): t = fftconvolve(im, strel, mode='same') > 0.1 return t im = np.squeeze(im) # Perform erosion and dilation # The array must be padded with 0's so it works correctly at edges temp = np.pad(array=im, pad_width=1, mode='constant', constant_values=0) if mode.startswith('ero'): temp = erode(temp, strel) if mode.startswith('dila'): temp = dilate(temp, strel) # Remove padding from resulting image if im.ndim == 2: result = temp[1:-1, 1:-1] elif im.ndim == 3: result = temp[1:-1, 1:-1, 1:-1] # Perform opening and closing if mode.startswith('open'): temp = fftmorphology(im=im, strel=strel, mode='erosion') result = fftmorphology(im=temp, strel=strel, mode='dilation') if mode.startswith('clos'): temp = fftmorphology(im=im, strel=strel, mode='dilation') result = fftmorphology(im=temp, strel=strel, mode='erosion') return result