def histogram(source, selem=None, sink=None, mask=None, max_bin=None): """Normalized sliding window histogram Arguments --------- source : array Input array. selem : array Structure element. If None, use a cube of size 3. sink : array Output array. If None, a new array is allocated. mask : array Optional mask, if None, the complete source is used. Pixels on the mask are zero in the output. max_bin : int or None Maximal number of bins. Returns ------- sink : array Array of the source shape pluse on extra dimension for the histogram at each pixel. """ if max_bin is None: max_bin = io.max_value(source.dtype) if max_bin >= 2**16: raise ValueError( 'The histograms are to large for this code to be efficient!') parameter_index = [max_bin] return _apply_code(code.histogram, code.histogram_masked, max_bin=max_bin, sink_shape_per_pixel=(max_bin, ), sink_dtype=float, source=source, selem=selem, sink=sink, mask=mask, parameter_index=parameter_index)
def _apply_code(function, function_mask, source, selem=None, sink=None, sink_dtype=None, sink_shape_per_pixel=None, mask=None, max_bin=None, parameter_index=None, parameter_float=None): """Helper to apply code.""" selem = _initialize_selem(selem, source.ndim) if source.ndim > 3: raise ValueError('Source dimension %d not supported!' % source.ndim) if source.ndim != 3: source = np.asarray(source) shape_remove = [d for d in range(source.ndim, 3)] source = source.view() source.shape = source.shape + (1, ) * (3 - source.ndim) if mask is not None: mask = np.asarray(mask) mask = mask.view() mask.shape = mask.shape + (1, ) * (3 - mask.ndim) selem = selem.view() selem.shape = selem.shape + (1, ) * (3 - selem.ndim) else: shape_remove = [] if source.dtype not in (np.uint8, np.uint16, np.int, np.int16, np.int32, np.int64, np.uint32, np.uint64, np.bool): raise ValueError( 'The rank filter requires a source of integer type, found %r!' % source.dtype) if mask is not None: if mask.dtype == bool: mask = mask.view('uint8') if mask.shape != source.shape: raise ValueError( 'Source shape %r and mask shape %r do not match!' % (source.shape, mask.shape)) if source is sink: raise ValueError("Cannot perform rank filter in place!") if sink_shape_per_pixel is None: shape_per_pixel = (1, ) shape_remove += [3] else: shape_per_pixel = sink_shape_per_pixel if sink is None: if sink_dtype is None: sink_dtype = source.dtype sink = np.zeros(source.shape + shape_per_pixel, dtype=sink_dtype) else: if shape_per_pixel != (1, ): if sink.shape != source.shape + shape_per_pixel: raise ValueError( 'The sink of shape %r does not have expected shape %r!' % (sink.shape, source.shape + shape_per_pixel)) if sink.shape != source.shape + shape_per_pixel: sink = sink.reshape(source.shape + shape_per_pixel) if sink.dtype == bool: s = sink.view('uint8') else: s = sink if max_bin is None: max_bin = io.max_value(source.dtype) if max_bin >= 2**16: raise ValueError( 'The histograms are to large for this code to be efficient!') bitdepth = int(np.log2(max_bin)) if bitdepth > 12: warnings.warn( "Bitdepth of %d may result in bad rank filter performance." % bitdepth) if parameter_index is None: parameter_index = np.zeros(0, dtype=int) parameter_index = np.asarray([parameter_index], dtype=int).flatten() if parameter_float is None: parameter_float = np.zeros(0, dtype=float) parameter_float = np.asarray([parameter_float], dtype=float).flatten() #print(source.__class__, source.dtype, s.__class__, s.dtype, selem.dtype, mask.dtype, max_bin) if mask is None: function(source=source, selem=selem, sink=s, max_bin=max_bin, p=parameter_index, q=parameter_float) else: function_mask(source=source, selem=selem, mask=mask, sink=s, max_bin=max_bin, p=parameter_index, q=parameter_float) if len(shape_remove) > 0: shape = tuple(s for d, s in enumerate(sink.shape) if d not in shape_remove) sink = sink.reshape(shape) return sink