def gaussian_filter(input, sigma, order = 0, output = None, mode = "reflect", cval = 0.0): """Multi-dimensional Gaussian filter. The standard-deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. The order of the filter along each axis is given as a sequence of integers, or as a single number. An order of 0 corresponds to convolution with a Gaussian kernel. An order of 1, 2, or 3 corresponds to convolution with the first, second or third derivatives of a Gaussian. Higher order derivatives are not implemented.' Note: The multi-dimensional filter is implemented as a sequence of one-dimensional convolution filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. """ input = numpy.asarray(input) output, return_value = _ni_support._get_output(output, input) orders = _ni_support._normalize_sequence(order, input.ndim) sigmas = _ni_support._normalize_sequence(sigma, input.ndim) axes = range(input.ndim) axes = [(axes[ii], sigmas[ii], orders[ii]) for ii in range(len(axes)) if sigmas[ii] > 1e-15] if len(axes) > 0: for axis, sigma, order in axes: gaussian_filter1d(input, sigma, axis, order, output, mode, cval) input = output else: output[...] = input[...] return return_value
def uniform_filter(input, size = 3, output = None, mode = "reflect", cval = 0.0, origin = 0): """Multi-dimensional uniform filter. The sizes of the uniform filter are given for each axis as a sequence, or as a single number, in which case the size is equal for all axes. The multi-dimensional filter is implemented as a sequence of one-dimensional uniform filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. """ input = numpy.asarray(input) output, return_value = _ni_support._get_output(output, input) sizes = _ni_support._normalize_sequence(size, input.ndim) origins = _ni_support._normalize_sequence(origin, input.ndim) axes = range(input.ndim) axes = [(axes[ii], sizes[ii], origins[ii]) for ii in range(len(axes)) if sizes[ii] > 1] if len(axes) > 0: for axis, size, origin in axes: uniform_filter1d(input, int(size), axis, output, mode, cval, origin) input = output else: output[...] = input[...] return return_value
def uniform_filter(input, size=3, output=None, mode="reflect", cval=0.0, origin=0): """Multi-dimensional uniform filter. The sizes of the uniform filter are given for each axis as a sequence, or as a single number, in which case the size is equal for all axes. The multi-dimensional filter is implemented as a sequence of one-dimensional uniform filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. """ input = numarray.asarray(input) output, return_value = _ni_support._get_output(output, input) sizes = _ni_support._normalize_sequence(size, input.rank) origins = _ni_support._normalize_sequence(origin, input.rank) axes = range(input.rank) axes = [(axes[ii], sizes[ii], origins[ii]) for ii in range(len(axes)) if sizes[ii] > 1] if len(axes) > 0: for axis, size, origin in axes: uniform_filter1d(input, int(size), axis, output, mode, cval, origin) input = output else: output[...] = input[...] return return_value
def binary_hit_or_miss(input, structure1 = None, structure2 = None, output = None, origin1 = 0, origin2 = None): """Multi-dimensional binary hit-or-miss transform. An output array can optionally be provided. The origin parameters controls the placement of the structuring elements. If the first structuring element is not given one is generated with a squared connectivity equal to one. If the second structuring element is not provided, it set equal to the inverse of the first structuring element. If the origin for the second structure is equal to None it is set equal to the origin of the first. """ input = numpy.asarray(input) if structure1 is None: structure1 = generate_binary_structure(input.ndim, 1) if structure2 is None: structure2 = numpy.logical_not(structure1) origin1 = _ni_support._normalize_sequence(origin1, input.ndim) if origin2 is None: origin2 = origin1 else: origin2 = _ni_support._normalize_sequence(origin2, input.ndim) tmp1 = _binary_erosion(input, structure1, 1, None, None, 0, origin1, 0, False) inplace = isinstance(output, numpy.ndarray) result = _binary_erosion(input, structure2, 1, None, output, 0, origin2, 1, False) if inplace: numpy.logical_not(output, output) numpy.logical_and(tmp1, output, output) else: numpy.logical_not(result, result) return numpy.logical_and(tmp1, result)
def _min_or_max_filter(input, size, footprint, structure, output, mode, cval, origin, minimum): if structure is None: if footprint is None: if size is None: raise RuntimeError, "no footprint provided" separable = True else: footprint = numarray.asarray(footprint, numarray.Bool) if numarray.alltrue(numarray.ravel(footprint)): size = footprint.shape footprint = None separable = True else: separable = False else: structure = numarray.asarray(structure, type=numarray.Float64) separable = False if footprint is None: footprint = numarray.ones(structure.shape, numarray.Bool) else: footprint = numarray.asarray(footprint, numarray.Bool) input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, 'Complex type not supported' output, return_value = _ni_support._get_output(output, input) origins = _ni_support._normalize_sequence(origin, input.rank) if separable: sizes = _ni_support._normalize_sequence(size, input.rank) axes = range(input.rank) axes = [(axes[ii], sizes[ii], origins[ii]) for ii in range(len(axes)) if sizes[ii] > 1] if minimum: filter = minimum_filter1d else: filter = maximum_filter1d if len(axes) > 0: for axis, size, origin in axes: filter(input, int(size), axis, output, mode, cval, origin) input = output else: output[...] = input[...] else: fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.rank: raise RuntimeError, 'footprint array has incorrect shape.' for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, 'invalid origin' if not footprint.iscontiguous(): footprint = footprint.copy() if structure is not None: if len(structure.shape) != input.rank: raise RuntimeError, 'structure array has incorrect shape' if not structure.iscontiguous(): structure = structure.copy() mode = _ni_support._extend_mode_to_code(mode) _nd_image.min_or_max_filter(input, footprint, structure, output, mode, cval, origins, minimum) return return_value
def _rank_filter(input, rank, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0, operation='rank'): input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, 'Complex type not supported' origins = _ni_support._normalize_sequence(origin, input.rank) if footprint == None: if size == None: raise RuntimeError, "no footprint or filter size provided" sizes = _ni_support._normalize_sequence(size, input.rank) footprint = numarray.ones(sizes, type=numarray.Bool) else: footprint = numarray.asarray(footprint, type=numarray.Bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.rank: raise RuntimeError, 'filter footprint array has incorrect shape.' for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, 'invalid origin' if not footprint.iscontiguous(): footprint = footprint.copy() filter_size = numarray.where(footprint, 1, 0).sum() if operation == 'median': rank = filter_size // 2 elif operation == 'percentile': percentile = rank if percentile < 0.0: percentile += 100.0 if percentile < 0 or percentile > 100: raise RuntimeError, 'invalid percentile' if percentile == 100.0: rank = filter_size - 1 else: rank = int(float(filter_size) * percentile / 100.0) if rank < 0: rank += filter_size if rank < 0 or rank >= filter_size: raise RuntimeError, 'rank not within filter footprint size' if rank == 0: return minimum_filter(input, None, footprint, output, mode, cval, origin) elif rank == filter_size - 1: return maximum_filter(input, None, footprint, output, mode, cval, origin) else: output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.rank_filter(input, rank, footprint, output, mode, cval, origins) return return_value
def _min_or_max_filter(input, size, footprint, structure, output, mode, cval, origin, minimum): if structure is None: if footprint is None: if size is None: raise RuntimeError, "no footprint provided" separable = True else: footprint = numarray.asarray(footprint, numarray.Bool) if numarray.alltrue(numarray.ravel(footprint)): size = footprint.shape footprint = None separable = True else: separable = False else: structure = numarray.asarray(structure, type=numarray.Float64) separable = False if footprint is None: footprint = numarray.ones(structure.shape, numarray.Bool) else: footprint = numarray.asarray(footprint, numarray.Bool) input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, "Complex type not supported" output, return_value = _ni_support._get_output(output, input) origins = _ni_support._normalize_sequence(origin, input.rank) if separable: sizes = _ni_support._normalize_sequence(size, input.rank) axes = range(input.rank) axes = [(axes[ii], sizes[ii], origins[ii]) for ii in range(len(axes)) if sizes[ii] > 1] if minimum: filter = minimum_filter1d else: filter = maximum_filter1d if len(axes) > 0: for axis, size, origin in axes: filter(input, int(size), axis, output, mode, cval, origin) input = output else: output[...] = input[...] else: fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.rank: raise RuntimeError, "footprint array has incorrect shape." for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, "invalid origin" if not footprint.iscontiguous(): footprint = footprint.copy() if structure is not None: if len(structure.shape) != input.rank: raise RuntimeError, "structure array has incorrect shape" if not structure.iscontiguous(): structure = structure.copy() mode = _ni_support._extend_mode_to_code(mode) _nd_image.min_or_max_filter(input, footprint, structure, output, mode, cval, origins, minimum) return return_value
def generic_filter(input, function, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0, extra_arguments=(), extra_keywords=None): """Calculates a multi-dimensional filter using the given function. At each element the provided function is called. The input values within the filter footprint at that element are passed to the function as a 1D array of double values. Parameters ---------- %(input)s function : callable function to apply at each element %(size_foot)s %(output)s %(mode)s %(cval)s %(origin)s %(extra_arguments)s %(extra_keywords)s """ if extra_keywords is None: extra_keywords = {} input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' origins = _ni_support._normalize_sequence(origin, input.ndim) if footprint is None: if size is None: raise RuntimeError, "no footprint or filter size provided" sizes = _ni_support._normalize_sequence(size, input.ndim) footprint = numpy.ones(sizes, dtype=bool) else: footprint = numpy.asarray(footprint) footprint = footprint.astype(bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.ndim: raise RuntimeError, 'filter footprint array has incorrect shape.' for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, 'invalid origin' if not footprint.flags.contiguous: footprint = footprint.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.generic_filter(input, function, footprint, output, mode, cval, origins, extra_arguments, extra_keywords) return return_value
def gaussian_filter(input, sigma, order=0, output=None, mode="reflect", cval=0.0): """Multi-dimensional Gaussian filter. Parameters ---------- %(input)s sigma : scalar or sequence of scalars standard deviation for Gaussian kernel. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. order : {0, 1, 2, 3} or sequence from same set, optional The order of the filter along each axis is given as a sequence of integers, or as a single number. An order of 0 corresponds to convolution with a Gaussian kernel. An order of 1, 2, or 3 corresponds to convolution with the first, second or third derivatives of a Gaussian. Higher order derivatives are not implemented %(output)s %(mode)s %(cval)s Notes ----- The multi-dimensional filter is implemented as a sequence of one-dimensional convolution filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. """ input = numpy.asarray(input) output, return_value = _ni_support._get_output(output, input) orders = _ni_support._normalize_sequence(order, input.ndim) if not set(orders).issubset(set(range(4))): raise ValueError('Order outside 0..4 not implemented') sigmas = _ni_support._normalize_sequence(sigma, input.ndim) axes = range(input.ndim) axes = [(axes[ii], sigmas[ii], orders[ii]) for ii in range(len(axes)) if sigmas[ii] > 1e-15] if len(axes) > 0: for axis, sigma, order in axes: gaussian_filter1d(input, sigma, axis, order, output, mode, cval) input = output else: output[...] = input[...] return return_value
def _rank_filter(input, rank, size = None, footprint = None, output = None, mode = "reflect", cval = 0.0, origin = 0, operation = 'rank'): input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') origins = _ni_support._normalize_sequence(origin, input.ndim) if footprint is None: if size is None: raise RuntimeError("no footprint or filter size provided") sizes = _ni_support._normalize_sequence(size, input.ndim) footprint = numpy.ones(sizes, dtype=bool) else: footprint = numpy.asarray(footprint, dtype=bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.ndim: raise RuntimeError('filter footprint array has incorrect shape.') for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError('invalid origin') if not footprint.flags.contiguous: footprint = footprint.copy() filter_size = numpy.where(footprint, 1, 0).sum() if operation == 'median': rank = filter_size // 2 elif operation == 'percentile': percentile = rank if percentile < 0.0: percentile += 100.0 if percentile < 0 or percentile > 100: raise RuntimeError('invalid percentile') if percentile == 100.0: rank = filter_size - 1 else: rank = int(float(filter_size) * percentile / 100.0) if rank < 0: rank += filter_size if rank < 0 or rank >= filter_size: raise RuntimeError('rank not within filter footprint size') if rank == 0: return minimum_filter(input, None, footprint, output, mode, cval, origin) elif rank == filter_size - 1: return maximum_filter(input, None, footprint, output, mode, cval, origin) else: output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.rank_filter(input, rank, footprint, output, mode, cval, origins) return return_value
def generic_filter(input, function, size = None, footprint = None, output = None, mode = "reflect", cval = 0.0, origin = 0, extra_arguments = (), extra_keywords = None): """Calculates a multi-dimensional filter using the given function. At each element the provided function is called. The input values within the filter footprint at that element are passed to the function as a 1D array of double values. Parameters ---------- %(input)s function : callable function to apply at each element %(size_foot)s %(output)s %(mode)s %(cval)s %(origin)s %(extra_arguments)s %(extra_keywords)s """ if extra_keywords is None: extra_keywords = {} input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') origins = _ni_support._normalize_sequence(origin, input.ndim) if footprint is None: if size is None: raise RuntimeError("no footprint or filter size provided") sizes = _ni_support._normalize_sequence(size, input.ndim) footprint = numpy.ones(sizes, dtype=bool) else: footprint = numpy.asarray(footprint) footprint = footprint.astype(bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.ndim: raise RuntimeError('filter footprint array has incorrect shape.') for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError('invalid origin') if not footprint.flags.contiguous: footprint = footprint.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.generic_filter(input, function, footprint, output, mode, cval, origins, extra_arguments, extra_keywords) return return_value
def generic_filter( input, function, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0, extra_arguments=(), extra_keywords={}, ): """Calculates a multi-dimensional filter using the given function. At each element the provided function is called. The input values within the filter footprint at that element are passed to the function as a 1D array of double values. Either a size or a footprint with the filter must be provided. An output array can optionally be provided. The origin parameter controls the placement of the filter. The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. The extra_arguments and extra_keywords arguments can be used to pass extra arguments and keywords that are passed to the function at each call.""" input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, "Complex type not supported" origins = _ni_support._normalize_sequence(origin, input.rank) if footprint == None: if size == None: raise RuntimeError, "no footprint or filter size provided" sizes = _ni_support._normalize_sequence(size, input.rank) footprint = numarray.ones(size, type=numarray.Bool) else: footprint = numarray.asarray(footprint, type=numarray.Bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.rank: raise RuntimeError, "filter footprint array has incorrect shape." for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, "invalid origin" if not footprint.iscontiguous(): footprint = footprint.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.generic_filter(input, function, footprint, output, mode, cval, origins, extra_arguments, extra_keywords) return return_value
def generic_filter(input, function, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0, extra_arguments=(), extra_keywords={}): """Calculates a multi-dimensional filter using the given function. At each element the provided function is called. The input values within the filter footprint at that element are passed to the function as a 1D array of double values. Either a size or a footprint with the filter must be provided. An output array can optionally be provided. The origin parameter controls the placement of the filter. The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. The extra_arguments and extra_keywords arguments can be used to pass extra arguments and keywords that are passed to the function at each call.""" input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' origins = _ni_support._normalize_sequence(origin, input.ndim) if footprint == None: if size == None: raise RuntimeError, "no footprint or filter size provided" sizes = _ni_support._normalize_sequence(size, input.ndim) footprint = numpy.ones(size, dtype=bool) else: footprint = numpy.asarray(footprint) footprint = footprint.astype(bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.ndim: raise RuntimeError, 'filter footprint array has incorrect shape.' for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, 'invalid origin' if not footprint.flags.contiguous: footprint = footprint.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.generic_filter(input, function, footprint, output, mode, cval, origins, extra_arguments, extra_keywords) return return_value
def _rank_filter( input, rank, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0, operation="rank" ): input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, "Complex type not supported" origins = _ni_support._normalize_sequence(origin, input.rank) if footprint == None: if size == None: raise RuntimeError, "no footprint or filter size provided" sizes = _ni_support._normalize_sequence(size, input.rank) footprint = numarray.ones(sizes, type=numarray.Bool) else: footprint = numarray.asarray(footprint, type=numarray.Bool) fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.rank: raise RuntimeError, "filter footprint array has incorrect shape." for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError, "invalid origin" if not footprint.iscontiguous(): footprint = footprint.copy() filter_size = numarray.where(footprint, 1, 0).sum() if operation == "median": rank = filter_size // 2 elif operation == "percentile": percentile = rank if percentile < 0.0: percentile += 100.0 if percentile < 0 or percentile > 100: raise RuntimeError, "invalid percentile" if percentile == 100.0: rank = filter_size - 1 else: rank = int(float(filter_size) * percentile / 100.0) if rank < 0: rank += filter_size if rank < 0 or rank >= filter_size: raise RuntimeError, "rank not within filter footprint size" if rank == 0: return minimum_filter(input, None, footprint, output, mode, cval, origin) elif rank == filter_size - 1: return maximum_filter(input, None, footprint, output, mode, cval, origin) else: output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.rank_filter(input, rank, footprint, output, mode, cval, origins) return return_value
def _correlate_or_convolve(input, weights, output, mode, cval, origin, convolution): input = numpy.asarray(input) if numpy.iscomplexobj(int): raise TypeError('Complex type not supported') origins = _ni_support._normalize_sequence(origin, input.ndim) weights = numpy.asarray(weights, dtype=numpy.float64) wshape = [ii for ii in weights.shape if ii > 0] if len(wshape) != input.ndim: raise RuntimeError('filter weights array has incorrect shape.') if convolution: weights = weights[tuple([slice(None, None, -1)] * weights.ndim)] for ii in range(len(origins)): origins[ii] = -origins[ii] if not weights.shape[ii] & 1: origins[ii] -= 1 for origin, lenw in zip(origins, wshape): if (lenw // 2 + origin < 0) or (lenw // 2 + origin > lenw): raise ValueError('invalid origin') if not weights.flags.contiguous: weights = weights.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.correlate(input, weights, output, mode, cval, origins) return return_value
def binary_dilation(input, structure=None, iterations=1, mask=None, output=None, border_value=0, origin=0, brute_force=False): """Multi-dimensional binary dilation with the given structure. An output array can optionally be provided. The origin parameter controls the placement of the filter. If no structuring element is provided an element is generated with a squared connectivity equal to one. The dilation operation is repeated iterations times. If iterations is less than 1, the dilation is repeated until the result does not change anymore. If a mask is given, only those elements with a true value at the corresponding mask element are modified at each iteration. """ input = numpy.asarray(input) if structure is None: structure = generate_binary_structure(input.ndim, 1) origin = _ni_support._normalize_sequence(origin, input.ndim) structure = numpy.asarray(structure) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] for ii in range(len(origin)): origin[ii] = -origin[ii] if not structure.shape[ii] & 1: origin[ii] -= 1 return _binary_erosion(input, structure, iterations, mask, output, border_value, origin, 1, brute_force)
def binary_dilation(input, structure = None, iterations = 1, mask = None, output = None, border_value = 0, origin = 0, brute_force = False): """Multi-dimensional binary dilation with the given structure. An output array can optionally be provided. The origin parameter controls the placement of the filter. If no structuring element is provided an element is generated with a squared connectivity equal to one. The dilation operation is repeated iterations times. If iterations is less than 1, the dilation is repeated until the result does not change anymore. If a mask is given, only those elements with a true value at the corresponding mask element are modified at each iteration. """ input = numpy.asarray(input) if structure is None: structure = generate_binary_structure(input.ndim, 1) origin = _ni_support._normalize_sequence(origin, input.ndim) structure = numpy.asarray(structure) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] for ii in range(len(origin)): origin[ii] = -origin[ii] if not structure.shape[ii] & 1: origin[ii] -= 1 return _binary_erosion(input, structure, iterations, mask, output, border_value, origin, 1, brute_force)
def grey_dilation(input, size = None, footprint = None, structure = None, output = None, mode = "reflect", cval = 0.0, origin = 0): """Calculate a grey values dilation. Either a size or a footprint, or the structure must be provided. An output array can optionally be provided. The origin parameter controls the placement of the filter. The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. """ if structure is not None: structure = numpy.asarray(structure) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] if footprint is not None: footprint = numpy.asarray(footprint) footprint = footprint[tuple([slice(None, None, -1)] * footprint.ndim)] input = numpy.asarray(input) origin = _ni_support._normalize_sequence(origin, input.ndim) for ii in range(len(origin)): origin[ii] = -origin[ii] if footprint is not None: sz = footprint.shape[ii] else: sz = size[ii] if not sz & 1: origin[ii] -= 1 return filters._min_or_max_filter(input, size, footprint, structure, output, mode, cval, origin, 0)
def iterate_structure(structure, iterations, origin=None): """Iterate a structure by dilating it with itself. If origin is None, only the iterated structure is returned. If not, a tuple of the iterated structure and the modified origin is returned. """ structure = numpy.asarray(structure) if iterations < 2: return structure.copy() ni = iterations - 1 shape = [ii + ni * (ii - 1) for ii in structure.shape] pos = [ni * (structure.shape[ii] / 2) for ii in range(len(shape))] slc = [ slice(pos[ii], pos[ii] + structure.shape[ii], None) for ii in range(len(shape)) ] out = numpy.zeros(shape, bool) out[slc] = structure != 0 out = binary_dilation(out, structure, iterations=ni) if origin is None: return out else: origin = _ni_support._normalize_sequence(origin, structure.ndim) origin = [iterations * o for o in origin] return out, origin
def zoom(input, zoom, output_type = None, output = None, order = 3, mode = 'constant', cval = 0.0, prefilter = True): """Zoom an array. The array is zoomed using spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. The parameter prefilter determines if the input is pre- filtered before interpolation, if False it is assumed that the input is already filtered. """ if order < 0 or order > 5: raise RuntimeError, 'spline order not supported' input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if input.ndim < 1: raise RuntimeError, 'input and output rank must be > 0' mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input zoom = _ni_support._normalize_sequence(zoom, input.ndim) output_shape = tuple([int(ii * jj) for ii, jj in zip(input.shape, zoom)]) zoom = (numpy.array(input.shape)-1)/(numpy.array(output_shape,float)-1) output, return_value = _ni_support._get_output(output, input, output_type, shape = output_shape) zoom = numpy.asarray(zoom, dtype = numpy.float64) zoom = numpy.ascontiguousarray(zoom) _nd_image.zoom_shift(filtered, zoom, None, output, order, mode, cval) return return_value
def grey_dilation(input, size=None, footprint=None, structure=None, output=None, mode="reflect", cval=0.0, origin=0): """Calculate a grey values dilation. Either a size or a footprint, or the structure must be provided. An output array can optionally be provided. The origin parameter controls the placement of the filter. The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. """ if structure is not None: structure = numpy.asarray(structure) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] if footprint is not None: footprint = numpy.asarray(footprint) footprint = footprint[tuple([slice(None, None, -1)] * footprint.ndim)] input = numpy.asarray(input) origin = _ni_support._normalize_sequence(origin, input.ndim) for ii in range(len(origin)): origin[ii] = -origin[ii] if footprint is not None: sz = footprint.shape[ii] else: sz = size[ii] if not sz & 1: origin[ii] -= 1 return filters._min_or_max_filter(input, size, footprint, structure, output, mode, cval, origin, 0)
def _correlate_or_convolve(input, weights, output, mode, cval, origin, convolution): input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, 'Complex type not supported' origins = _ni_support._normalize_sequence(origin, input.rank) weights = numarray.asarray(weights, type=numarray.Float64) wshape = [ii for ii in weights.shape if ii > 0] if len(wshape) != input.rank: raise RuntimeError, 'filter weights array has incorrect shape.' if convolution: weights = weights[tuple([slice(None, None, -1)] * weights.rank)] for ii in range(len(origins)): origins[ii] = -origins[ii] if not weights.shape[ii] & 1: origins[ii] -= 1 for origin, lenw in zip(origins, wshape): if (lenw // 2 + origin < 0) or (lenw // 2 + origin > lenw): raise ValueError, 'invalid origin' if not weights.iscontiguous(): weights = weights.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.correlate(input, weights, output, mode, cval, origins) return return_value
def shift(input, shift, output_type = None, output = None, order = 3, mode = 'constant', cval = 0.0, prefilter = True): """Shift an array. The array is shifted using spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. The parameter prefilter determines if the input is pre-filtered before interpolation, if False it is assumed that the input is already filtered. """ if order < 0 or order > 5: raise RuntimeError, 'spline order not supported' input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if input.ndim < 1: raise RuntimeError, 'input and output rank must be > 0' mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input, output_type) shift = _ni_support._normalize_sequence(shift, input.ndim) shift = [-ii for ii in shift] shift = numpy.asarray(shift, dtype = numpy.float64) if not shift.flags.contiguous: shift = shift.copy() _nd_image.zoom_shift(filtered, None, shift, output, order, mode, cval) return return_value
def affine_transform(input, matrix, offset = 0.0, output_shape = None, output_type = None, output = None, order = 3, mode = 'constant', cval = 0.0, prefilter = True): """Apply an affine transformation. The given matrix and offset are used to find for each point in the output the corresponding coordinates in the input by an affine transformation. The value of the input at those coordinates is determined by spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. The output shape can optionally be given. If not given it is equal to the input shape. The parameter prefilter determines if the input is pre-filtered before interpolation, if False it is assumed that the input is already filtered. The matrix must be two-dimensional or can also be given as a one-dimensional sequence or array. In the latter case, it is assumed that the matrix is diagonal. A more efficient algorithms is then applied that exploits the separability of the problem. """ if order < 0 or order > 5: raise RuntimeError, 'spline order not supported' input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if output_shape is None: output_shape = input.shape if input.ndim < 1 or len(output_shape) < 1: raise RuntimeError, 'input and output rank must be > 0' mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input, output_type, shape = output_shape) matrix = numpy.asarray(matrix, dtype = numpy.float64) if matrix.ndim not in [1, 2] or matrix.shape[0] < 1: raise RuntimeError, 'no proper affine matrix provided' if matrix.shape[0] != input.ndim: raise RuntimeError, 'affine matrix has wrong number of rows' if matrix.ndim == 2 and matrix.shape[1] != output.ndim: raise RuntimeError, 'affine matrix has wrong number of columns' if not matrix.flags.contiguous: matrix = matrix.copy() offset = _ni_support._normalize_sequence(offset, input.ndim) offset = numpy.asarray(offset, dtype = numpy.float64) if offset.ndim != 1 or offset.shape[0] < 1: raise RuntimeError, 'no proper offset provided' if not offset.flags.contiguous: offset = offset.copy() if matrix.ndim == 1: _nd_image.zoom_shift(filtered, matrix, offset, output, order, mode, cval) else: _nd_image.geometric_transform(filtered, None, None, matrix, offset, output, order, mode, cval, None, None) return return_value
def binary_hit_or_miss(input, structure1=None, structure2=None, output=None, origin1=0, origin2=None): """Multi-dimensional binary hit-or-miss transform. An output array can optionally be provided. The origin parameters controls the placement of the structuring elements. If the first structuring element is not given one is generated with a squared connectivity equal to one. If the second structuring element is not provided, it set equal to the inverse of the first structuring element. If the origin for the second structure is equal to None it is set equal to the origin of the first. """ input = numpy.asarray(input) if structure1 is None: structure1 = generate_binary_structure(input.ndim, 1) if structure2 is None: structure2 = numpy.logical_not(structure1) origin1 = _ni_support._normalize_sequence(origin1, input.ndim) if origin2 is None: origin2 = origin1 else: origin2 = _ni_support._normalize_sequence(origin2, input.ndim) tmp1 = _binary_erosion(input, structure1, 1, None, None, 0, origin1, 0, False) inplace = isinstance(output, numpy.ndarray) result = _binary_erosion(input, structure2, 1, None, output, 0, origin2, 1, False) if inplace: numpy.logical_not(output, output) numpy.logical_and(tmp1, output, output) else: numpy.logical_not(result, result) return numpy.logical_and(tmp1, result)
def gaussian_filter(input, sigma, order=0, output=None, mode="reflect", cval=0.0): """Multi-dimensional Gaussian filter. The standard-deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. The order of the filter along each axis is given as a sequence of integers, or as a single number. An order of 0 corresponds to convolution with a Gaussian kernel. An order of 1, 2, or 3 corresponds to convolution with the first, second or third derivatives of a Gaussian. Higher order derivatives are not implemented.' Note: The multi-dimensional filter is implemented as a sequence of one-dimensional convolution filters. The intermediate arrays are stored in the same data type as the output. Therefore, for output types with a limited precision, the results may be imprecise because intermediate results may be stored with insufficient precision. """ input = numarray.asarray(input) output, return_value = _ni_support._get_output(output, input) orders = _ni_support._normalize_sequence(order, input.rank) sigmas = _ni_support._normalize_sequence(sigma, input.rank) axes = range(input.rank) axes = [(axes[ii], sigmas[ii], orders[ii]) for ii in range(len(axes)) if sigmas[ii] > 1e-15] if len(axes) > 0: for axis, sigma, order in axes: gaussian_filter1d(input, sigma, axis, order, output, mode, cval) input = output else: output[...] = input[...] return return_value
def fourier_ellipsoid(input, size, n = -1, axis = -1, output = None): """ Multi-dimensional ellipsoid fourier filter. The array is multiplied with the fourier transform of a ellipsoid of given sizes. Parameters ---------- input : array_like The input array. size : float or sequence The size of the box used for filtering. If a float, `size` is the same for all axes. If a sequence, `size` has to contain one value for each axis. n : int, optional If `n` is negative (default), then the input is assumed to be the result of a complex fft. If `n` is larger than or equal to zero, the input is assumed to be the result of a real fft, and `n` gives the length of the array before transformation along the real transform direction. axis : int, optional The axis of the real transform. output : ndarray, optional If given, the result of filtering the input is placed in this array. None is returned in this case. Returns ------- return_value : ndarray or None The filtered input. If `output` is given as a parameter, None is returned. Notes ----- This function is implemented for arrays of rank 1, 2, or 3. """ input = numpy.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.ndim) sizes = _ni_support._normalize_sequence(size, input.ndim) sizes = numpy.asarray(sizes, dtype = numpy.float64) if not sizes.flags.contiguous: sizes = sizes.copy() _nd_image.fourier_filter(input, sizes, n, axis, output, 2) return return_value
def fourier_ellipsoid(input, size, n=-1, axis=-1, output=None): """ Multi-dimensional ellipsoid fourier filter. The array is multiplied with the fourier transform of a ellipsoid of given sizes. Parameters ---------- input : array_like The input array. size : float or sequence The size of the box used for filtering. If a float, `size` is the same for all axes. If a sequence, `size` has to contain one value for each axis. n : int, optional If `n` is negative (default), then the input is assumed to be the result of a complex fft. If `n` is larger than or equal to zero, the input is assumed to be the result of a real fft, and `n` gives the length of the array before transformation along the real transform direction. axis : int, optional The axis of the real transform. output : ndarray, optional If given, the result of filtering the input is placed in this array. None is returned in this case. Returns ------- return_value : ndarray or None The filtered input. If `output` is given as a parameter, None is returned. Notes ----- This function is implemented for arrays of rank 1, 2, or 3. """ input = numpy.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.ndim) sizes = _ni_support._normalize_sequence(size, input.ndim) sizes = numpy.asarray(sizes, dtype=numpy.float64) if not sizes.flags.contiguous: sizes = sizes.copy() _nd_image.fourier_filter(input, sizes, n, axis, output, 2) return return_value
def fourier_uniform(input, size, n = -1, axis = -1, output = None): """Multi-dimensional Uniform fourier filter. The array is multiplied with the fourier transform of a box of given sizes. If the parameter n is negative, then the input is assumed to be the result of a complex fft. If n is larger or equal to zero, the input is assumed to be the result of a real fft, and n gives the length of the of the array before transformation along the the real transform direction. The axis of the real transform is given by the axis parameter. """ input = numarray.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.rank) sizes = _ni_support._normalize_sequence(size, input.rank) sizes = numarray.asarray(sizes, type = numarray.Float64) if not sizes.iscontiguous(): sizes = sizes.copy() _nd_image.fourier_filter(input, sizes, n, axis, output, 1) return return_value
def fourier_shift(input, shift, n=-1, axis=-1, output=None): """Multi-dimensional fourier shift filter. The array is multiplied with the fourier transform of a shift operation If the parameter n is negative, then the input is assumed to be the result of a complex fft. If n is larger or equal to zero, the input is assumed to be the result of a real fft, and n gives the length of the of the array before transformation along the the real transform direction. The axis of the real transform is given by the axis parameter. """ input = numpy.asarray(input) output, return_value = _get_output_fourier_complex(output, input) axis = _ni_support._check_axis(axis, input.ndim) shifts = _ni_support._normalize_sequence(shift, input.ndim) shifts = numpy.asarray(shifts, dtype=numpy.float64) if not shifts.flags.contiguous: shifts = shifts.copy() _nd_image.fourier_shift(input, shifts, n, axis, output) return return_value
def fourier_uniform(input, size, n = -1, axis = -1, output = None): """Multi-dimensional Uniform fourier filter. The array is multiplied with the fourier transform of a box of given sizes. If the parameter n is negative, then the input is assumed to be the result of a complex fft. If n is larger or equal to zero, the input is assumed to be the result of a real fft, and n gives the length of the of the array before transformation along the the real transform direction. The axis of the real transform is given by the axis parameter. """ input = numpy.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.ndim) sizes = _ni_support._normalize_sequence(size, input.ndim) sizes = numpy.asarray(sizes, dtype = numpy.float64) if not sizes.flags.contiguous: sizes = sizes.copy() _nd_image.fourier_filter(input, sizes, n, axis, output, 1) return return_value
def fourier_gaussian(input, sigma, n=-1, axis=-1, output=None): """Multi-dimensional Gaussian fourier filter. The array is multiplied with the fourier transform of a Gaussian kernel. If the parameter n is negative, then the input is assumed to be the result of a complex fft. If n is larger or equal to zero, the input is assumed to be the result of a real fft, and n gives the length of the of the array before transformation along the the real transform direction. The axis of the real transform is given by the axis parameter. """ input = numarray.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.rank) sigmas = _ni_support._normalize_sequence(sigma, input.rank) sigmas = numarray.asarray(sigmas, type=numarray.Float64) if not sigmas.iscontiguous(): sigmas = sigmas.copy() _nd_image.fourier_filter(input, sigmas, n, axis, output, 0) return return_value
def fourier_ellipsoid(input, size, n=-1, axis=-1, output=None): """Multi-dimensional ellipsoid fourier filter. The array is multiplied with the fourier transform of a ellipsoid of given sizes. If the parameter n is negative, then the input is assumed to be the result of a complex fft. If n is larger or equal to zero, the input is assumed to be the result of a real fft, and n gives the length of the of the array before transformation along the the real transform direction. The axis of the real transform is given by the axis parameter. This function is implemented for arrays of rank 1, 2, or 3. """ input = numpy.asarray(input) output, return_value = _get_output_fourier(output, input) axis = _ni_support._check_axis(axis, input.ndim) sizes = _ni_support._normalize_sequence(size, input.ndim) sizes = numpy.asarray(sizes, dtype=numpy.float64) if not sizes.flags.contiguous: sizes = sizes.copy() _nd_image.fourier_filter(input, sizes, n, axis, output, 2) return return_value
def iterate_structure(structure, iterations, origin = None): """Iterate a structure by dilating it with itself. If origin is None, only the iterated structure is returned. If not, a tuple of the iterated structure and the modified origin is returned. """ structure = numpy.asarray(structure) if iterations < 2: return structure.copy() ni = iterations - 1 shape = [ii + ni * (ii - 1) for ii in structure.shape] pos = [ni * (structure.shape[ii] / 2) for ii in range(len(shape))] slc = [slice(pos[ii], pos[ii] + structure.shape[ii], None) for ii in range(len(shape))] out = numpy.zeros(shape, bool) out[slc] = structure != 0 out = binary_dilation(out, structure, iterations = ni) if origin is None: return out else: origin = _ni_support._normalize_sequence(origin, structure.ndim) origin = [iterations * o for o in origin] return out, origin
def _correlate_or_convolve(input, weights, output, mode, cval, origin, convolution): input = numarray.asarray(input) if isinstance(input.type(), numarray.ComplexType): raise TypeError, "Complex type not supported" origins = _ni_support._normalize_sequence(origin, input.rank) weights = numarray.asarray(weights, type=numarray.Float64) wshape = [ii for ii in weights.shape if ii > 0] if len(wshape) != input.rank: raise RuntimeError, "filter weights array has incorrect shape." if convolution: weights = weights[tuple([slice(None, None, -1)] * weights.rank)] for ii in range(len(origins)): origins[ii] = -origins[ii] if not weights.shape[ii] & 1: origins[ii] -= 1 for origin, lenw in zip(origins, wshape): if (lenw // 2 + origin < 0) or (lenw // 2 + origin > lenw): raise ValueError, "invalid origin" if not weights.iscontiguous(): weights = weights.copy() output, return_value = _ni_support._get_output(output, input) mode = _ni_support._extend_mode_to_code(mode) _nd_image.correlate(input, weights, output, mode, cval, origins) return return_value
def _binary_erosion(input, structure, iterations, mask, output, border_value, origin, invert, brute_force): input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if structure is None: structure = generate_binary_structure(input.ndim, 1) else: structure = numpy.asarray(structure) structure = structure.astype(bool) if structure.ndim != input.ndim: raise RuntimeError, 'structure rank must equal input rank' if not structure.flags.contiguous: structure = structure.copy() if numpy.product(structure.shape,axis=0) < 1: raise RuntimeError, 'structure must not be empty' if mask is not None: mask = numpy.asarray(mask) if mask.shape != input.shape: raise RuntimeError, 'mask and input must have equal sizes' origin = _ni_support._normalize_sequence(origin, input.ndim) cit = _center_is_true(structure, origin) if isinstance(output, numpy.ndarray): if numpy.iscomplexobj(output): raise TypeError, 'Complex output type not supported' else: output = bool output, return_value = _ni_support._get_output(output, input) if iterations == 1: _nd_image.binary_erosion(input, structure, mask, output, border_value, origin, invert, cit, 0) return return_value elif cit and not brute_force: changed, coordinate_list = _nd_image.binary_erosion(input, structure, mask, output, border_value, origin, invert, cit, 1) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] for ii in range(len(origin)): origin[ii] = -origin[ii] if not structure.shape[ii] & 1: origin[ii] -= 1 if mask is not None: msk = numpy.asarray(mask) msk = mask.astype(numpy.int8) if msk is mask: msk = mask.copy() mask = msk if not structure.flags.contiguous: structure = structure.copy() _nd_image.binary_erosion2(output, structure, mask, iterations - 1, origin, invert, coordinate_list) return return_value else: tmp_in = numpy.zeros(input.shape, bool) if return_value is None: tmp_out = output else: tmp_out = numpy.zeros(input.shape, bool) if not iterations & 1: tmp_in, tmp_out = tmp_out, tmp_in changed = _nd_image.binary_erosion(input, structure, mask, tmp_out, border_value, origin, invert, cit, 0) ii = 1 while (ii < iterations) or (iterations < 1) and changed: tmp_in, tmp_out = tmp_out, tmp_in changed = _nd_image.binary_erosion(tmp_in, structure, mask, tmp_out, border_value, origin, invert, cit, 0) ii += 1 if return_value is not None: return tmp_out
def distance_transform_edt(input, sampling = None, return_distances = True, return_indices = False, distances = None, indices = None): """Exact euclidean distance transform. In addition to the distance transform, the feature transform can be calculated. In this case the index of the closest background element is returned along the first axis of the result. The return_distances, and return_indices flags can be used to indicate if the distance transform, the feature transform, or both must be returned. Optionally the sampling along each axis can be given by the sampling parameter which should be a sequence of length equal to the input rank, or a single number in which the sampling is assumed to be equal along all axes. the distances and indices arguments can be used to give optional output arrays that must be of the correct size and type (float64 and int32). """ if (not return_distances) and (not return_indices): msg = 'at least one of distances/indices must be specified' raise RuntimeError, msg ft_inplace = isinstance(indices, numpy.ndarray) dt_inplace = isinstance(distances, numpy.ndarray) # calculate the feature transform input = numpy.where(input, 1, 0).astype(numpy.int8) if sampling is not None: sampling = _ni_support._normalize_sequence(sampling, input.ndim) sampling = numpy.asarray(sampling, dtype = numpy.float64) if not sampling.flags.contiguous: sampling = sampling.copy() if ft_inplace: ft = indices if ft.shape != (input.ndim,) + input.shape: raise RuntimeError, 'indices has wrong shape' if ft.dtype.type != numpy.int32: raise RuntimeError, 'indices must be of int32 type' else: ft = numpy.zeros((input.ndim,) + input.shape, dtype = numpy.int32) _nd_image.euclidean_feature_transform(input, sampling, ft) # if requested, calculate the distance transform if return_distances: dt = ft - numpy.indices(input.shape, dtype = ft.dtype) dt = dt.astype(numpy.float64) if sampling is not None: for ii in range(len(sampling)): dt[ii, ...] *= sampling[ii] numpy.multiply(dt, dt, dt) if dt_inplace: dt = numpy.add.reduce(dt, axis = 0) if distances.shape != dt.shape: raise RuntimeError, 'indices has wrong shape' if distances.dtype.type != numpy.float64: raise RuntimeError, 'indices must be of float64 type' numpy.sqrt(dt, distances) del dt else: dt = numpy.add.reduce(dt, axis = 0) dt = numpy.sqrt(dt) # construct and return the result result = [] if return_distances and not dt_inplace: result.append(dt) if return_indices and not ft_inplace: result.append(ft) if len(result) == 2: return tuple(result) elif len(result) == 1: return result[0] else: return None
def distance_transform_bf(input, metric = "euclidean", sampling = None, return_distances = True, return_indices = False, distances = None, indices = None): """Distance transform function by a brute force algorithm. This function calculates the distance transform of the input, by replacing each background element (zero values), with its shortest distance to the foreground (any element non-zero). Three types of distance metric are supported: 'euclidean', 'taxicab' and 'chessboard'. In addition to the distance transform, the feature transform can be calculated. In this case the index of the closest background element is returned along the first axis of the result. The return_distances, and return_indices flags can be used to indicate if the distance transform, the feature transform, or both must be returned. Optionally the sampling along each axis can be given by the sampling parameter which should be a sequence of length equal to the input rank, or a single number in which the sampling is assumed to be equal along all axes. This parameter is only used in the case of the euclidean distance transform. This function employs a slow brute force algorithm, see also the function distance_transform_cdt for more efficient taxicab and chessboard algorithms. the distances and indices arguments can be used to give optional output arrays that must be of the correct size and type (float64 and int32). """ if (not return_distances) and (not return_indices): msg = 'at least one of distances/indices must be specified' raise RuntimeError, msg tmp1 = numpy.asarray(input) != 0 struct = generate_binary_structure(tmp1.ndim, tmp1.ndim) tmp2 = binary_dilation(tmp1, struct) tmp2 = numpy.logical_xor(tmp1, tmp2) tmp1 = tmp1.astype(numpy.int8) - tmp2.astype(numpy.int8) del tmp2 metric = metric.lower() if metric == 'euclidean': metric = 1 elif metric in ['taxicab', 'cityblock', 'manhattan']: metric = 2 elif metric == 'chessboard': metric = 3 else: raise RuntimeError, 'distance metric not supported' if sampling is not None: sampling = _ni_support._normalize_sequence(sampling, tmp1.ndim) sampling = numpy.asarray(sampling, dtype = numpy.float64) if not sampling.flags.contiguous: sampling = sampling.copy() if return_indices: ft = numpy.zeros(tmp1.shape, dtype = numpy.int32) else: ft = None if return_distances: if distances is None: if metric == 1: dt = numpy.zeros(tmp1.shape, dtype = numpy.float64) else: dt = numpy.zeros(tmp1.shape, dtype = numpy.uint32) else: if distances.shape != tmp1.shape: raise RuntimeError, 'distances array has wrong shape' if metric == 1: if distances.dtype.type != numpy.float64: raise RuntimeError, 'distances array must be float64' else: if distances.dtype.type != numpy.uint32: raise RuntimeError, 'distances array must be uint32' dt = distances else: dt = None _nd_image.distance_transform_bf(tmp1, metric, sampling, dt, ft) if return_indices: if isinstance(indices, numpy.ndarray): if indices.dtype.type != numpy.int32: raise RuntimeError, 'indices must of int32 type' if indices.shape != (tmp1.ndim,) + tmp1.shape: raise RuntimeError, 'indices has wrong shape' tmp2 = indices else: tmp2 = numpy.indices(tmp1.shape, dtype = numpy.int32) ft = numpy.ravel(ft) for ii in range(tmp2.shape[0]): rtmp = numpy.ravel(tmp2[ii, ...])[ft] rtmp.shape = tmp1.shape tmp2[ii, ...] = rtmp ft = tmp2 # construct and return the result result = [] if return_distances and not isinstance(distances, numpy.ndarray): result.append(dt) if return_indices and not isinstance(indices, numpy.ndarray): result.append(ft) if len(result) == 2: return tuple(result) elif len(result) == 1: return result[0] else: return None
def distance_transform_bf(input, metric="euclidean", sampling=None, return_distances=True, return_indices=False, distances=None, indices=None): """Distance transform function by a brute force algorithm. This function calculates the distance transform of the input, by replacing each background element (zero values), with its shortest distance to the foreground (any element non-zero). Three types of distance metric are supported: 'euclidean', 'taxicab' and 'chessboard'. In addition to the distance transform, the feature transform can be calculated. In this case the index of the closest background element is returned along the first axis of the result. The return_distances, and return_indices flags can be used to indicate if the distance transform, the feature transform, or both must be returned. Optionally the sampling along each axis can be given by the sampling parameter which should be a sequence of length equal to the input rank, or a single number in which the sampling is assumed to be equal along all axes. This parameter is only used in the case of the euclidean distance transform. This function employs a slow brute force algorithm, see also the function distance_transform_cdt for more efficient taxicab and chessboard algorithms. the distances and indices arguments can be used to give optional output arrays that must be of the correct size and type (float64 and int32). """ if (not return_distances) and (not return_indices): msg = 'at least one of distances/indices must be specified' raise RuntimeError, msg tmp1 = numpy.asarray(input) != 0 struct = generate_binary_structure(tmp1.ndim, tmp1.ndim) tmp2 = binary_dilation(tmp1, struct) tmp2 = numpy.logical_xor(tmp1, tmp2) tmp1 = tmp1.astype(numpy.int8) - tmp2.astype(numpy.int8) del tmp2 metric = metric.lower() if metric == 'euclidean': metric = 1 elif metric in ['taxicab', 'cityblock', 'manhattan']: metric = 2 elif metric == 'chessboard': metric = 3 else: raise RuntimeError, 'distance metric not supported' if sampling is not None: sampling = _ni_support._normalize_sequence(sampling, tmp1.ndim) sampling = numpy.asarray(sampling, dtype=numpy.float64) if not sampling.flags.contiguous: sampling = sampling.copy() if return_indices: ft = numpy.zeros(tmp1.shape, dtype=numpy.int32) else: ft = None if return_distances: if distances is None: if metric == 1: dt = numpy.zeros(tmp1.shape, dtype=numpy.float64) else: dt = numpy.zeros(tmp1.shape, dtype=numpy.uint32) else: if distances.shape != tmp1.shape: raise RuntimeError, 'distances array has wrong shape' if metric == 1: if distances.dtype.type != numpy.float64: raise RuntimeError, 'distances array must be float64' else: if distances.dtype.type != numpy.uint32: raise RuntimeError, 'distances array must be uint32' dt = distances else: dt = None _nd_image.distance_transform_bf(tmp1, metric, sampling, dt, ft) if return_indices: if isinstance(indices, numpy.ndarray): if indices.dtype.type != numpy.int32: raise RuntimeError, 'indices must of int32 type' if indices.shape != (tmp1.ndim, ) + tmp1.shape: raise RuntimeError, 'indices has wrong shape' tmp2 = indices else: tmp2 = numpy.indices(tmp1.shape, dtype=numpy.int32) ft = numpy.ravel(ft) for ii in range(tmp2.shape[0]): rtmp = numpy.ravel(tmp2[ii, ...])[ft] rtmp.shape = tmp1.shape tmp2[ii, ...] = rtmp ft = tmp2 # construct and return the result result = [] if return_distances and not isinstance(distances, numpy.ndarray): result.append(dt) if return_indices and not isinstance(indices, numpy.ndarray): result.append(ft) if len(result) == 2: return tuple(result) elif len(result) == 1: return result[0] else: return None
def distance_transform_edt(input, sampling=None, return_distances=True, return_indices=False, distances=None, indices=None): """Exact euclidean distance transform. In addition to the distance transform, the feature transform can be calculated. In this case the index of the closest background element is returned along the first axis of the result. The return_distances, and return_indices flags can be used to indicate if the distance transform, the feature transform, or both must be returned. Optionally the sampling along each axis can be given by the sampling parameter which should be a sequence of length equal to the input rank, or a single number in which the sampling is assumed to be equal along all axes. the distances and indices arguments can be used to give optional output arrays that must be of the correct size and type (float64 and int32). """ if (not return_distances) and (not return_indices): msg = 'at least one of distances/indices must be specified' raise RuntimeError, msg ft_inplace = isinstance(indices, numpy.ndarray) dt_inplace = isinstance(distances, numpy.ndarray) # calculate the feature transform input = numpy.where(input, 1, 0).astype(numpy.int8) if sampling is not None: sampling = _ni_support._normalize_sequence(sampling, input.ndim) sampling = numpy.asarray(sampling, dtype=numpy.float64) if not sampling.flags.contiguous: sampling = sampling.copy() if ft_inplace: ft = indices if ft.shape != (input.ndim, ) + input.shape: raise RuntimeError, 'indices has wrong shape' if ft.dtype.type != numpy.int32: raise RuntimeError, 'indices must be of int32 type' else: ft = numpy.zeros((input.ndim, ) + input.shape, dtype=numpy.int32) _nd_image.euclidean_feature_transform(input, sampling, ft) # if requested, calculate the distance transform if return_distances: dt = ft - numpy.indices(input.shape, dtype=ft.dtype) dt = dt.astype(numpy.float64) if sampling is not None: for ii in range(len(sampling)): dt[ii, ...] *= sampling[ii] numpy.multiply(dt, dt, dt) if dt_inplace: dt = numpy.add.reduce(dt, axis=0) if distances.shape != dt.shape: raise RuntimeError, 'indices has wrong shape' if distances.dtype.type != numpy.float64: raise RuntimeError, 'indices must be of float64 type' numpy.sqrt(dt, distances) del dt else: dt = numpy.add.reduce(dt, axis=0) dt = numpy.sqrt(dt) # construct and return the result result = [] if return_distances and not dt_inplace: result.append(dt) if return_indices and not ft_inplace: result.append(ft) if len(result) == 2: return tuple(result) elif len(result) == 1: return result[0] else: return None
def _binary_erosion(input, structure, iterations, mask, output, border_value, origin, invert, brute_force): input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if structure is None: structure = generate_binary_structure(input.ndim, 1) else: structure = numpy.asarray(structure) structure = structure.astype(bool) if structure.ndim != input.ndim: raise RuntimeError, 'structure rank must equal input rank' if not structure.flags.contiguous: structure = structure.copy() if numpy.product(structure.shape, axis=0) < 1: raise RuntimeError, 'structure must not be empty' if mask is not None: mask = numpy.asarray(mask) if mask.shape != input.shape: raise RuntimeError, 'mask and input must have equal sizes' origin = _ni_support._normalize_sequence(origin, input.ndim) cit = _center_is_true(structure, origin) if isinstance(output, numpy.ndarray): if numpy.iscomplexobj(output): raise TypeError, 'Complex output type not supported' else: output = bool output, return_value = _ni_support._get_output(output, input) if iterations == 1: _nd_image.binary_erosion(input, structure, mask, output, border_value, origin, invert, cit, 0) return return_value elif cit and not brute_force: changed, coordinate_list = _nd_image.binary_erosion( input, structure, mask, output, border_value, origin, invert, cit, 1) structure = structure[tuple([slice(None, None, -1)] * structure.ndim)] for ii in range(len(origin)): origin[ii] = -origin[ii] if not structure.shape[ii] & 1: origin[ii] -= 1 if mask is not None: msk = numpy.asarray(mask) msk = mask.astype(numpy.int8) if msk is mask: msk = mask.copy() mask = msk if not structure.flags.contiguous: structure = structure.copy() _nd_image.binary_erosion2(output, structure, mask, iterations - 1, origin, invert, coordinate_list) return return_value else: tmp_in = numpy.zeros(input.shape, bool) if return_value is None: tmp_out = output else: tmp_out = numpy.zeros(input.shape, bool) if not iterations & 1: tmp_in, tmp_out = tmp_out, tmp_in changed = _nd_image.binary_erosion(input, structure, mask, tmp_out, border_value, origin, invert, cit, 0) ii = 1 while (ii < iterations) or (iterations < 1) and changed: tmp_in, tmp_out = tmp_out, tmp_in changed = _nd_image.binary_erosion(tmp_in, structure, mask, tmp_out, border_value, origin, invert, cit, 0) ii += 1 if return_value is not None: return tmp_out
def zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0, prefilter=True): """ Zoom an array. The array is zoomed using spline interpolation of the requested order. Parameters ---------- input : ndarray The input array. zoom : float or sequence, optional The zoom factor along the axes. If a float, `zoom` is the same for each axis. If a sequence, `zoom` should contain one value for each axis. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The zoomed input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError('spline order not supported') input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') if input.ndim < 1: raise RuntimeError('input and output rank must be > 0') mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input zoom = _ni_support._normalize_sequence(zoom, input.ndim) output_shape = tuple([int(ii * jj) for ii, jj in zip(input.shape, zoom)]) zoom = (numpy.array(input.shape)-1)/(numpy.array(output_shape,float)-1) output, return_value = _ni_support._get_output(output, input, shape=output_shape) zoom = numpy.asarray(zoom, dtype = numpy.float64) zoom = numpy.ascontiguousarray(zoom) _nd_image.zoom_shift(filtered, zoom, None, output, order, mode, cval) return return_value
def affine_transform(input, matrix, offset=0.0, output_shape=None, output=None, order=3, mode='constant', cval=0.0, prefilter=True): """ Apply an affine transformation. The given matrix and offset are used to find for each point in the output the corresponding coordinates in the input by an affine transformation. The value of the input at those coordinates is determined by spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. Parameters ---------- input : ndarray The input array. matrix : ndarray The matrix must be two-dimensional or can also be given as a one-dimensional sequence or array. In the latter case, it is assumed that the matrix is diagonal. A more efficient algorithms is then applied that exploits the separability of the problem. offset : float or sequence, optional The offset into the array where the transform is applied. If a float, `offset` is the same for each axis. If a sequence, `offset` should contain one value for each axis. output_shape : tuple of ints, optional Shape tuple. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The transformed input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError('spline order not supported') input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') if output_shape is None: output_shape = input.shape if input.ndim < 1 or len(output_shape) < 1: raise RuntimeError('input and output rank must be > 0') mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input, shape=output_shape) matrix = numpy.asarray(matrix, dtype = numpy.float64) if matrix.ndim not in [1, 2] or matrix.shape[0] < 1: raise RuntimeError('no proper affine matrix provided') if matrix.shape[0] != input.ndim: raise RuntimeError('affine matrix has wrong number of rows') if matrix.ndim == 2 and matrix.shape[1] != output.ndim: raise RuntimeError('affine matrix has wrong number of columns') if not matrix.flags.contiguous: matrix = matrix.copy() offset = _ni_support._normalize_sequence(offset, input.ndim) offset = numpy.asarray(offset, dtype = numpy.float64) if offset.ndim != 1 or offset.shape[0] < 1: raise RuntimeError('no proper offset provided') if not offset.flags.contiguous: offset = offset.copy() if matrix.ndim == 1: _nd_image.zoom_shift(filtered, matrix, offset, output, order, mode, cval) else: _nd_image.geometric_transform(filtered, None, None, matrix, offset, output, order, mode, cval, None, None) return return_value
def zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0, prefilter=True): """ Zoom an array. The array is zoomed using spline interpolation of the requested order. Parameters ---------- input : ndarray The input array. zoom : float or sequence, optional The zoom factor along the axes. If a float, `zoom` is the same for each axis. If a sequence, `zoom` should contain one value for each axis. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The zoomed input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError('spline order not supported') input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') if input.ndim < 1: raise RuntimeError('input and output rank must be > 0') mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output=numpy.float64) else: filtered = input zoom = _ni_support._normalize_sequence(zoom, input.ndim) output_shape = tuple([int(ii * jj) for ii, jj in zip(input.shape, zoom)]) zoom_div = numpy.array(output_shape, float) - 1 zoom = (numpy.array(input.shape) - 1) / zoom_div # Zooming to infinity is unpredictable, so just choose # zoom factor 1 instead zoom[numpy.isinf(zoom)] = 1 output, return_value = _ni_support._get_output(output, input, shape=output_shape) zoom = numpy.asarray(zoom, dtype=numpy.float64) zoom = numpy.ascontiguousarray(zoom) _nd_image.zoom_shift(filtered, zoom, None, output, order, mode, cval) return return_value
def shift(input, shift, output=None, order=3, mode='constant', cval=0.0, prefilter=True): """ Shift an array. The array is shifted using spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. Parameters ---------- input : ndarray The input array. shift : float or sequence, optional The shift along the axes. If a float, `shift` is the same for each axis. If a sequence, `shift` should contain one value for each axis. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The shifted input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError('spline order not supported') input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') if input.ndim < 1: raise RuntimeError('input and output rank must be > 0') mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output=numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input) shift = _ni_support._normalize_sequence(shift, input.ndim) shift = [-ii for ii in shift] shift = numpy.asarray(shift, dtype=numpy.float64) if not shift.flags.contiguous: shift = shift.copy() _nd_image.zoom_shift(filtered, None, shift, output, order, mode, cval) return return_value
def affine_transform(input, matrix, offset=0.0, output_shape=None, output=None, order=3, mode='constant', cval=0.0, prefilter=True): """ Apply an affine transformation. The given matrix and offset are used to find for each point in the output the corresponding coordinates in the input by an affine transformation. The value of the input at those coordinates is determined by spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. Parameters ---------- input : ndarray The input array. matrix : ndarray The matrix must be two-dimensional or can also be given as a one-dimensional sequence or array. In the latter case, it is assumed that the matrix is diagonal. A more efficient algorithms is then applied that exploits the separability of the problem. offset : float or sequence, optional The offset into the array where the transform is applied. If a float, `offset` is the same for each axis. If a sequence, `offset` should contain one value for each axis. output_shape : tuple of ints, optional Shape tuple. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The transformed input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError('spline order not supported') input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') if output_shape is None: output_shape = input.shape if input.ndim < 1 or len(output_shape) < 1: raise RuntimeError('input and output rank must be > 0') mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output=numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input, shape=output_shape) matrix = numpy.asarray(matrix, dtype=numpy.float64) if matrix.ndim not in [1, 2] or matrix.shape[0] < 1: raise RuntimeError('no proper affine matrix provided') if matrix.shape[0] != input.ndim: raise RuntimeError('affine matrix has wrong number of rows') if matrix.ndim == 2 and matrix.shape[1] != output.ndim: raise RuntimeError('affine matrix has wrong number of columns') if not matrix.flags.contiguous: matrix = matrix.copy() offset = _ni_support._normalize_sequence(offset, input.ndim) offset = numpy.asarray(offset, dtype=numpy.float64) if offset.ndim != 1 or offset.shape[0] < 1: raise RuntimeError('no proper offset provided') if not offset.flags.contiguous: offset = offset.copy() if matrix.ndim == 1: _nd_image.zoom_shift(filtered, matrix, offset, output, order, mode, cval) else: _nd_image.geometric_transform(filtered, None, None, matrix, offset, output, order, mode, cval, None, None) return return_value
def _min_or_max_filter(input, size, footprint, structure, output, mode, cval, origin, minimum): if structure is None: if footprint is None: if size is None: raise RuntimeError("no footprint provided") separable= True else: footprint = numpy.asarray(footprint) footprint = footprint.astype(bool) if numpy.alltrue(numpy.ravel(footprint),axis=0): size = footprint.shape footprint = None separable = True else: separable = False else: structure = numpy.asarray(structure, dtype=numpy.float64) separable = False if footprint is None: footprint = numpy.ones(structure.shape, bool) else: footprint = numpy.asarray(footprint) footprint = footprint.astype(bool) input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError('Complex type not supported') output, return_value = _ni_support._get_output(output, input) origins = _ni_support._normalize_sequence(origin, input.ndim) if separable: sizes = _ni_support._normalize_sequence(size, input.ndim) axes = range(input.ndim) axes = [(axes[ii], sizes[ii], origins[ii]) for ii in range(len(axes)) if sizes[ii] > 1] if minimum: filter_ = minimum_filter1d else: filter_ = maximum_filter1d if len(axes) > 0: for axis, size, origin in axes: filter_(input, int(size), axis, output, mode, cval, origin) input = output else: output[...] = input[...] else: fshape = [ii for ii in footprint.shape if ii > 0] if len(fshape) != input.ndim: raise RuntimeError('footprint array has incorrect shape.') for origin, lenf in zip(origins, fshape): if (lenf // 2 + origin < 0) or (lenf // 2 + origin > lenf): raise ValueError('invalid origin') if not footprint.flags.contiguous: footprint = footprint.copy() if structure is not None: if len(structure.shape) != input.ndim: raise RuntimeError('structure array has incorrect shape') if not structure.flags.contiguous: structure = structure.copy() mode = _ni_support._extend_mode_to_code(mode) _nd_image.min_or_max_filter(input, footprint, structure, output, mode, cval, origins, minimum) return return_value
def shift(input, shift, output_type = None, output = None, order = 3, mode = 'constant', cval = 0.0, prefilter = True): """ Shift an array. The array is shifted using spline interpolation of the requested order. Points outside the boundaries of the input are filled according to the given mode. Parameters ---------- input : ndarray The input array. shift : float or sequence, optional The shift along the axes. If a float, `shift` is the same for each axis. If a sequence, `shift` should contain one value for each axis. output : ndarray or dtype, optional The array in which to place the output, or the dtype of the returned array. output_type : dtype, optional DEPRECATED, DO NOT USE. If used, a RuntimeError is raised. order : int, optional The order of the spline interpolation, default is 3. The order has to be in the range 0-5. mode : str, optional Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. cval : scalar, optional Value used for points outside the boundaries of the input if ``mode='constant'``. Default is 0.0 prefilter : bool, optional The parameter prefilter determines if the input is pre-filtered with `spline_filter` before interpolation (necessary for spline interpolation of order > 1). If False, it is assumed that the input is already filtered. Default is True. Returns ------- return_value : ndarray or None The shifted input. If `output` is given as a parameter, None is returned. """ if order < 0 or order > 5: raise RuntimeError, 'spline order not supported' input = numpy.asarray(input) if numpy.iscomplexobj(input): raise TypeError, 'Complex type not supported' if input.ndim < 1: raise RuntimeError, 'input and output rank must be > 0' mode = _extend_mode_to_code(mode) if prefilter and order > 1: filtered = spline_filter(input, order, output = numpy.float64) else: filtered = input output, return_value = _ni_support._get_output(output, input, output_type) shift = _ni_support._normalize_sequence(shift, input.ndim) shift = [-ii for ii in shift] shift = numpy.asarray(shift, dtype = numpy.float64) if not shift.flags.contiguous: shift = shift.copy() _nd_image.zoom_shift(filtered, None, shift, output, order, mode, cval) return return_value