From 6f9d7c5d1af916f6d4d96d6e8debe891ccfdbe83 Mon Sep 17 00:00:00 2001 From: Ankit Agrawal Date: Thu, 4 Jul 2013 16:56:37 +0800 Subject: [PATCH] Cleaning up downsampling for integer factors --- skimage/measure/__init__.py | 4 +- skimage/measure/_sum_blocks.py | 34 ++++++++++++++ skimage/measure/tests/test_sum_blocks.py | 16 +++++++ skimage/transform/__init__.py | 1 - skimage/transform/_warps.py | 56 +++++++++++++++++------- skimage/transform/tests/test_warps.py | 22 +++------- 6 files changed, 97 insertions(+), 36 deletions(-) create mode 100644 skimage/measure/_sum_blocks.py create mode 100644 skimage/measure/tests/test_sum_blocks.py diff --git a/skimage/measure/__init__.py b/skimage/measure/__init__.py index 89f707c1..a9fbae24 100755 --- a/skimage/measure/__init__.py +++ b/skimage/measure/__init__.py @@ -3,6 +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 ._sum_blocks import sum_blocks __all__ = ['find_contours', @@ -14,4 +15,5 @@ __all__ = ['find_contours', 'LineModel', 'CircleModel', 'EllipseModel', - 'ransac'] + 'ransac', + 'sum_blocks'] diff --git a/skimage/measure/_sum_blocks.py b/skimage/measure/_sum_blocks.py new file mode 100644 index 00000000..e6a478e5 --- /dev/null +++ b/skimage/measure/_sum_blocks.py @@ -0,0 +1,34 @@ +from ..transform._warps import _downsample + + +def sum_blocks(array, factors): + """Sums the elements in blocks of integer factors and pads the original + array with zeroes if the dimensions are not perfectly divisible by factors. + + Parameters + ---------- + array : ndarray + Input n-dimensional array. + factors: tuple + Tuple containing integer values representing block length along each + axis. + + Returns + ------- + array : ndarray + Downsampled array with same number of dimensions as that of input + array. + + Example + ------- + >>> a = np.arange(15).reshape(3, 5) + >>> a + array([[ 0, 1, 2, 3, 4], + [ 5, 6, 7, 8, 9], + [10, 11, 12, 13, 14]]) + >>> sum_blocks(a, (2,3)) + array([[21, 24], + [33, 27]]) + + """ + return _downsample(array, factors) diff --git a/skimage/measure/tests/test_sum_blocks.py b/skimage/measure/tests/test_sum_blocks.py new file mode 100644 index 00000000..b4910495 --- /dev/null +++ b/skimage/measure/tests/test_sum_blocks.py @@ -0,0 +1,16 @@ +import numpy as np +from numpy.testing import assert_array_equal +from skimage.measure._sum_blocks import sum_blocks + +def test_downsample_sum_blocks(): + """Verifying downsampling of an array with expected result in sum mode""" + image1 = np.arange(4*6).reshape(4, 6) + out1 = sum_blocks(image1, (2, 3)) + expected1 = np.array([[ 24, 42], + [ 96, 114]]) + assert_array_equal(expected1, out1) + image2 = np.arange(5*8).reshape(5, 8) + out2 = sum_blocks(image2, (3, 3)) + expected2 = np.array([[ 81, 108, 87], + [174, 192, 138]]) + assert_array_equal(expected2, out2) diff --git a/skimage/transform/__init__.py b/skimage/transform/__init__.py index dcd39c31..311801be 100644 --- a/skimage/transform/__init__.py +++ b/skimage/transform/__init__.py @@ -9,7 +9,6 @@ from ._geometric import (warp, warp_coords, estimate_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) - from ._warps import swirl, resize, rotate, rescale, downscale_local_means from .pyramids import (pyramid_reduce, pyramid_expand, pyramid_gaussian, pyramid_laplacian) diff --git a/skimage/transform/_warps.py b/skimage/transform/_warps.py index 640a451d..cca5d1d9 100644 --- a/skimage/transform/_warps.py +++ b/skimage/transform/_warps.py @@ -287,7 +287,7 @@ def swirl(image, center=None, strength=1, radius=100, rotation=0, order=order, mode=mode, cval=cval) -def _downsample(array, factors, mode='sum'): +def _downsample(array, factors, sum=True): """Performs downsampling with integer factors. Parameters @@ -296,10 +296,9 @@ def _downsample(array, factors, mode='sum'): Input n-dimensional array. factors: tuple Tuple containing downsampling factor along each axis. - mode : string - Decides whether the downsampled element is the sum or mean - of its corresponding constituent elements in the input array. Default - is 'sum'. + sum : bool + If True, downsampled element is the sum of its corresponding + constituent elements in the input array. Default is True. Returns ------- @@ -307,17 +306,6 @@ def _downsample(array, factors, mode='sum'): Downsampled array with same number of dimensions as that of input array. - Example - ------- - >>> a = np.arange(15).reshape(3, 5) - >>> a - array([[ 0, 1, 2, 3, 4], - [ 5, 6, 7, 8, 9], - [10, 11, 12, 13, 14]]) - >>> downsample(a, (2,3)) - array([[21, 24], - [33, 27]]) - """ pad_size = [] @@ -337,10 +325,44 @@ def _downsample(array, factors, mode='sum'): out = view_as_blocks(array, factors) block_shape = out.shape - if mode == 'sum': + if sum: for i in range(len(block_shape) // 2): out = out.sum(-1) else: for i in range(len(block_shape) // 2): out = out.mean(-1) return out + + +def downscale_local_means(array, factors): + """Downsamples the array in blocks of input integer factors after padding + the original array with zeroes if the dimensions are not perfectly + divisible by factors and replaces it with mean i.e. average value. + + Parameters + ---------- + array : ndarray + Input n-dimensional array. + factors: tuple + Tuple containing integer values representing block length along each + axis. + + Returns + ------- + array : ndarray + Downsampled array with same number of dimensions as that of input + array. + + Example + ------- + >>> a = np.arange(15).reshape(3, 5) + >>> a + array([[ 0, 1, 2, 3, 4], + [ 5, 6, 7, 8, 9], + [10, 11, 12, 13, 14]]) + >>> downscale_local_means(a, (2,3)) + array([[3.5, 4.], + [5.5, 4.5]]) + + """ + return _downsample(array, factors, False) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index a2cd2b05..88ede530 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -5,7 +5,8 @@ from scipy.ndimage import map_coordinates from skimage.transform import (warp, warp_coords, rotate, resize, rescale, AffineTransform, ProjectiveTransform, - SimilarityTransform) + SimilarityTransform, + downscale_local_means) from skimage import transform as tf, data, img_as_float from skimage.color import rgb2gray @@ -193,29 +194,16 @@ def test_warp_coords_example(): coords = warp_coords(tform, (30, 30, 3)) map_coordinates(image[:, :, 0], coords[:2]) -def test_downsample_sum(): - """Verifying downsampling of an array with expected result in sum mode""" - image1 = np.arange(4*6).reshape(4, 6) - out1 = tf.downsample(image1, (2, 3)) - expected1 = np.array([[ 24, 42], - [ 96, 114]]) - assert_array_equal(expected1, out1) - image2 = np.arange(5*8).reshape(5, 8) - out2 = tf.downsample(image2, (3, 3)) - expected2 = np.array([[ 81, 108, 87], - [174, 192, 138]]) - assert_array_equal(expected2, out2) - -def test_downsample_mean(): +def test_downscale_local_means(): """Verifying downsampling of an array with expected result in mean mode""" image1 = np.arange(4*6).reshape(4, 6) - out1 = tf.downsample(image1, (2, 3), 'mean') + out1 = downscale_local_means(image1, (2, 3)) expected1 = np.array([[ 4., 7.], [ 16., 19.]]) assert_array_equal(expected1, out1) image2 = np.arange(5*8).reshape(5, 8) - out2 = tf.downsample(image2, (4, 5), 'mean') + out2 = downscale_local_means(image2, (4, 5)) expected2 = np.array([[ 14. , 10.8], [ 8.5, 5.7]]) assert_array_equal(expected2, out2)