From 486909c5f5cacf03c516c28ab9416660c395d0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 15 Jul 2013 21:51:55 +0200 Subject: [PATCH] Rename and combine local_* functions to block_reduce --- skimage/measure/__init__.py | 8 +- skimage/measure/block.py | 49 ++++ skimage/measure/local.py | 226 ------------------ .../tests/{test_local.py => test_block.py} | 35 ++- 4 files changed, 68 insertions(+), 250 deletions(-) create mode 100644 skimage/measure/block.py delete mode 100644 skimage/measure/local.py rename skimage/measure/tests/{test_local.py => test_block.py} (70%) diff --git a/skimage/measure/__init__.py b/skimage/measure/__init__.py index 26eb179c..423aa9a7 100755 --- a/skimage/measure/__init__.py +++ b/skimage/measure/__init__.py @@ -3,7 +3,7 @@ from ._regionprops import regionprops, perimeter from ._structural_similarity import structural_similarity from ._polygon import approximate_polygon, subdivide_polygon from .fit import LineModel, CircleModel, EllipseModel, ransac -from .local import local_sum, local_mean, local_median, local_min, local_max +from .block import block_reduce __all__ = ['find_contours', @@ -16,8 +16,4 @@ __all__ = ['find_contours', 'CircleModel', 'EllipseModel', 'ransac', - 'local_sum', - 'local_mean', - 'local_median', - 'local_min', - 'local_max'] + 'block_reduce'] diff --git a/skimage/measure/block.py b/skimage/measure/block.py new file mode 100644 index 00000000..7bef1220 --- /dev/null +++ b/skimage/measure/block.py @@ -0,0 +1,49 @@ +import numpy as np +from skimage.util import view_as_blocks, pad + + +def block_reduce(image, block_size, func=np.sum, cval=0): + """Down-sample image by applying function to local blocks. + + Parameters + ---------- + image : ndarray + N-dimensional input image. + block_size : array_like + Array containing down-sampling integer factor along each axis. + func : callable + Function object which is used to calculate the return value for each + local block. This function must implement an ``axis`` parameter such as + ``numpy.sum`` or ``numpy.min``. + cval : float + Constant padding value if image is not perfectly divisible by the + block size. + + Returns + ------- + image : ndarray + Down-sampled image with same number of dimensions as input image. + + """ + + if len(block_size) != image.ndim: + raise ValueError("`block_size` must have the same length " + "as `image.shape`.") + + pad_width = [] + for i in range(len(block_size)): + if image.shape[i] % block_size[i] != 0: + after_width = block_size[i] - (image.shape[i] % block_size[i]) + else: + after_width = 0 + pad_width.append((0, after_width)) + + image = pad(image, pad_width=pad_width, mode='constant', + constant_values=cval) + + out = view_as_blocks(image, block_size) + + for i in range(len(out.shape) // 2): + out = func(out, axis=-1) + + return out diff --git a/skimage/measure/local.py b/skimage/measure/local.py deleted file mode 100644 index bcb587cf..00000000 --- a/skimage/measure/local.py +++ /dev/null @@ -1,226 +0,0 @@ -import numpy as np -from skimage.util import view_as_blocks, pad - - -def _local_func(image, block_size, func, cval): - """Down-sample image by applying function to local blocks. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - func : object - Function object which is used to calculate the return value for each - local block, e.g. `numpy.sum`. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - """ - - if len(block_size) != image.ndim: - raise ValueError("`block_size` must have the same length " - "as `image.shape`.") - - pad_width = [] - for i in range(len(block_size)): - if image.shape[i] % block_size[i] != 0: - after_width = block_size[i] - (image.shape[i] % block_size[i]) - else: - after_width = 0 - pad_width.append((0, after_width)) - - image = pad(image, pad_width=pad_width, mode='constant', - constant_values=cval) - - out = view_as_blocks(image, block_size) - - for i in range(len(out.shape) // 2): - out = func(out, axis=-1) - - return out - - -def local_sum(image, block_size, cval=0): - """Sum elements in local blocks. - - The image is padded with zeros if it is not perfectly divisible by the - block size. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - Example - ------- - >>> a = np.arange(15).reshape(3, 5) - >>> a - image([[ 0, 1, 2, 3, 4], - [ 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14]]) - >>> block_sum(a, (2, 3)) - image([[21, 24], - [33, 27]]) - - """ - return _local_func(image, block_size, np.sum, cval) - - -def local_mean(image, block_size, cval=0): - """Average elements in local blocks. - - The image is padded with zeros if it is not perfectly divisible by the - block size. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - Example - ------- - >>> a = np.arange(15).reshape(3, 5) - >>> a - image([[ 0, 1, 2, 3, 4], - [ 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14]]) - >>> block_mean(a, (2, 3)) - array([[ 3.5, 4. ], - [ 5.5, 4.5]]) - - """ - return _local_func(image, block_size, np.mean, cval) - - -def local_median(image, block_size, cval=0): - """Median element in local blocks. - - The image is padded with zeros if it is not perfectly divisible by the - block size. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - Example - ------- - >>> a = np.array([[1, 5, 100], [0, 5, 1000]]) - >>> a - array([[ 1, 5, 100], - [ 0, 5, 1000]]) - >>> block_median(a, (2, 3)) - array([[ 5.]]) - - """ - return _local_func(image, block_size, np.median, cval) - - -def local_min(image, block_size, cval=0): - """Minimum element in local blocks. - - The image is padded with zeros if it is not perfectly divisible by the - block size. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - Example - ------- - >>> a = np.arange(15).reshape(3, 5) - >>> a - image([[ 0, 1, 2, 3, 4], - [ 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14]]) - >>> block_min(a, (2, 2)) - array([[0, 2, 0], - [0, 0, 0]]) - - """ - return _local_func(image, block_size, np.min, cval) - - -def local_max(image, block_size, cval=0): - """Maximum element in local blocks. - - The image is padded with zeros if it is not perfectly divisible by the - block size. - - Parameters - ---------- - image : ndarray - N-dimensional input image. - block_size : array_like - Array containing down-sampling integer factor along each axis. - cval : float, optional - Constant padding value if image is not perfectly divisible by the - block size. - - Returns - ------- - image : ndarray - Down-sampled image with same number of dimensions as input image. - - Example - ------- - >>> a = np.arange(15).reshape(3, 5) - >>> a - image([[ 0, 1, 2, 3, 4], - [ 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14]]) - >>> block_max(a, (2, 3)) - array([[ 7, 9], - [12, 14]]) - - """ - return _local_func(image, block_size, np.max, cval) diff --git a/skimage/measure/tests/test_local.py b/skimage/measure/tests/test_block.py similarity index 70% rename from skimage/measure/tests/test_local.py rename to skimage/measure/tests/test_block.py index fc01b7b9..a8bc62a9 100644 --- a/skimage/measure/tests/test_local.py +++ b/skimage/measure/tests/test_block.py @@ -1,78 +1,77 @@ import numpy as np from numpy.testing import assert_array_equal -from skimage.measure import (local_sum, local_mean, local_median, local_min, - local_max) +from skimage.measure import block_reduce -def test_local_sum(): +def test_block_reduce_sum(): image1 = np.arange(4 * 6).reshape(4, 6) - out1 = local_sum(image1, (2, 3)) + out1 = block_reduce(image1, (2, 3)) expected1 = np.array([[ 24, 42], [ 96, 114]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) - out2 = local_sum(image2, (3, 3)) + out2 = block_reduce(image2, (3, 3)) expected2 = np.array([[ 81, 108, 87], [174, 192, 138]]) assert_array_equal(expected2, out2) -def test_local_mean(): +def test_block_reduce_mean(): image1 = np.arange(4 * 6).reshape(4, 6) - out1 = local_mean(image1, (2, 3)) + out1 = block_reduce(image1, (2, 3), func=np.mean) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) - out2 = local_mean(image2, (4, 5)) + out2 = block_reduce(image2, (4, 5), func=np.mean) expected2 = np.array([[14. , 10.8], [ 8.5, 5.7]]) assert_array_equal(expected2, out2) -def test_local_median(): +def test_block_reduce_median(): image1 = np.arange(4 * 6).reshape(4, 6) - out1 = local_median(image1, (2, 3)) + out1 = block_reduce(image1, (2, 3), func=np.median) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) - out2 = local_median(image2, (4, 5)) + out2 = block_reduce(image2, (4, 5), func=np.median) expected2 = np.array([[ 14., 17.], [ 0., 0.]]) assert_array_equal(expected2, out2) image3 = np.array([[1, 5, 5, 5], [5, 5, 5, 1000]]) - out3 = local_median(image3, (2, 4)) + out3 = block_reduce(image3, (2, 4), func=np.median) assert_array_equal(5, out3) -def test_local_min(): +def test_block_reduce_min(): image1 = np.arange(4 * 6).reshape(4, 6) - out1 = local_min(image1, (2, 3)) + out1 = block_reduce(image1, (2, 3), func=np.min) expected1 = np.array([[ 0, 3], [12, 15]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) - out2 = local_min(image2, (4, 5)) + out2 = block_reduce(image2, (4, 5), func=np.min) expected2 = np.array([[0, 0], [0, 0]]) assert_array_equal(expected2, out2) -def test_local_max(): +def test_block_reduce_max(): image1 = np.arange(4 * 6).reshape(4, 6) - out1 = local_max(image1, (2, 3)) + out1 = block_reduce(image1, (2, 3), func=np.max) expected1 = np.array([[ 8, 11], [20, 23]]) assert_array_equal(expected1, out1) image2 = np.arange(5 * 8).reshape(5, 8) - out2 = local_max(image2, (4, 5)) + out2 = block_reduce(image2, (4, 5), func=np.max) expected2 = np.array([[28, 31], [36, 39]]) assert_array_equal(expected2, out2)