mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-23 13:10:18 +08:00
Clip to min and max range of input image, add missing clip parameter to other functions
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user