diff --git a/skimage/transform/__init__.py b/skimage/transform/__init__.py index a55d5df4..befcc23f 100644 --- a/skimage/transform/__init__.py +++ b/skimage/transform/__init__.py @@ -6,6 +6,6 @@ from ._geometric import (warp, warp_coords, estimate_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform, PiecewiseAffineTransform) -from ._warps import swirl, homography, resize, rotate +from ._warps import swirl, homography, resize, rotate, rescale from .pyramids import (pyramid_reduce, pyramid_expand, pyramid_gaussian, pyramid_laplacian) diff --git a/skimage/transform/_warps.py b/skimage/transform/_warps.py index 72f90050..71bc41b8 100644 --- a/skimage/transform/_warps.py +++ b/skimage/transform/_warps.py @@ -4,7 +4,7 @@ from ._geometric import (warp, SimilarityTransform, AffineTransform, def resize(image, output_shape, order=1, mode='constant', cval=0.): - """Resize image. + """Resize image to match a certain size. Parameters ---------- @@ -35,15 +35,15 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.): rows, cols = output_shape orig_rows, orig_cols = image.shape[0], image.shape[1] - rscale = float(orig_rows) / rows - cscale = float(orig_cols) / cols + row_scale = float(orig_rows) / rows + col_scale = float(orig_cols) / cols # 3 control points necessary to estimate exact AffineTransform src_corners = np.array([[1, 1], [1, rows], [cols, rows]]) - 1 dst_corners = np.zeros(src_corners.shape, dtype=np.double) # take into account that 0th pixel is at position (0.5, 0.5) - dst_corners[:, 0] = cscale * (src_corners[:, 0] + 0.5) - 0.5 - dst_corners[:, 1] = rscale * (src_corners[:, 1] + 0.5) - 0.5 + dst_corners[:, 0] = col_scale * (src_corners[:, 0] + 0.5) - 0.5 + dst_corners[:, 1] = row_scale * (src_corners[:, 1] + 0.5) - 0.5 tform = AffineTransform() tform.estimate(src_corners, dst_corners) @@ -52,6 +52,49 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.): mode=mode, cval=cval) +def rescale(image, scale, order=1, mode='constant', cval=0.): + """Scale image by a certain factor. + + Parameters + ---------- + image : ndarray + Input image. + scale : {float, tuple of floats} + Scale factors. Separate scale factors can be defined as + `(row_scale, col_scale)`. + + Returns + ------- + scaled : ndarray + Scaled version of the input. + + Other parameters + ---------------- + order : int + Order of splines used in interpolation. See + `scipy.ndimage.map_coordinates` for detail. + mode : string + How to handle values outside the image borders. See + `scipy.ndimage.map_coordinates` for detail. + cval : string + Used in conjunction with mode 'constant', the value outside + the image boundaries. + + """ + + try: + row_scale, col_scale = scale + except TypeError: + row_scale = col_scale = scale + + orig_rows, orig_cols = image.shape[0], image.shape[1] + rows = np.round(row_scale * orig_rows) + cols = np.round(col_scale * orig_cols) + output_shape = (rows, cols) + + return resize(image, output_shape, order=order, mode=mode, cval=cval) + + def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.): """Rotate image by a certain angle around its center. diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index b705ac47..69980b25 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -2,7 +2,7 @@ from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np from scipy.ndimage import map_coordinates -from skimage.transform import (warp, warp_coords, rotate, resize, +from skimage.transform import (warp, warp_coords, rotate, resize, rescale, AffineTransform, ProjectiveTransform, SimilarityTransform, homography) @@ -94,6 +94,24 @@ def test_resize(): assert_array_almost_equal(resized, ref) +def test_scale(): + # same scale factor + x = np.zeros((5, 5), dtype=np.double) + x[1, 1] = 1 + scaled = rescale(x, 2, order=0) + ref = np.zeros((10, 10)) + ref[2:4, 2:4] = 1 + assert_array_almost_equal(scaled, ref) + + # different scale factors + x = np.zeros((5, 5), dtype=np.double) + x[1, 1] = 1 + scaled = rescale(x, (2, 1), order=0) + ref = np.zeros((10, 5)) + ref[2:4, 1] = 1 + assert_array_almost_equal(scaled, ref) + + def test_swirl(): image = img_as_float(data.checkerboard())