diff --git a/doc/source/user_guide/data_types.txt b/doc/source/user_guide/data_types.txt index 43ea8e9b..258314af 100644 --- a/doc/source/user_guide/data_types.txt +++ b/doc/source/user_guide/data_types.txt @@ -134,7 +134,11 @@ dtype range:: Here, the ``in_range`` argument is set to the maximum range for a 10-bit image. By default, ``rescale_intensity`` stretches the values of ``in_range`` to match -the range of the dtype. +the range of the dtype. ``rescale_intensity`` also accepts strings as inputs +to ``in_range`` and ``out_range``, so the example above could also be written +as:: + + >>> image = exposure.rescale_intensity(img10bit, in_range='uint10') Note about negative values diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py index 31d9a57f..ce066d68 100644 --- a/skimage/exposure/exposure.py +++ b/skimage/exposure/exposure.py @@ -7,8 +7,16 @@ from skimage._shared.utils import deprecated __all__ = ['histogram', 'cumulative_distribution', 'equalize', - 'rescale_intensity', 'adjust_gamma', - 'adjust_log', 'adjust_sigmoid'] + 'rescale_intensity', 'adjust_gamma', 'adjust_log', 'adjust_sigmoid'] + + +DTYPE_RANGE = dtype_range.copy() +DTYPE_RANGE.update((d.__name__, limits) for d, limits in dtype_range.items()) +DTYPE_RANGE.update({'uint10': (0, 2**10 - 1), + 'uint12': (0, 2**12 - 1), + 'uint14': (0, 2**14 - 1), + 'bool': dtype_range[np.bool_], + 'float': dtype_range[np.float64]}) def histogram(image, nbins=256): @@ -143,14 +151,15 @@ def rescale_intensity(image, in_range=None, out_range=None): ---------- image : array Image array. - in_range : 2-tuple (float, float) + in_range : 2-tuple (float, float) or str Min and max *allowed* intensity values of input image. If None, the *allowed* min/max values are set to the *actual* min/max values in the - input image. - out_range : 2-tuple (float, float) + input image. Intensity values outside this range are clipped. + If string, use data limits of dtype specified by the string. + out_range : 2-tuple (float, float) or str Min and max intensity values of output image. If None, use the min/max intensities of the image data type. See `skimage.util.dtype` for - details. + details. If string, use data limits of dtype specified by the string. Returns ------- @@ -201,11 +210,16 @@ def rescale_intensity(image, in_range=None, out_range=None): if in_range is None: imin = np.min(image) imax = np.max(image) + elif in_range in DTYPE_RANGE: + imin, imax = DTYPE_RANGE[in_range] else: imin, imax = in_range - if out_range is None: - omin, omax = dtype_range[dtype] + if out_range is None or out_range in DTYPE_RANGE: + out_range = dtype if out_range is None else out_range + if out_range is None: + out_range + omin, omax = DTYPE_RANGE[out_range] if imin >= 0: omin = 0 else: diff --git a/skimage/exposure/tests/test_exposure.py b/skimage/exposure/tests/test_exposure.py index e6610874..2fc1f750 100644 --- a/skimage/exposure/tests/test_exposure.py +++ b/skimage/exposure/tests/test_exposure.py @@ -44,6 +44,11 @@ def check_cdf_slope(cdf): # Test rescale intensity # ====================== + +uint10_max = 2**10 - 1 +uint16_max = 2**16 - 1 + + def test_rescale_stretch(): image = np.array([51, 102, 153], dtype=np.uint8) out = exposure.rescale_intensity(image) @@ -76,6 +81,18 @@ def test_rescale_out_range(): assert_close(out, [0, 63, 127]) +def test_rescale_named_in_range(): + image = np.array([0, uint10_max, uint10_max + 100], dtype=np.uint16) + out = exposure.rescale_intensity(image, in_range='uint10') + assert_close(out, [0, uint16_max, uint16_max]) + + +def test_rescale_named_out_range(): + image = np.array([0, uint16_max], dtype=np.uint16) + out = exposure.rescale_intensity(image, out_range='uint10') + assert_close(out, [0, uint10_max]) + + # Test adaptive histogram equalization # ====================================