scikit-image
94 строки · 3.2 Кб
1import numpy as np2from ..util import view_as_blocks3
4
5def block_reduce(image, block_size=2, func=np.sum, cval=0, func_kwargs=None):6"""Downsample image by applying function `func` to local blocks.7
8This function is useful for max and mean pooling, for example.
9
10Parameters
11----------
12image : (M[, ...]) ndarray
13N-dimensional input image.
14block_size : array_like or int
15Array containing down-sampling integer factor along each axis.
16Default block_size is 2.
17func : callable
18Function object which is used to calculate the return value for each
19local block. This function must implement an ``axis`` parameter.
20Primary functions are ``numpy.sum``, ``numpy.min``, ``numpy.max``,
21``numpy.mean`` and ``numpy.median``. See also `func_kwargs`.
22cval : float
23Constant padding value if image is not perfectly divisible by the
24block size.
25func_kwargs : dict
26Keyword arguments passed to `func`. Notably useful for passing dtype
27argument to ``np.mean``. Takes dictionary of inputs, e.g.:
28``func_kwargs={'dtype': np.float16})``.
29
30Returns
31-------
32image : ndarray
33Down-sampled image with same number of dimensions as input image.
34
35Examples
36--------
37>>> from skimage.measure import block_reduce
38>>> image = np.arange(3*3*4).reshape(3, 3, 4)
39>>> image # doctest: +NORMALIZE_WHITESPACE
40array([[[ 0, 1, 2, 3],
41[ 4, 5, 6, 7],
42[ 8, 9, 10, 11]],
43[[12, 13, 14, 15],
44[16, 17, 18, 19],
45[20, 21, 22, 23]],
46[[24, 25, 26, 27],
47[28, 29, 30, 31],
48[32, 33, 34, 35]]])
49>>> block_reduce(image, block_size=(3, 3, 1), func=np.mean)
50array([[[16., 17., 18., 19.]]])
51>>> image_max1 = block_reduce(image, block_size=(1, 3, 4), func=np.max)
52>>> image_max1 # doctest: +NORMALIZE_WHITESPACE
53array([[[11]],
54[[23]],
55[[35]]])
56>>> image_max2 = block_reduce(image, block_size=(3, 1, 4), func=np.max)
57>>> image_max2 # doctest: +NORMALIZE_WHITESPACE
58array([[[27],
59[31],
60[35]]])
61"""
62
63if np.isscalar(block_size):64block_size = (block_size,) * image.ndim65elif len(block_size) != image.ndim:66raise ValueError(67"`block_size` must be a scalar or have " "the same length as `image.shape`"68)69
70if func_kwargs is None:71func_kwargs = {}72
73pad_width = []74for i in range(len(block_size)):75if block_size[i] < 1:76raise ValueError(77"Down-sampling factors must be >= 1. Use "78"`skimage.transform.resize` to up-sample an "79"image."80)81if image.shape[i] % block_size[i] != 0:82after_width = block_size[i] - (image.shape[i] % block_size[i])83else:84after_width = 085pad_width.append((0, after_width))86
87if np.any(np.asarray(pad_width)):88image = np.pad(89image, pad_width=pad_width, mode='constant', constant_values=cval90)91
92blocked = view_as_blocks(image, block_size)93
94return func(blocked, axis=tuple(range(image.ndim, blocked.ndim)), **func_kwargs)95