From 1ac289c5887bca11b4278d855dca70f8fbaa26cc Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Fri, 17 Aug 2012 17:57:43 -0400 Subject: [PATCH 01/16] FIX: corrected docstring for transform.warp --- skimage/transform/_geometric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index c055247e..422737a7 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -721,7 +721,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, mode : string How to handle values outside the image borders. See `scipy.ndimage.map_coordinates` for detail. - cval : string + cval : float Used in conjunction with mode 'constant', the value outside the image boundaries. From 0749f8d9f008fcc32ab533bcc0c87c7cda521d7d Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Fri, 17 Aug 2012 17:59:28 -0400 Subject: [PATCH 02/16] FIX: transform.warp supports cval outside 0-1 range --- skimage/transform/_geometric.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 422737a7..2aecfe48 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -785,4 +785,9 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, # The spline filters sometimes return results outside [0, 1], # so clip to ensure valid data - return np.clip(mapped.squeeze(), 0, 1) + clipped = np.clip(mapped, 0, 1) + if mode == 'constant' and not (0 <= cval <= 1): + clipped[mapped == cval] = cval + + # Remove singleton dim introduced by atleast_3d + return clipped.squeeze() From e710fac03e1b8a4fb4bebba3e6dc732546da2722 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 19:11:58 -0400 Subject: [PATCH 03/16] Added test case for warp() when cval out of clipping range --- skimage/transform/_geometric.py | 1 + skimage/transform/tests/test_warps.py | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 2aecfe48..5baaeba1 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -786,6 +786,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, # The spline filters sometimes return results outside [0, 1], # so clip to ensure valid data clipped = np.clip(mapped, 0, 1) + if mode == 'constant' and not (0 <= cval <= 1): clipped[mapped == cval] = cval diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index f35b7f57..3ef5a2ee 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -2,7 +2,8 @@ from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np from skimage.transform import (warp, homography, fast_homography, - SimilarityTransform, ProjectiveTransform) + SimilarityTransform, ProjectiveTransform, + AffineTransform) from skimage import transform as tf, data, img_as_float from skimage.color import rgb2gray @@ -74,5 +75,12 @@ def test_swirl(): assert np.mean(np.abs(image - unswirled)) < 0.01 +def test_const_cval_out_of_range(): + img = np.random.randn(100, 100) + warped = warp(img, AffineTransform(translation=(10, 10)), cval=-10) + assert np.any(warped < 0) + + + if __name__ == "__main__": run_module_suite() From c22a176e8d8c368e108cef65144e062abbd87121 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 19:13:04 -0400 Subject: [PATCH 04/16] ENH: moved code generating coords out of warp() to _warp_coords --- skimage/transform/_geometric.py | 63 ++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 5baaeba1..9d394372 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -27,6 +27,45 @@ def _stackcopy(a, b): a[:] = b +def _build_coords(orows, ocols, bands, coord_transform_fn, + dtype='float64'): + """ + Return coords object suitable for scipy.ndimage.map_coordinates + + Parameters + ---------- + orows: number of output rows + ocols: number of output columns + bands: number of color bands (aka channels) + coord_transform_fn: something like GeometricTransform.inverse_map + interp_dtype: precision of interpolation e.g. 'float32' or 'float64' + + """ + + coords = np.empty(np.r_[3, (orows, ocols, bands)], dtype=dtype) + + # Reshape grid coordinates into a (P, 2) array of (x, y) pairs + tf_coords = np.indices((ocols, orows), dtype=dtype).reshape(2, -1).T + + # Map each (x, y) pair to the source image according to + # the user-provided mapping + tf_coords = coord_transform_fn(tf_coords) + + # Reshape back to a (2, M, N) coordinate grid + tf_coords = tf_coords.T.reshape((-1, ocols, orows)).swapaxes(1, 2) + + # Place the y-coordinate mapping + _stackcopy(coords[1, ...], tf_coords[0, ...]) + + # Place the x-coordinate mapping + _stackcopy(coords[0, ...], tf_coords[1, ...]) + + # colour-coordinate mapping + coords[2, ...] = range(bands) + + return coords + + class GeometricTransform(object): """Perform geometric transformations on a set of coordinates. @@ -753,30 +792,12 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, if output_shape is None: output_shape = ishape - coords = np.empty(np.r_[3, output_shape], dtype=float) - - ## Construct transformed coordinates - rows, cols = output_shape[:2] - # Reshape grid coordinates into a (P, 2) array of (x, y) pairs - tf_coords = np.indices((cols, rows), dtype=float).reshape(2, -1).T + def coord_transform_fn(*args): + return inverse_map(*args, **map_args) - # Map each (x, y) pair to the source image according to - # the user-provided mapping - tf_coords = inverse_map(tf_coords, **map_args) - - # Reshape back to a (2, M, N) coordinate grid - tf_coords = tf_coords.T.reshape((-1, cols, rows)).swapaxes(1, 2) - - # Place the y-coordinate mapping - _stackcopy(coords[1, ...], tf_coords[0, ...]) - - # Place the x-coordinate mapping - _stackcopy(coords[0, ...], tf_coords[1, ...]) - - # colour-coordinate mapping - coords[2, ...] = range(bands) + coords = _build_coords(rows, cols, bands, coord_transform_fn) # Prefilter not necessary for order 1 interpolation prefilter = order > 1 From ce200f570f2e7e4b67c24d42a0d0e6f3cdd95243 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 19:15:36 -0400 Subject: [PATCH 05/16] ENH: test_warp test case to make sure _warp_coords works for grey and rgb images --- skimage/transform/tests/test_warps.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 3ef5a2ee..2c2ecf53 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -1,6 +1,9 @@ +import sys from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np +import scipy.misc # -- greyscale lena that works without PIL png support + from skimage.transform import (warp, homography, fast_homography, SimilarityTransform, ProjectiveTransform, AffineTransform) @@ -66,6 +69,10 @@ def test_fast_homography(): def test_swirl(): + if not data.checkerboard().shape: + print >> sys.stderr, ('Failed to read image data.checkerboard()' + ' -- Skipping test_fast_homography') + return image = img_as_float(data.checkerboard()) swirl_params = {'radius': 80, 'rotation': 0, 'order': 2, 'mode': 'reflect'} @@ -81,6 +88,28 @@ def test_const_cval_out_of_range(): assert np.any(warped < 0) +def test_warp_identity(): + lena = scipy.misc.lena().astype('float32') / 255 + assert len(lena.shape) == 2 + assert np.allclose(lena, + warp(lena, AffineTransform(rotation=0))) + assert not np.allclose(lena, + warp(lena, AffineTransform(rotation=0.1))) + + rgb_lena = np.transpose( + np.asarray([lena, np.zeros_like(lena), lena]), + (1, 2, 0)) + warped_rgb_lena = warp(rgb_lena, AffineTransform(rotation=0.1)) + + assert np.allclose(rgb_lena, + warp(rgb_lena, AffineTransform(rotation=0))) + assert not np.allclose(rgb_lena, warped_rgb_lena) + # assert no cross-talk between bands + assert np.all(0 == warped_rgb_lena[:, :, 1]) + + + + if __name__ == "__main__": run_module_suite() From e3585ad17a98ec374a4baa453585bcecea3acbee Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 23:35:21 -0400 Subject: [PATCH 06/16] ENH: renamed and docd _build_coords -> warp_coords --- skimage/transform/_geometric.py | 107 ++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 40 deletions(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 9d394372..5dae2c7f 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -27,45 +27,6 @@ def _stackcopy(a, b): a[:] = b -def _build_coords(orows, ocols, bands, coord_transform_fn, - dtype='float64'): - """ - Return coords object suitable for scipy.ndimage.map_coordinates - - Parameters - ---------- - orows: number of output rows - ocols: number of output columns - bands: number of color bands (aka channels) - coord_transform_fn: something like GeometricTransform.inverse_map - interp_dtype: precision of interpolation e.g. 'float32' or 'float64' - - """ - - coords = np.empty(np.r_[3, (orows, ocols, bands)], dtype=dtype) - - # Reshape grid coordinates into a (P, 2) array of (x, y) pairs - tf_coords = np.indices((ocols, orows), dtype=dtype).reshape(2, -1).T - - # Map each (x, y) pair to the source image according to - # the user-provided mapping - tf_coords = coord_transform_fn(tf_coords) - - # Reshape back to a (2, M, N) coordinate grid - tf_coords = tf_coords.T.reshape((-1, ocols, orows)).swapaxes(1, 2) - - # Place the y-coordinate mapping - _stackcopy(coords[1, ...], tf_coords[0, ...]) - - # Place the x-coordinate mapping - _stackcopy(coords[0, ...], tf_coords[1, ...]) - - # colour-coordinate mapping - coords[2, ...] = range(bands) - - return coords - - class GeometricTransform(object): """Perform geometric transformations on a set of coordinates. @@ -737,6 +698,72 @@ def matrix_transform(coords, matrix): return ProjectiveTransform(matrix)(coords) +def warp_coords(orows, ocols, bands, coord_transform_fn, + dtype='float64'): + """ + Return `coords` ndarray suitable for `scipy.ndimage.map_coordinates`, which will yield an + image of shape (orows, ocols, bands) by drawing from source points according to the + `coord_transform_fn`. + + Parameters + ---------- + orows: number of output rows + ocols: number of output columns + bands: number of color bands (aka channels) + coord_transform_fn: something like GeometricTransform.inverse_map + dtype: dtype for return value (should probably be 'float32' or 'float64') + + Notes + ----- + This is a lower-level routine that produces the source coordinates used by `warp()`. + + It is provided separately from `warp` to give additional flexibility to users who would + like, for example, to re-use a particular coordinate mapping, to use specific dtypes at + various points along the the image-warping process, or to implement different + post-processing logic than `warp` performs after the call to `ndimage.map_coordinates`. + + + Examples + -------- + Produce a coordinate map that Shifts an image to the right: + + >>> from skimage import data + >>> from scipy.ndimage import map_coordinates + >>> + >>> def shift_right(xy): + ... xy[:, 0] -= 10 + ... return xy + >>> + >>> coords = warp_coords(30, 30, 3, shift_right) + >>> image = data.camera() + >>> warped_image = map_coordinates(coords, image) + + """ + + coords = np.empty(np.r_[3, (orows, ocols, bands)], dtype=dtype) + + # Reshape grid coordinates into a (P, 2) array of (x, y) pairs + tf_coords = np.indices((ocols, orows), dtype=dtype).reshape(2, -1).T + + # Map each (x, y) pair to the source image according to + # the user-provided mapping + tf_coords = coord_transform_fn(tf_coords) + + # Reshape back to a (2, M, N) coordinate grid + tf_coords = tf_coords.T.reshape((-1, ocols, orows)).swapaxes(1, 2) + + # Place the y-coordinate mapping + _stackcopy(coords[1, ...], tf_coords[0, ...]) + + # Place the x-coordinate mapping + _stackcopy(coords[0, ...], tf_coords[1, ...]) + + # colour-coordinate mapping + coords[2, ...] = range(bands) + + return coords + + def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, mode='constant', cval=0., reverse_map=None): """Warp an image according to a given coordinate transformation. @@ -797,7 +824,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, def coord_transform_fn(*args): return inverse_map(*args, **map_args) - coords = _build_coords(rows, cols, bands, coord_transform_fn) + coords = warp_coords(rows, cols, bands, coord_transform_fn) # Prefilter not necessary for order 1 interpolation prefilter = order > 1 From 96c022535495f6315a28c53e42f973ce1f6da7ef Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 23:37:03 -0400 Subject: [PATCH 07/16] ENH: test warp with data.lena instead of scipy.misc.lena --- skimage/transform/tests/test_warps.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 2c2ecf53..610c42a8 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -2,8 +2,6 @@ import sys from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np -import scipy.misc # -- greyscale lena that works without PIL png support - from skimage.transform import (warp, homography, fast_homography, SimilarityTransform, ProjectiveTransform, AffineTransform) @@ -71,7 +69,7 @@ def test_fast_homography(): def test_swirl(): if not data.checkerboard().shape: print >> sys.stderr, ('Failed to read image data.checkerboard()' - ' -- Skipping test_fast_homography') + ' -- Skipping test_swirl') return image = img_as_float(data.checkerboard()) @@ -89,7 +87,12 @@ def test_const_cval_out_of_range(): def test_warp_identity(): - lena = scipy.misc.lena().astype('float32') / 255 + lena = data.lena() + if not lena.shape: + print >> sys.stderr, ('Failed to read image data.lena()' + ' -- Skipping test_warp_identity') + return + lena = img_as_float(rgb2gray(lena)) assert len(lena.shape) == 2 assert np.allclose(lena, warp(lena, AffineTransform(rotation=0))) @@ -108,8 +111,5 @@ def test_warp_identity(): assert np.all(0 == warped_rgb_lena[:, :, 1]) - - - if __name__ == "__main__": run_module_suite() From 5cce39a44ace53223ac547fa50a90d6b9aaf0646 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Mon, 20 Aug 2012 23:44:31 -0400 Subject: [PATCH 08/16] ENH: remove call in tests to deprecated homography fn --- skimage/transform/tests/test_warps.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 610c42a8..72604b03 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -2,9 +2,10 @@ import sys from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np -from skimage.transform import (warp, homography, fast_homography, - SimilarityTransform, ProjectiveTransform, - AffineTransform) +from skimage.transform import (warp, fast_homography, + AffineTransform, + ProjectiveTransform, + SimilarityTransform) from skimage import transform as tf, data, img_as_float from skimage.color import rgb2gray @@ -31,7 +32,10 @@ def test_homography(): M = np.array([[np.cos(theta),-np.sin(theta),0], [np.sin(theta), np.cos(theta),4], [0, 0, 1]]) - x90 = homography(x, M, order=1) + + x90 = warp(x, + inverse_map=ProjectiveTransform(M).inverse, + order=1) assert_array_almost_equal(x90, np.rot90(x)) From c5dc55cd52e605b7a27be1dd6786cce6f85758ba Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Tue, 21 Aug 2012 16:09:47 -0400 Subject: [PATCH 09/16] ENH: better docstring and test for warp_coords --- skimage/transform/__init__.py | 2 +- skimage/transform/_geometric.py | 29 ++++++++++++++++++--------- skimage/transform/tests/test_warps.py | 18 ++++++++++++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/skimage/transform/__init__.py b/skimage/transform/__init__.py index 4721e7d1..b0eee512 100644 --- a/skimage/transform/__init__.py +++ b/skimage/transform/__init__.py @@ -3,7 +3,7 @@ from .radon_transform import * from .finite_radon_transform import * from ._project import homography as fast_homography from .integral import * -from ._geometric import (warp, estimate_transform, +from ._geometric import (warp, warp_coords, estimate_transform, SimilarityTransform, AffineTransform, ProjectiveTransform, PolynomialTransform) from ._warps import swirl, homography diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 5dae2c7f..0e590487 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -699,19 +699,28 @@ def matrix_transform(coords, matrix): def warp_coords(orows, ocols, bands, coord_transform_fn, - dtype='float64'): - """ - Return `coords` ndarray suitable for `scipy.ndimage.map_coordinates`, which will yield an - image of shape (orows, ocols, bands) by drawing from source points according to the - `coord_transform_fn`. + dtype=np.float64): + """Build the source coordinates for the output pixels of an image warp. Parameters ---------- - orows: number of output rows - ocols: number of output columns - bands: number of color bands (aka channels) - coord_transform_fn: something like GeometricTransform.inverse_map - dtype: dtype for return value (should probably be 'float32' or 'float64') + orows : int + number of output rows + ocols : int + number of output columns + bands : int + number of color bands (aka channels) + coord_transform_fn : callable like GeometricTransform.inverse_map + Return input coordinates for given output coordinates + dtype : np.dtype or string + dtype for return value (sane choices: float32 or float64) + + Returns + ------- + coords : (orows * ocols, ) array + Coordinates for `scipy.ndimage.map_coordinates`, that will yield + an image of shape (orows, ocols, bands) by drawing from source + points according to the `coord_transform_fn`. Notes ----- diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 72604b03..28350ff6 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -2,7 +2,7 @@ import sys from numpy.testing import assert_array_almost_equal, run_module_suite import numpy as np -from skimage.transform import (warp, fast_homography, +from skimage.transform import (warp, warp_coords, fast_homography, AffineTransform, ProjectiveTransform, SimilarityTransform) @@ -115,5 +115,21 @@ def test_warp_identity(): assert np.all(0 == warped_rgb_lena[:, :, 1]) +def test_warp_coords_example(): + from skimage import data + from scipy.ndimage import map_coordinates + def shift_right(xy): + print 'xyshape', xy.shape + xy[:, 0] -= 10 + return xy + + image = data.lena().astype(np.float32) + print 'testing' + print image.dtype, image.shape + coords = warp_coords(512, 512, 3, shift_right) + print 'warp_coords', coords.dtype, coords.shape + warped_image = map_coordinates(coords, image) + + if __name__ == "__main__": run_module_suite() From e859520872736a0564a896fd96aab8515fc1debe Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Tue, 21 Aug 2012 16:52:04 -0400 Subject: [PATCH 10/16] FIX: doctest of warp_coords --- skimage/transform/_geometric.py | 9 +++++---- skimage/transform/tests/test_warps.py | 9 +++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 0e590487..2fd2a694 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -717,7 +717,7 @@ def warp_coords(orows, ocols, bands, coord_transform_fn, Returns ------- - coords : (orows * ocols, ) array + coords : (3, orows, ocols, bands) array Coordinates for `scipy.ndimage.map_coordinates`, that will yield an image of shape (orows, ocols, bands) by drawing from source points according to the `coord_transform_fn`. @@ -744,12 +744,12 @@ def warp_coords(orows, ocols, bands, coord_transform_fn, ... return xy >>> >>> coords = warp_coords(30, 30, 3, shift_right) - >>> image = data.camera() - >>> warped_image = map_coordinates(coords, image) + >>> image = data.lena().astype(np.float32) + >>> warped_image = map_coordinates(image, coords) """ - coords = np.empty(np.r_[3, (orows, ocols, bands)], dtype=dtype) + coords = np.empty((3, orows, ocols, bands), dtype=dtype) # Reshape grid coordinates into a (P, 2) array of (x, y) pairs tf_coords = np.indices((ocols, orows), dtype=dtype).reshape(2, -1).T @@ -833,6 +833,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, def coord_transform_fn(*args): return inverse_map(*args, **map_args) + coords = warp_coords(rows, cols, bands, coord_transform_fn) # Prefilter not necessary for order 1 interpolation diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 28350ff6..3cde47ac 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -119,16 +119,13 @@ def test_warp_coords_example(): from skimage import data from scipy.ndimage import map_coordinates def shift_right(xy): - print 'xyshape', xy.shape xy[:, 0] -= 10 return xy image = data.lena().astype(np.float32) - print 'testing' - print image.dtype, image.shape - coords = warp_coords(512, 512, 3, shift_right) - print 'warp_coords', coords.dtype, coords.shape - warped_image = map_coordinates(coords, image) + assert 3 == image.shape[2] + coords = warp_coords(30, 30, 3, shift_right) + warped_image = map_coordinates(image[:, :, 0], coords[:2]) if __name__ == "__main__": From 47c0a506bcdaf2cec28a63bd3aceac970f312124 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Tue, 21 Aug 2012 16:53:04 -0400 Subject: [PATCH 11/16] ENH: warp_coords docstring --- skimage/transform/_geometric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 2fd2a694..d29baac0 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -717,7 +717,7 @@ def warp_coords(orows, ocols, bands, coord_transform_fn, Returns ------- - coords : (3, orows, ocols, bands) array + coords : (3, orows, ocols, bands) array of dtype `dtype` Coordinates for `scipy.ndimage.map_coordinates`, that will yield an image of shape (orows, ocols, bands) by drawing from source points according to the `coord_transform_fn`. From 3e6a6e37b1b9a4c6ddb6e86ef316b407f9f1de47 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Tue, 21 Aug 2012 16:55:08 -0400 Subject: [PATCH 12/16] ENH: stricter check on test_const_cval_out_of_range --- skimage/transform/tests/test_warps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 3cde47ac..226a0520 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -87,7 +87,7 @@ def test_swirl(): def test_const_cval_out_of_range(): img = np.random.randn(100, 100) warped = warp(img, AffineTransform(translation=(10, 10)), cval=-10) - assert np.any(warped < 0) + assert np.sum(warped < 0) == (2 * 100 * 10 - 10 * 10) def test_warp_identity(): From 8faf1489556649728be1a58fe2c38eef373e18ae Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Wed, 22 Aug 2012 09:08:14 -0400 Subject: [PATCH 13/16] FIX: wordwrap to 78 --- skimage/transform/_geometric.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index d29baac0..ce2eb7b6 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -724,12 +724,14 @@ def warp_coords(orows, ocols, bands, coord_transform_fn, Notes ----- - This is a lower-level routine that produces the source coordinates used by `warp()`. + This is a lower-level routine that produces the source coordinates used by + `warp()`. - It is provided separately from `warp` to give additional flexibility to users who would - like, for example, to re-use a particular coordinate mapping, to use specific dtypes at - various points along the the image-warping process, or to implement different - post-processing logic than `warp` performs after the call to `ndimage.map_coordinates`. + It is provided separately from `warp` to give additional flexibility to + users who would like, for example, to re-use a particular coordinate + mapping, to use specific dtypes at various points along the the + image-warping process, or to implement different post-processing logic + than `warp` performs after the call to `ndimage.map_coordinates`. Examples From acc86a55084d23d7ef3c0b3b9bdf8f2b2ac38288 Mon Sep 17 00:00:00 2001 From: James Bergstra Date: Wed, 22 Aug 2012 09:11:22 -0400 Subject: [PATCH 14/16] FIX: docstring mentions inverse instead of inverse_map --- skimage/transform/_geometric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index ce2eb7b6..f83f65d1 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -710,7 +710,7 @@ def warp_coords(orows, ocols, bands, coord_transform_fn, number of output columns bands : int number of color bands (aka channels) - coord_transform_fn : callable like GeometricTransform.inverse_map + coord_transform_fn : callable like GeometricTransform.inverse Return input coordinates for given output coordinates dtype : np.dtype or string dtype for return value (sane choices: float32 or float64) From 58bddb1cf2875b5c4a1ae74486ce43b8617706eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 24 Aug 2012 00:05:53 +0200 Subject: [PATCH 15/16] Remove empty line --- skimage/transform/_geometric.py | 1 - 1 file changed, 1 deletion(-) diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index f83f65d1..cec591a9 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -835,7 +835,6 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, def coord_transform_fn(*args): return inverse_map(*args, **map_args) - coords = warp_coords(rows, cols, bands, coord_transform_fn) # Prefilter not necessary for order 1 interpolation From f750e633c8aad5b499a851b39855cdae7fb02634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 24 Aug 2012 00:14:37 +0200 Subject: [PATCH 16/16] Fix test cases of warps --- skimage/transform/tests/test_warps.py | 50 ++++++++------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/skimage/transform/tests/test_warps.py b/skimage/transform/tests/test_warps.py index 226a0520..ac241722 100644 --- a/skimage/transform/tests/test_warps.py +++ b/skimage/transform/tests/test_warps.py @@ -1,6 +1,6 @@ -import sys 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, fast_homography, AffineTransform, @@ -28,10 +28,10 @@ def test_homography(): x = np.zeros((5, 5), dtype=np.uint8) x[1, 1] = 255 x = img_as_float(x) - theta = -np.pi/2 - M = np.array([[np.cos(theta),-np.sin(theta),0], - [np.sin(theta), np.cos(theta),4], - [0, 0, 1]]) + theta = -np.pi / 2 + M = np.array([[np.cos(theta), - np.sin(theta), 0], + [np.sin(theta), np.cos(theta), 4], + [0, 0, 1]]) x90 = warp(x, inverse_map=ProjectiveTransform(M).inverse, @@ -40,7 +40,7 @@ def test_homography(): def test_fast_homography(): - img = rgb2gray(data.lena()) + img = rgb2gray(data.lena()).astype(np.uint8) img = img[:, :100] theta = np.deg2rad(30) @@ -71,10 +71,6 @@ def test_fast_homography(): def test_swirl(): - if not data.checkerboard().shape: - print >> sys.stderr, ('Failed to read image data.checkerboard()' - ' -- Skipping test_swirl') - return image = img_as_float(data.checkerboard()) swirl_params = {'radius': 80, 'rotation': 0, 'order': 2, 'mode': 'reflect'} @@ -91,41 +87,25 @@ def test_const_cval_out_of_range(): def test_warp_identity(): - lena = data.lena() - if not lena.shape: - print >> sys.stderr, ('Failed to read image data.lena()' - ' -- Skipping test_warp_identity') - return - lena = img_as_float(rgb2gray(lena)) + lena = img_as_float(rgb2gray(data.lena())) assert len(lena.shape) == 2 - assert np.allclose(lena, - warp(lena, AffineTransform(rotation=0))) - assert not np.allclose(lena, - warp(lena, AffineTransform(rotation=0.1))) - - rgb_lena = np.transpose( - np.asarray([lena, np.zeros_like(lena), lena]), - (1, 2, 0)) + assert np.allclose(lena, warp(lena, AffineTransform(rotation=0))) + assert not np.allclose(lena, warp(lena, AffineTransform(rotation=0.1))) + rgb_lena = np.transpose(np.asarray([lena, np.zeros_like(lena), lena]), + (1, 2, 0)) warped_rgb_lena = warp(rgb_lena, AffineTransform(rotation=0.1)) - - assert np.allclose(rgb_lena, - warp(rgb_lena, AffineTransform(rotation=0))) + assert np.allclose(rgb_lena, warp(rgb_lena, AffineTransform(rotation=0))) assert not np.allclose(rgb_lena, warped_rgb_lena) # assert no cross-talk between bands assert np.all(0 == warped_rgb_lena[:, :, 1]) def test_warp_coords_example(): - from skimage import data - from scipy.ndimage import map_coordinates - def shift_right(xy): - xy[:, 0] -= 10 - return xy - image = data.lena().astype(np.float32) assert 3 == image.shape[2] - coords = warp_coords(30, 30, 3, shift_right) - warped_image = map_coordinates(image[:, :, 0], coords[:2]) + tform = SimilarityTransform(translation=(0, -10)) + coords = warp_coords(30, 30, 3, tform) + warped_image1 = map_coordinates(image[:, :, 0], coords[:2]) if __name__ == "__main__":