diff --git a/skimage/color/colorconv.py b/skimage/color/colorconv.py index 8e8c3b41..74a9a520 100644 --- a/skimage/color/colorconv.py +++ b/skimage/color/colorconv.py @@ -53,6 +53,7 @@ References from __future__ import division +from warnings import warn import numpy as np from scipy import linalg from ..util import dtype @@ -552,6 +553,8 @@ def xyz2rgb(xyz): mask = arr > 0.0031308 arr[mask] = 1.055 * np.power(arr[mask], 1 / 2.4) - 0.055 arr[~mask] *= 12.92 + arr[arr < 0] = 0 + arr[arr > 1] = 1 return arr @@ -832,6 +835,8 @@ def lab2xyz(lab, illuminant="D65", observer="2"): ValueError If either the illuminant or the observer angle are not supported or unknown. + UserWarning + If any of the pixels are invalid (Z < 0). Notes @@ -854,6 +859,11 @@ def lab2xyz(lab, illuminant="D65", observer="2"): x = (a / 500.) + y z = y - (b / 200.) + if np.any(z < 0): + invalid = np.nonzero(z < 0) + warn('Color data out of range: Z < 0 in %s pixels' % invalid[0].size) + z[invalid] = 0 + out = np.dstack([x, y, z]) mask = out > 0.2068966 diff --git a/skimage/color/tests/test_colorconv.py b/skimage/color/tests/test_colorconv.py index 094873ae..c9febb5f 100644 --- a/skimage/color/tests/test_colorconv.py +++ b/skimage/color/tests/test_colorconv.py @@ -11,6 +11,7 @@ Authors :license: modified BSD """ +from __future__ import division import os.path import numpy as np @@ -372,6 +373,26 @@ class TestColorconv(TestCase): img_rgb = img_as_float(self.img_rgb) assert_array_almost_equal(luv2rgb(rgb2luv(img_rgb)), img_rgb) + def test_lab_rgb_outlier(self): + lab_array = np.ones((3, 1, 3)) + lab_array[0] = [50, -12, 85] + lab_array[1] = [50, 12, -85] + lab_array[2] = [90, -4, -47] + rgb_array = np.array([[[0.501, 0.481, 0]], + [[0, 0.482, 1.]], + [[0.578, 0.914, 1.]], + ]) + assert_almost_equal(lab2rgb(lab_array), rgb_array, decimal=3) + + def test_lab_full_gamut(self): + a, b = np.meshgrid(np.arange(-100, 100), np.arange(-100, 100)) + L = np.ones(a.shape) + lab = np.dstack((L, a, b)) + for value in [0, 10, 20]: + lab[:, :, 0] = value + with expected_warnings(['Color data out of range']): + lab2xyz(lab) + def test_lab_lch_roundtrip(self): rgb = img_as_float(self.img_rgb) lab = rgb2lab(rgb)