diff --git a/doc/source/user_guide/transforming_image_data.rst b/doc/source/user_guide/transforming_image_data.rst index 883cda41..741cb229 100644 --- a/doc/source/user_guide/transforming_image_data.rst +++ b/doc/source/user_guide/transforming_image_data.rst @@ -21,7 +21,7 @@ green and blue channels. However, other color models are widely used, such as the `HSV color model `_, where hue, saturation and value are independent channels, or the `CMYK model -`_ used for printing. +`_ used for printing. :mod:`skimage.color` provides utility functions to convert images to and from different color spaces. Integer-type arrays can be @@ -46,7 +46,7 @@ Conversion from RGBA to RGB - Removing alpha channel through alpha blending ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Converting an RGBA image to an RGB image by alpha blending it with a -background is realized with :func:`rgba2rgb` :: +background is realized with :func:`rgba2rgb` :: >>> from skimage.color import rgba2rgb >>> from skimage import data @@ -57,7 +57,7 @@ Conversion between color and gray values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Converting an RGB image to a grayscale image is realized with -:func:`rgb2gray` :: +:func:`rgb2gray` :: >>> from skimage.color import rgb2gray >>> from skimage import data @@ -81,12 +81,25 @@ from RGB to grayscale:: Converting a grayscale image to RGB with :func:`gray2rgb` simply duplicates the gray values over the three color channels. +Image inversion +~~~~~~~~~~~~~~~ + +An inverted image is also called complementary image. For binary images, True values +become False and conversely. For grayscale images, pixel values are replaced by the +difference of the maximum value of the data type and the actual value. For RGB +images, the same operation is done for each channel. This operation can be achieved +with :py:func:`skimage.util.invert`:: + + >>> from skimage import util + >>> img = data.camera() + >>> inverted_img = util.invert(img) + Painting images with labels ~~~~~~~~~~~~~~~~~~~~~~~~~~~ :func:`label2rgb` can be used to superimpose colors on a grayscale image using an array of labels to encode the regions to be represented with the -same color. +same color. .. image:: ../auto_examples/segmentation/images/sphx_glr_plot_join_segmentations_001.png @@ -139,7 +152,7 @@ the boundaries of the bins. The simplest contrast enhancement :func:`rescale_intensity` consists in stretching pixel values to the whole allowed range, using a linear transformation:: - + >>> from skimage import exposure >>> text = data.text() >>> text.min(), text.max() diff --git a/skimage/util/__init__.py b/skimage/util/__init__.py index 2500469b..b64836f1 100644 --- a/skimage/util/__init__.py +++ b/skimage/util/__init__.py @@ -7,6 +7,7 @@ from .apply_parallel import apply_parallel from .arraypad import pad, crop from ._regular_grid import regular_grid from .unique import unique_rows +from ._invert import invert __all__ = ['img_as_float', @@ -22,4 +23,5 @@ __all__ = ['img_as_float', 'random_noise', 'regular_grid', 'apply_parallel', + 'invert', 'unique_rows'] diff --git a/skimage/util/_invert.py b/skimage/util/_invert.py new file mode 100644 index 00000000..f59bef29 --- /dev/null +++ b/skimage/util/_invert.py @@ -0,0 +1,33 @@ +import numpy as np +from .dtype import dtype_limits + + +def invert(image): + """Invert an image. + + Substract the image to the maximum value allowed by the dtype maximum. + + Parameters + ---------- + image : ndarray + The input image. + + Returns + ------- + invert : ndarray + Inverted image. + + Examples + -------- + >>> img = np.array([[100, 0, 200], + ... [0, 50, 0], + ... [30, 0, 255]], np.uint8) + >>> invert(img) + array([[155, 255, 55], + [255, 205, 255], + [225, 255, 0]], dtype=uint8) + """ + if image.dtype == 'bool': + return ~image + else: + return dtype_limits(image)[1] - image diff --git a/skimage/util/tests/test_invert.py b/skimage/util/tests/test_invert.py new file mode 100644 index 00000000..5890d685 --- /dev/null +++ b/skimage/util/tests/test_invert.py @@ -0,0 +1,48 @@ +import numpy as np +from numpy.testing import assert_array_equal +from skimage import dtype_limits +from skimage.util import invert + + +def test_invert_bool(): + dtype = 'bool' + image = np.zeros((3, 3), dtype=dtype) + image[1, :] = dtype_limits(image)[1] + expected = np.zeros((3, 3), dtype=dtype) + dtype_limits(image)[1] + expected[1, :] = 0 + result = invert(image) + assert_array_equal(expected, result) + + +def test_invert_uint8(): + dtype = 'uint8' + image = np.zeros((3, 3), dtype=dtype) + image[1, :] = dtype_limits(image)[1] + expected = np.zeros((3, 3), dtype=dtype) + dtype_limits(image)[1] + expected[1, :] = 0 + result = invert(image) + assert_array_equal(expected, result) + + +def test_invert_int8(): + dtype = 'int8' + image = np.zeros((3, 3), dtype=dtype) + image[1, :] = dtype_limits(image)[1] + expected = np.zeros((3, 3), dtype=dtype) + dtype_limits(image)[1] + expected[1, :] = 0 + result = invert(image) + assert_array_equal(expected, result) + + +def test_invert_float64(): + dtype = 'float64' + image = np.zeros((3, 3), dtype=dtype) + image[1, :] = dtype_limits(image)[1] + expected = np.zeros((3, 3), dtype=dtype) + dtype_limits(image)[1] + expected[1, :] = 0 + result = invert(image) + assert_array_equal(expected, result) + + +if __name__ == '__main__': + np.testing.run_module_suite()