mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 12:41:58 +08:00
114 lines
3.2 KiB
Python
114 lines
3.2 KiB
Python
__all__ = ['warp']
|
|
|
|
import numpy as np
|
|
from scipy import ndimage
|
|
from skimage.util import img_as_float
|
|
|
|
|
|
def _stackcopy(a, b):
|
|
"""Copy b into each color layer of a, such that::
|
|
|
|
a[:,:,0] = a[:,:,1] = ... = b
|
|
|
|
Parameters
|
|
----------
|
|
a : (M, N) or (M, N, P) ndarray
|
|
Target array.
|
|
b : (M, N)
|
|
Source array.
|
|
|
|
Notes
|
|
-----
|
|
Color images are stored as an ``MxNx3`` or ``MxNx4`` arrays.
|
|
|
|
"""
|
|
if a.ndim == 3:
|
|
a[:] = b[:, :, np.newaxis]
|
|
else:
|
|
a[:] = b
|
|
|
|
|
|
def warp(image, reverse_map, map_args={},
|
|
output_shape=None, order=1, mode='constant', cval=0.):
|
|
"""Warp an image according to a given coordinate transformation.
|
|
|
|
Parameters
|
|
----------
|
|
image : 2-D array
|
|
Input image.
|
|
reverse_map : callable xy = f(xy, **kwargs)
|
|
Reverse coordinate map. A function that transforms a Px2 array of
|
|
``(x, y)`` coordinates in the *output image* into their corresponding
|
|
coordinates in the *source image*. Also see examples below.
|
|
map_args : dict, optional
|
|
Keyword arguments passed to `reverse_map`.
|
|
output_shape : tuple (rows, cols)
|
|
Shape of the output image generated.
|
|
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.
|
|
|
|
Examples
|
|
--------
|
|
Shift an image to the right:
|
|
|
|
>>> from skimage import data
|
|
>>> image = data.camera()
|
|
>>>
|
|
>>> def shift_right(xy):
|
|
... xy[:, 0] -= 10
|
|
... return xy
|
|
>>>
|
|
>>> warp(image, shift_right)
|
|
|
|
"""
|
|
if image.ndim < 2:
|
|
raise ValueError("Input must have more than 1 dimension.")
|
|
|
|
image = np.atleast_3d(img_as_float(image))
|
|
ishape = np.array(image.shape)
|
|
bands = ishape[2]
|
|
|
|
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
|
|
|
|
# Map each (x, y) pair to the source image according to
|
|
# the user-provided mapping
|
|
tf_coords = reverse_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)
|
|
|
|
# Prefilter not necessary for order 1 interpolation
|
|
prefilter = order > 1
|
|
mapped = ndimage.map_coordinates(image, coords, prefilter=prefilter,
|
|
mode=mode, order=order, cval=cval)
|
|
|
|
# The spline filters sometimes return results outside [0, 1],
|
|
# so clip to ensure valid data
|
|
return np.clip(mapped.squeeze(), 0, 1)
|