def kuwahara(arr, size=5): """ Kuwahara, a nonlinear 2D smoothing filter. http://subsurfwiki.org/wiki/Kuwahara_filter Args: arr (ndarray): a 2D array, such as a seismic horizon. size (int): the kernel size, e.g. 5 for 5x5. Should be odd, rounded up if not. Returns: ndarray: the resulting smoothed array. """ def func(this, s, k): """ Deal with this patch. """ t = this.reshape((s, s)) sub = np.array([t[:k, :k].flatten(), t[:k, k-1:].flatten(), t[k-1:, :k].flatten(), t[k-1:, k-1:].flatten()] ) select = sub[np.argmin(np.var(sub, axis=1))] return np.mean(select) arr = np.array(arr, dtype=np.float) if arr.ndim != 2: raise BrugesError("arr must have 2-dimensions") if not size // 2: size += 1 k = int(np.ceil(size / 2)) return scipy.ndimage.generic_filter(arr, func, size=size, extra_keywords={'s': size, 'k': k, } )
def snn(arr, size=5, include=True): """ Symmetric nearest neighbour, a nonlinear 2D smoothing filter. http://subsurfwiki.org/wiki/Symmetric_nearest_neighbour_filter Args: arr (ndarray): a 2D array, such as a seismic horizon. size (int): the kernel size, e.g. 5 for 5x5. Should be odd, rounded up if not. include (bool): whether to include the central pixel itself. Returns: ndarray: the resulting smoothed array. """ def func(this, pairs, include): """ Deal with this patch. """ centre = this[this.size // 2] select = [nearest(this[p], centre) for p in pairs] if include: select += [centre] return np.mean(select) arr = np.array(arr, dtype=np.float) if arr.ndim != 2: raise BrugesError("arr must have 2-dimensions") if not size // 2: size += 1 pairs = [[i, size**2 - 1 - i] for i in range(size**2 // 2)] return scipy.ndimage.generic_filter(arr, func, size=size, extra_keywords={ 'pairs': pairs, 'include': include })