Clip to min and max range of input image, add missing clip parameter to other functions

This commit is contained in:
Johannes Schönberger
2014-12-22 20:28:00 +01:00
parent 6b0c3f7ab5
commit 0ae8c4a74b
4 changed files with 70 additions and 47 deletions
+28 -24
View File
@@ -994,6 +994,24 @@ def warp_coords(coord_map, shape, dtype=np.float64):
return coords
def _clip_warp_output(input_image, output_image, clip, mode, order, cval):
"""Clip output image to range of values of input image, considering the
parameters of a call to warp.
"""
if clip and order != 0:
min_val = input_image.min()
max_val = input_image.max()
clipped = np.clip(output_image, min_val, max_val)
if mode == 'constant' and not (min_val <= cval <= max_val):
clipped[output_image == cval] = cval
return clipped
return output_image
def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
mode='constant', cval=0., clip=True):
"""Warp an image according to a given coordinate transformation.
@@ -1055,17 +1073,17 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
Used in conjunction with mode 'constant', the value outside
the image boundaries.
clip : bool, optional
Whether to clip the output to the float range of ``[0, 1]``, or
``[-1, 1]`` for input images with negative values. This is enabled by
default, since higher order interpolation may produce values outside
the given input range.
Whether to clip the output to the range of values of the input image.
This is enabled by default, since higher order interpolation may
produce values outside the given input range.
Notes
-----
In case of a `SimilarityTransform`, `AffineTransform` and
`ProjectiveTransform` and `order` in [0, 3] this function uses the
underlying transformation matrix to warp the image with a much faster
routine.
- The input image is converted to a `double` image.
- In case of a `SimilarityTransform`, `AffineTransform` and
`ProjectiveTransform` and `order` in [0, 3] this function uses the
underlying transformation matrix to warp the image with a much faster
routine.
Examples
--------
@@ -1124,7 +1142,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
"""
image = img_as_float(image)
image = image.astype(np.double)
input_shape = np.array(image.shape)
if output_shape is None:
@@ -1219,21 +1237,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
out = ndimage.map_coordinates(image, coords, prefilter=prefilter,
mode=mode, order=order, cval=cval)
if clip:
# The spline filters sometimes return results outside [0, 1],
# so clip to ensure valid data
if np.min(image) < 0:
min_val = -1
else:
min_val = 0
max_val = 1
clipped = np.clip(out, min_val, max_val)
if mode == 'constant' and not (0 <= cval <= 1):
clipped[out == cval] = cval
out = clipped
out = _clip_warp_output(image, out, clip, mode, order, cval)
return out
+35 -16
View File
@@ -2,11 +2,11 @@ import numpy as np
from scipy import ndimage
from skimage.transform._geometric import (warp, SimilarityTransform,
AffineTransform)
AffineTransform, _clip_warp_output)
from skimage.measure import block_reduce
def resize(image, output_shape, order=1, mode='constant', cval=0.):
def resize(image, output_shape, order=1, mode='constant', cval=0, clip=True):
"""Resize image to match a certain size.
Performs interpolation to up-size or down-size images. For down-sampling
@@ -40,6 +40,10 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.):
cval : float, optional
Used in conjunction with mode 'constant', the value outside
the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image.
This is enabled by default, since higher order interpolation may
produce values outside the given input range.
Examples
--------
@@ -71,8 +75,10 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.):
coord_map = np.array([map_rows, map_cols, map_dims])
out = ndimage.map_coordinates(image, coord_map, order=order, mode=mode,
cval=cval)
out = ndimage.map_coordinates(image, coord_map, order=order,
mode=mode, cval=cval)
out = _clip_warp_output(image, out, clip, mode, order, cval)
else: # 2-dimensional interpolation
@@ -87,12 +93,12 @@ def resize(image, output_shape, order=1, mode='constant', cval=0.):
tform.estimate(src_corners, dst_corners)
out = warp(image, tform, output_shape=output_shape, order=order,
mode=mode, cval=cval)
mode=mode, cval=cval, clip=clip)
return out
def rescale(image, scale, order=1, mode='constant', cval=0.):
def rescale(image, scale, order=1, mode='constant', cval=0, clip=True):
"""Scale image by a certain factor.
Performs interpolation to upscale or down-scale images. For down-sampling
@@ -124,6 +130,10 @@ def rescale(image, scale, order=1, mode='constant', cval=0.):
cval : float, optional
Used in conjunction with mode 'constant', the value outside
the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image.
This is enabled by default, since higher order interpolation may
produce values outside the given input range.
Examples
--------
@@ -147,11 +157,12 @@ def rescale(image, scale, order=1, mode='constant', cval=0.):
cols = np.round(col_scale * orig_cols)
output_shape = (rows, cols)
return resize(image, output_shape, order=order, mode=mode, cval=cval)
return resize(image, output_shape, order=order, mode=mode, cval=cval,
clip=clip)
def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.,
center=None):
def rotate(image, angle, resize=False, center=None, order=1, mode='constant',
cval=0, clip=True):
"""Rotate image by a certain angle around its center.
Parameters
@@ -164,6 +175,9 @@ def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.,
Determine whether the shape of the output image will be automatically
calculated, so the complete rotated image exactly fits. Default is
False.
center : iterable of length 2
The rotation center. If ``center=None``, the image is rotated around
its center, i.e. ``center=(rows / 2 - 0.5, cols / 2 - 0.5)``.
Returns
-------
@@ -181,9 +195,10 @@ def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.,
cval : float, optional
Used in conjunction with mode 'constant', the value outside
the image boundaries.
center : iterable of length 2
The rotation center. If ``center=None``, the image is rotated around
its center, i.e. ``center=(rows / 2 - 0.5, cols / 2 - 0.5)``.
clip : bool, optional
Whether to clip the output to the range of values of the input image.
This is enabled by default, since higher order interpolation may
produce values outside the given input range.
Examples
--------
@@ -230,10 +245,10 @@ def rotate(image, angle, resize=False, order=1, mode='constant', cval=0.,
tform = tform4 + tform
return warp(image, tform, output_shape=output_shape, order=order,
mode=mode, cval=cval)
mode=mode, cval=cval, clip=clip)
def downscale_local_mean(image, factors, cval=0):
def downscale_local_mean(image, factors, cval=0, clip=True):
"""Down-sample N-dimensional image by local averaging.
The image is padded with `cval` if it is not perfectly divisible by the
@@ -294,7 +309,7 @@ def _swirl_mapping(xy, center, rotation, strength, radius):
def swirl(image, center=None, strength=1, radius=100, rotation=0,
output_shape=None, order=1, mode='constant', cval=0):
output_shape=None, order=1, mode='constant', cval=0, clip=True):
"""Perform a swirl transformation.
Parameters
@@ -330,6 +345,10 @@ def swirl(image, center=None, strength=1, radius=100, rotation=0,
cval : float, optional
Used in conjunction with mode 'constant', the value outside
the image boundaries.
clip : bool, optional
Whether to clip the output to the range of values of the input image.
This is enabled by default, since higher order interpolation may
produce values outside the given input range.
"""
@@ -343,4 +362,4 @@ 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)
order=order, mode=mode, cval=cval, clip=clip)
-1
View File
@@ -3,7 +3,6 @@
#cython: nonecheck=False
#cython: wraparound=False
import numpy as np
cimport numpy as cnp
from skimage._shared.interpolation cimport (nearest_neighbour_interpolation,
bilinear_interpolation,
+7 -6
View File
@@ -75,14 +75,15 @@ def test_warp_nd():
def test_warp_clip():
x = 2 * np.ones((5, 5), dtype=np.double)
matrix = np.eye(3)
x = np.zeros((5, 5), dtype=np.double)
x[2, 2] = 1
outx = warp(x, matrix, order=0, clip=False)
assert_almost_equal(x, outx)
outx = rescale(x, 3, order=3, clip=False)
assert outx.min() < 0
outx = warp(x, matrix, order=0, clip=True)
assert_almost_equal(x / 2, outx)
outx = rescale(x, 3, order=3, clip=True)
assert_almost_equal(outx.min(), 0)
assert_almost_equal(outx.max(), 1)
def test_homography():