Merge pull request #632 from ahojnnes/local-blocks

Refactor N-dimensial array resampling and add additional functionality
This commit is contained in:
Josh Warner
2013-07-31 14:10:18 -07:00
10 changed files with 222 additions and 175 deletions
+2 -2
View File
@@ -9,7 +9,7 @@ from ._geometric import (warp, warp_coords, estimate_transform,
SimilarityTransform, AffineTransform,
ProjectiveTransform, PolynomialTransform,
PiecewiseAffineTransform)
from ._warps import swirl, resize, rotate, rescale, downscale_local_means
from ._warps import swirl, resize, rotate, rescale, downscale_local_mean
from .pyramids import (pyramid_reduce, pyramid_expand,
pyramid_gaussian, pyramid_laplacian)
@@ -41,7 +41,7 @@ __all__ = ['hough_circle',
'resize',
'rotate',
'rescale',
'downscale_local_means',
'downscale_local_mean',
'pyramid_reduce',
'pyramid_expand',
'pyramid_gaussian',
+52 -98
View File
@@ -1,18 +1,18 @@
import numpy as np
from scipy import ndimage
from ._geometric import warp, SimilarityTransform, AffineTransform
from skimage.util.shape import view_as_blocks, _pad_asymmetric_zeros
from skimage.transform._geometric import (warp, SimilarityTransform,
AffineTransform)
from skimage.measure import block_reduce
def resize(image, output_shape, order=1, mode='constant', cval=0.):
"""Resize image to match a certain size.
Resize performs interpolation to upsample or downsample 2D arrays. For
downsampling any n-dimensional array by performing arithmetic sum or
arithmetic mean, see measure._sum_blocks.sum_blocks and
transform._warps.downscale_local_means respectively.
Performs interpolation to up-size or down-size images. For down-sampling
N-dimensional images by applying the arithmetic sum or mean, see
`skimage.measure.local_sum` and `skimage.transform.downscale_local_mean`,
respectively.
Parameters
----------
@@ -95,10 +95,10 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.):
def rescale(image, scale, order=1, mode='constant', cval=0.):
"""Scale image by a certain factor.
Rescale performs interpolation to upsample or downsample 2D arrays. For
downsampling any n-dimensional array by performing arithmetic sum or
arithmetic mean, see measure._sum_blocks.sum_blocks and
transform._warps.downscale_local_means respectively.
Performs interpolation to upscale or down-scale images. For down-sampling
N-dimensional images with integer factors by applying the arithmetic sum or
mean, see `skimage.measure.local_sum` and
`skimage.transform.downscale_local_mean`, respectively.
Parameters
----------
@@ -226,6 +226,47 @@ def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.):
mode=mode, cval=cval)
def downscale_local_mean(image, factors, cval=0):
"""Down-sample N-dimensional image by local averaging.
The image is padded with `cval` if it is not perfectly divisible by the
integer factors.
In contrast to the 2-D interpolation in `skimage.transform.resize` and
`skimage.transform.rescale` this function may be applied to N-dimensional
images and calculates the local mean of elements in each block of size
`factors` in the input image.
Parameters
----------
image : ndarray
N-dimensional input image.
factors : 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
integer factors.
Returns
-------
image : ndarray
Down-sampled image with same number of dimensions as input image.
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_mean(a, (2, 3))
array([[3.5, 4.],
[5.5, 4.5]])
"""
return block_reduce(image, factors, np.mean, cval)
def _swirl_mapping(xy, center, rotation, strength, radius):
x, y = xy.T
x0, y0 = center
@@ -296,90 +337,3 @@ def swirl(image, center=None, strength=1, radius=100, rotation=0,
return warp(image, _swirl_mapping, map_args=warp_args,
output_shape=output_shape,
order=order, mode=mode, cval=cval)
def _downsample(array, factors, sum=True):
"""Performs downsampling with integer factors.
Parameters
----------
array : ndarray
Input n-dimensional array.
factors: tuple
Tuple containing downsampling factor along each axis.
sum : bool
If True, downsampled element is the sum of its corresponding
constituent elements in the input array. Default is True.
Returns
-------
array : ndarray
Downsampled array with same number of dimensions as that of input
array.
"""
pad_size = []
if len(factors) != array.ndim:
raise ValueError("'factors' must have the same length "
"as 'array.shape'")
else:
for i in range(len(factors)):
if array.shape[i] % factors[i] != 0:
pad_size.append(factors[i] - (array.shape[i] % factors[i]))
else:
pad_size.append(0)
for i in range(len(pad_size)):
array = _pad_asymmetric_zeros(array, pad_size[i], i)
out = view_as_blocks(array, factors)
block_shape = out.shape
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.
This function is different from resize and rescale in the sense that they
use interpolation to upsample or downsample on a 2D array, while this
function performs only dawnsampling but on any n-dimensional array and
returns the arithmetic mean of elements in a block of size factors in the
original array.
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)
+7 -7
View File
@@ -6,7 +6,7 @@ from skimage.transform import (warp, warp_coords, rotate, resize, rescale,
AffineTransform,
ProjectiveTransform,
SimilarityTransform,
downscale_local_means)
downscale_local_mean)
from skimage import transform as tf, data, img_as_float
from skimage.color import rgb2gray
@@ -195,15 +195,15 @@ def test_warp_coords_example():
map_coordinates(image[:, :, 0], coords[:2])
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 = downscale_local_means(image1, (2, 3))
def test_downscale_local_mean():
image1 = np.arange(4 * 6).reshape(4, 6)
out1 = downscale_local_mean(image1, (2, 3))
expected1 = np.array([[ 4., 7.],
[ 16., 19.]])
assert_array_equal(expected1, out1)
image2 = np.arange(5*8).reshape(5, 8)
out2 = downscale_local_means(image2, (4, 5))
image2 = np.arange(5 * 8).reshape(5, 8)
out2 = downscale_local_mean(image2, (4, 5))
expected2 = np.array([[ 14. , 10.8],
[ 8.5, 5.7]])
assert_array_equal(expected2, out2)