diff --git a/skimage/color/colorconv.py b/skimage/color/colorconv.py index 59e68048..6e92c210 100644 --- a/skimage/color/colorconv.py +++ b/skimage/color/colorconv.py @@ -56,7 +56,6 @@ from __future__ import division import numpy as np from scipy import linalg from ..util import dtype -from skimage._shared.utils import deprecated def guess_spatial_dimensions(image): @@ -114,7 +113,8 @@ def convert_colorspace(arr, fromspace, tospace): Notes ----- Conversion occurs through the "central" RGB color space, i.e. conversion - from XYZ to HSV is implemented as ``XYZ -> RGB -> HSV`` instead of directly. + from XYZ to HSV is implemented as ``XYZ -> RGB -> HSV`` instead of + directly. Examples -------- @@ -129,9 +129,9 @@ def convert_colorspace(arr, fromspace, tospace): fromspace = fromspace.upper() tospace = tospace.upper() - if not fromspace in fromdict.keys(): + if fromspace not in fromdict.keys(): raise ValueError('fromspace needs to be one of %s' % fromdict.keys()) - if not tospace in todict.keys(): + if tospace not in todict.keys(): raise ValueError('tospace needs to be one of %s' % todict.keys()) return todict[tospace](fromdict[fromspace](arr)) @@ -287,15 +287,15 @@ def hsv2rgb(hsv): return out -#--------------------------------------------------------------- +# --------------------------------------------------------------- # Primaries for the coordinate systems -#--------------------------------------------------------------- +# --------------------------------------------------------------- cie_primaries = np.array([700, 546.1, 435.8]) sb_primaries = np.array([1. / 155, 1. / 190, 1. / 225]) * 1e5 -#--------------------------------------------------------------- +# --------------------------------------------------------------- # Matrices that define conversion between different color spaces -#--------------------------------------------------------------- +# --------------------------------------------------------------- # From sRGB specification xyz_from_rgb = np.array([[0.412453, 0.357580, 0.180423], @@ -321,9 +321,81 @@ gray_from_rgb = np.array([[0.2125, 0.7154, 0.0721], [0, 0, 0], [0, 0, 0]]) -# CIE LAB constants for Observer= 2A, Illuminant= D65 +# CIE LAB constants for Observer=2A, Illuminant=D65 +# NOTE: this is actually the XYZ values for the illuminant above. lab_ref_white = np.array([0.95047, 1., 1.08883]) +# XYZ coordinates of the illuminants, scaled to [0, 1]. For each illuminant I +# we have: +# +# illuminant[I][0] corresponds to the XYZ coordinates for the 2 degree +# field of view. +# +# illuminant[I][1] corresponds to the XYZ coordinates for the 10 degree +# field of view. +# +# The XYZ coordinates are calculated from [1], using the formula: +# +# X = x * ( Y / y ) +# Y = Y +# Z = ( 1 - x - y ) * ( Y / y ) +# +# where Y = 1. The only exception is the illuminant "D65" with aperture angle +# 2, whose coordinates are copied from 'lab_ref_white' for +# backward-compatibility reasons. +# +# References +# ---------- +# .. [1] http://en.wikipedia.org/wiki/Standard_illuminant + +illuminants = \ + {"A": {'2': (1.098466069456375, 1, 0.3558228003436005), + '10': (1.111420406956693, 1, 0.3519978321919493)}, + "D50": {'2': (0.9642119944211994, 1, 0.8251882845188288), + '10': (0.9672062750333777, 1, 0.8142801513128616)}, + "D55": {'2': (0.956797052643698, 1, 0.9214805860173273), + '10': (0.9579665682254781, 1, 0.9092525159847462)}, + "D65": {'2': (0.95047, 1., 1.08883), # This was: `lab_ref_white` + '10': (0.94809667673716, 1, 1.0730513595166162)}, + "D75": {'2': (0.9497220898840717, 1, 1.226393520724154), + '10': (0.9441713925645873, 1, 1.2064272211720228)}, + "E": {'2': (1.0, 1.0, 1.0), + '10': (1.0, 1.0, 1.0)}} + + +def get_xyz_coords(illuminant, observer): + """Get the XYZ coordinates of the given illuminant and observer [1]_. + + Parameters + ---------- + illuminant : {"A", "D50", "D55", "D65", "D75", "E"}, optional + The name of the illuminant (the function is NOT case sensitive). + observer : {"2", "10"}, optional + The aperture angle of the observer. + + Returns + ------- + (x, y, z) : tuple + A tuple with 3 elements containing the XYZ coordinates of the given + illuminant. + + Raises + ------ + ValueError + If either the illuminant or the observer angle are not supported or + unknown. + + References + ---------- + .. [1] http://en.wikipedia.org/wiki/Standard_illuminant + + """ + illuminant = illuminant.upper() + try: + return illuminants[illuminant][observer] + except KeyError: + raise ValueError("Unknown illuminant/observer combination\ + (\'{0}\', \'{1}\')".format(illuminant, observer)) # Haematoxylin-Eosin-DAB colorspace # From original Ruifrok's paper: A. C. Ruifrok and D. A. Johnston, @@ -408,9 +480,9 @@ rgb_from_hpx = np.array([[0.644211, 0.716556, 0.266844], rgb_from_hpx[2, :] = np.cross(rgb_from_hpx[0, :], rgb_from_hpx[1, :]) hpx_from_rgb = linalg.inv(rgb_from_hpx) -#------------------------------------------------------------- +# ------------------------------------------------------------- # The conversion functions that make use of the matrices above -#------------------------------------------------------------- +# ------------------------------------------------------------- def _convert(matrix, arr): @@ -668,7 +740,7 @@ def gray2rgb(image): raise ValueError("Input image expected to be RGB, RGBA or gray.") -def xyz2lab(xyz): +def xyz2lab(xyz, illuminant="D65", observer="2"): """XYZ to CIE-LAB color space conversion. Parameters @@ -676,6 +748,10 @@ def xyz2lab(xyz): xyz : array_like The image in XYZ format, in a 3- or 4-D array of shape ``(.., ..,[ ..,] 3)``. + illuminant : {"A", "D50", "D55", "D65", "D75", "E"}, optional + The name of the illuminant (the function is NOT case sensitive). + observer : {"2", "10"}, optional + The aperture angle of the observer. Returns ------- @@ -687,11 +763,15 @@ def xyz2lab(xyz): ------ ValueError If `xyz` is not a 3-D array of shape ``(.., ..,[ ..,] 3)``. + ValueError + If either the illuminant or the observer angle is unsupported or + unknown. Notes ----- - Observer= 2A, Illuminant= D65 - CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883 + By default Observer= 2A, Illuminant= D65. CIE XYZ tristimulus values + x_ref=95.047, y_ref=100., z_ref=108.883. See function `get_xyz_coords` for + a list of supported illuminants. References ---------- @@ -705,11 +785,14 @@ def xyz2lab(xyz): >>> lena = data.lena() >>> lena_xyz = rgb2xyz(lena) >>> lena_lab = xyz2lab(lena_xyz) + """ arr = _prepare_colorarray(xyz) + xyz_ref_white = get_xyz_coords(illuminant, observer) + # scale by CIE XYZ tristimulus values of the reference white point - arr = arr / lab_ref_white + arr = arr / xyz_ref_white # Nonlinear distortion and linear transformation mask = arr > 0.008856 @@ -726,13 +809,17 @@ def xyz2lab(xyz): return np.concatenate([x[..., np.newaxis] for x in [L, a, b]], axis=-1) -def lab2xyz(lab): +def lab2xyz(lab, illuminant="D65", observer="2"): """CIE-LAB to XYZcolor space conversion. Parameters ---------- lab : array_like The image in lab format, in a 3-D array of shape ``(.., .., 3)``. + illuminant : {"A", "D50", "D55", "D65", "D75", "E"}, optional + The name of the illuminant (the function is NOT case sensitive). + observer : {"2", "10"}, optional + The aperture angle of the observer. Returns ------- @@ -743,11 +830,16 @@ def lab2xyz(lab): ------ ValueError If `lab` is not a 3-D array of shape ``(.., .., 3)``. + ValueError + If either the illuminant or the observer angle are not supported or + unknown. + Notes ----- - Observer = 2A, Illuminant = D65 - CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883 + By default Observer= 2A, Illuminant= D65. CIE XYZ tristimulus values x_ref + = 95.047, y_ref = 100., z_ref = 108.883. See function 'get_xyz_coords' for + a list of supported illuminants. References ---------- @@ -769,8 +861,9 @@ def lab2xyz(lab): out[mask] = np.power(out[mask], 3.) out[~mask] = (out[~mask] - 16.0 / 116.) / 7.787 - # rescale Observer= 2 deg, Illuminant= D65 - out *= lab_ref_white + # rescale to the reference white (illuminant) + xyz_ref_white = get_xyz_coords(illuminant, observer) + out *= xyz_ref_white return out @@ -826,7 +919,7 @@ def lab2rgb(lab): return xyz2rgb(lab2xyz(lab)) -def xyz2luv(xyz): +def xyz2luv(xyz, illuminant="D65", observer="2"): """XYZ to CIE-Luv color space conversion. Parameters @@ -834,6 +927,10 @@ def xyz2luv(xyz): xyz : (M, N, [P,] 3) array_like The 3 or 4 dimensional image in XYZ format. Final dimension denotes channels. + illuminant : {"A", "D50", "D55", "D65", "D75", "E"}, optional + The name of the illuminant (the function is NOT case sensitive). + observer : {"2", "10"}, optional + The aperture angle of the observer. Returns ------- @@ -844,11 +941,16 @@ def xyz2luv(xyz): ------ ValueError If `xyz` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``. + ValueError + If either the illuminant or the observer angle are not supported or + unknown. Notes ----- - XYZ conversion weights use Observer = 2A. Reference whitepoint for D65 - Illuminant, with XYZ tristimulus values of ``(95.047, 100., 108.883)``. + By default XYZ conversion weights use observer=2A. Reference whitepoint + for D65 Illuminant, with XYZ tristimulus values of ``(95.047, 100., + 108.883)``. See function 'get_xyz_coords' for a list of supported + illuminants. References ---------- @@ -871,13 +973,14 @@ def xyz2luv(xyz): eps = np.finfo(np.float).eps # compute y_r and L - L = y / lab_ref_white[1] + xyz_ref_white = get_xyz_coords(illuminant, observer) + L = y / xyz_ref_white[1] mask = L > 0.008856 L[mask] = 116. * np.power(L[mask], 1. / 3.) - 16. L[~mask] = 903.3 * L[~mask] - u0 = 4*lab_ref_white[0] / np.dot([1, 15, 3], lab_ref_white) - v0 = 9*lab_ref_white[1] / np.dot([1, 15, 3], lab_ref_white) + u0 = 4*xyz_ref_white[0] / np.dot([1, 15, 3], xyz_ref_white) + v0 = 9*xyz_ref_white[1] / np.dot([1, 15, 3], xyz_ref_white) # u' and v' helper functions def fu(X, Y, Z): @@ -893,7 +996,7 @@ def xyz2luv(xyz): return np.concatenate([q[..., np.newaxis] for q in [L, u, v]], axis=-1) -def luv2xyz(luv): +def luv2xyz(luv, illuminant="D65", observer="2"): """CIE-Luv to XYZ color space conversion. Parameters @@ -901,6 +1004,10 @@ def luv2xyz(luv): luv : (M, N, [P,] 3) array_like The 3 or 4 dimensional image in CIE-Luv format. Final dimension denotes channels. + illuminant : {"A", "D50", "D55", "D65", "D75", "E"}, optional + The name of the illuminant (the function is NOT case sensitive). + observer : {"2", "10"}, optional + The aperture angle of the observer. Returns ------- @@ -911,11 +1018,15 @@ def luv2xyz(luv): ------ ValueError If `luv` is not a 3-D or 4-D array of shape ``(M, N, [P,] 3)``. + ValueError + If either the illuminant or the observer angle are not supported or + unknown. Notes ----- - XYZ conversion weights use Observer = 2A. Reference whitepoint for D65 - Illuminant, with XYZ tristimulus values of ``(95.047, 100., 108.883)``. + XYZ conversion weights use observer=2A. Reference whitepoint for D65 + Illuminant, with XYZ tristimulus values of ``(95.047, 100., 108.883)``. See + function 'get_xyz_coords' for a list of supported illuminants. References ---------- @@ -935,12 +1046,13 @@ def luv2xyz(luv): mask = y > 7.999625 y[mask] = np.power((y[mask]+16.) / 116., 3.) y[~mask] = y[~mask] / 903.3 - y *= lab_ref_white[1] + xyz_ref_white = get_xyz_coords(illuminant, observer) + y *= xyz_ref_white[1] # reference white x,z uv_weights = [1, 15, 3] - u0 = 4*lab_ref_white[0] / np.dot(uv_weights, lab_ref_white) - v0 = 9*lab_ref_white[1] / np.dot(uv_weights, lab_ref_white) + u0 = 4*xyz_ref_white[0] / np.dot(uv_weights, xyz_ref_white) + v0 = 9*xyz_ref_white[1] / np.dot(uv_weights, xyz_ref_white) # compute intermediate values a = u0 + u / (13.*L + eps) @@ -1048,7 +1160,8 @@ def hed2rgb(hed): Parameters ---------- hed : array_like - The image in the HED color space, in a 3-D array of shape ``(.., .., 3)``. + The image in the HED color space, in a 3-D array of shape + ``(.., .., 3)``. Returns ------- @@ -1091,7 +1204,8 @@ def separate_stains(rgb, conv_matrix): Returns ------- out : ndarray - The image in stain color space, in a 3-D array of shape ``(.., .., 3)``. + The image in stain color space, in a 3-D array of shape + ``(.., .., 3)``. Raises ------ @@ -1139,7 +1253,8 @@ def combine_stains(stains, conv_matrix): Parameters ---------- stains : array_like - The image in stain color space, in a 3-D array of shape ``(.., .., 3)``. + The image in stain color space, in a 3-D array of shape + ``(.., .., 3)``. conv_matrix: ndarray The stain separation matrix as described by G. Landini [1]_. @@ -1190,7 +1305,8 @@ def combine_stains(stains, conv_matrix): stains = dtype.img_as_float(stains) logrgb2 = np.dot(-np.reshape(stains, (-1, 3)), conv_matrix) rgb2 = np.exp(logrgb2) - return rescale_intensity(np.reshape(rgb2 - 2, stains.shape), in_range=(-1, 1)) + return rescale_intensity(np.reshape(rgb2 - 2, stains.shape), + in_range=(-1, 1)) def lab2lch(lab): diff --git a/skimage/color/tests/data/lab_array_a_2.npy b/skimage/color/tests/data/lab_array_a_2.npy new file mode 100644 index 00000000..cd1b81d1 Binary files /dev/null and b/skimage/color/tests/data/lab_array_a_2.npy differ diff --git a/skimage/color/tests/data/lab_array_d50_10.npy b/skimage/color/tests/data/lab_array_d50_10.npy new file mode 100644 index 00000000..7eea857a Binary files /dev/null and b/skimage/color/tests/data/lab_array_d50_10.npy differ diff --git a/skimage/color/tests/data/lab_array_d50_2.npy b/skimage/color/tests/data/lab_array_d50_2.npy new file mode 100644 index 00000000..61270a05 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d50_2.npy differ diff --git a/skimage/color/tests/data/lab_array_d55_10.npy b/skimage/color/tests/data/lab_array_d55_10.npy new file mode 100644 index 00000000..566bc110 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d55_10.npy differ diff --git a/skimage/color/tests/data/lab_array_d55_2.npy b/skimage/color/tests/data/lab_array_d55_2.npy new file mode 100644 index 00000000..87a309b9 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d55_2.npy differ diff --git a/skimage/color/tests/data/lab_array_d65_10.npy b/skimage/color/tests/data/lab_array_d65_10.npy new file mode 100644 index 00000000..4ac9c0ae Binary files /dev/null and b/skimage/color/tests/data/lab_array_d65_10.npy differ diff --git a/skimage/color/tests/data/lab_array_d65_2.npy b/skimage/color/tests/data/lab_array_d65_2.npy new file mode 100644 index 00000000..71e233d1 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d65_2.npy differ diff --git a/skimage/color/tests/data/lab_array_d75_10.npy b/skimage/color/tests/data/lab_array_d75_10.npy new file mode 100644 index 00000000..642ccaf6 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d75_10.npy differ diff --git a/skimage/color/tests/data/lab_array_d75_2.npy b/skimage/color/tests/data/lab_array_d75_2.npy new file mode 100644 index 00000000..1ef36855 Binary files /dev/null and b/skimage/color/tests/data/lab_array_d75_2.npy differ diff --git a/skimage/color/tests/data/lab_array_e_2.npy b/skimage/color/tests/data/lab_array_e_2.npy new file mode 100644 index 00000000..f795d3be Binary files /dev/null and b/skimage/color/tests/data/lab_array_e_2.npy differ diff --git a/skimage/color/tests/data/luv_array_a_2.npy b/skimage/color/tests/data/luv_array_a_2.npy new file mode 100644 index 00000000..ae25c119 Binary files /dev/null and b/skimage/color/tests/data/luv_array_a_2.npy differ diff --git a/skimage/color/tests/data/luv_array_d50_10.npy b/skimage/color/tests/data/luv_array_d50_10.npy new file mode 100644 index 00000000..cf05a2ad Binary files /dev/null and b/skimage/color/tests/data/luv_array_d50_10.npy differ diff --git a/skimage/color/tests/data/luv_array_d50_2.npy b/skimage/color/tests/data/luv_array_d50_2.npy new file mode 100644 index 00000000..8f3711f4 Binary files /dev/null and b/skimage/color/tests/data/luv_array_d50_2.npy differ diff --git a/skimage/color/tests/data/luv_array_d55_10.npy b/skimage/color/tests/data/luv_array_d55_10.npy new file mode 100644 index 00000000..b2ce26ac Binary files /dev/null and b/skimage/color/tests/data/luv_array_d55_10.npy differ diff --git a/skimage/color/tests/data/luv_array_d55_2.npy b/skimage/color/tests/data/luv_array_d55_2.npy new file mode 100644 index 00000000..88daa5db Binary files /dev/null and b/skimage/color/tests/data/luv_array_d55_2.npy differ diff --git a/skimage/color/tests/data/luv_array_d65_10.npy b/skimage/color/tests/data/luv_array_d65_10.npy new file mode 100644 index 00000000..43ce45ab Binary files /dev/null and b/skimage/color/tests/data/luv_array_d65_10.npy differ diff --git a/skimage/color/tests/data/luv_array_d65_2.npy b/skimage/color/tests/data/luv_array_d65_2.npy new file mode 100644 index 00000000..75ed4792 Binary files /dev/null and b/skimage/color/tests/data/luv_array_d65_2.npy differ diff --git a/skimage/color/tests/data/luv_array_d75_10.npy b/skimage/color/tests/data/luv_array_d75_10.npy new file mode 100644 index 00000000..a04d6965 Binary files /dev/null and b/skimage/color/tests/data/luv_array_d75_10.npy differ diff --git a/skimage/color/tests/data/luv_array_d75_2.npy b/skimage/color/tests/data/luv_array_d75_2.npy new file mode 100644 index 00000000..a2ef298c Binary files /dev/null and b/skimage/color/tests/data/luv_array_d75_2.npy differ diff --git a/skimage/color/tests/data/luv_array_e_2.npy b/skimage/color/tests/data/luv_array_e_2.npy new file mode 100644 index 00000000..f2f4c280 Binary files /dev/null and b/skimage/color/tests/data/luv_array_e_2.npy differ diff --git a/skimage/color/tests/test_colorconv.py b/skimage/color/tests/test_colorconv.py index 63336a76..cf960f4e 100644 --- a/skimage/color/tests/test_colorconv.py +++ b/skimage/color/tests/test_colorconv.py @@ -71,24 +71,24 @@ class TestColorconv(TestCase): colbars_point75 = colbars * 0.75 colbars_point75_array = np.swapaxes(colbars_point75.reshape(3, 4, 2), 0, 2) - xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], # red - [[0, 0, 0]], # black - [[.9505, 1., 1.089]], # white - [[.1805, .0722, .9505]], # blue - [[.07719, .15438, .02573]], # green + xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], # red + [[0, 0, 0]], # black + [[.9505, 1., 1.089]], # white + [[.1805, .0722, .9505]], # blue + [[.07719, .15438, .02573]], # green ]) - lab_array = np.array([[[53.233, 80.109, 67.220]], # red - [[0., 0., 0.]], # black - [[100.0, 0.005, -0.010]], # white - [[32.303, 79.197, -107.864]], # blue - [[46.229, -51.7, 49.898]], # green + lab_array = np.array([[[53.233, 80.109, 67.220]], # red + [[0., 0., 0.]], # black + [[100.0, 0.005, -0.010]], # white + [[32.303, 79.197, -107.864]], # blue + [[46.229, -51.7, 49.898]], # green ]) - luv_array = np.array([[[53.233, 175.053, 37.751]], # red - [[0., 0., 0.]], # black - [[100., 0.001, -0.017]], # white - [[32.303, -9.400, -130.358]], # blue - [[46.228, -43.774, 56.589]], # green + luv_array = np.array([[[53.233, 175.053, 37.751]], # red + [[0., 0., 0.]], # black + [[100., 0.001, -0.017]], # white + [[32.303, -9.400, -130.358]], # blue + [[46.228, -43.774, 56.589]], # green ]) # RGB to HSV @@ -227,16 +227,60 @@ class TestColorconv(TestCase): def test_rgb2grey_on_grey(self): rgb2grey(np.random.rand(5, 5)) - # test matrices for xyz2lab and lab2xyz generated using http://www.easyrgb.com/index.php?X=CALC + # test matrices for xyz2lab and lab2xyz generated using + # http://www.easyrgb.com/index.php?X=CALC # Note: easyrgb website displays xyz*100 def test_xyz2lab(self): assert_array_almost_equal(xyz2lab(self.xyz_array), self.lab_array, decimal=3) + # Test the conversion with the rest of the illuminants. + for I in ["d50", "d55", "d65", "d75"]: + for obs in ["2", "10"]: + fname = "lab_array_{0}_{1}.npy".format(I, obs) + lab_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(lab_array_I_obs, + xyz2lab(self.xyz_array, I, obs), + decimal=2) + for I in ["a", "e"]: + fname = "lab_array_{0}_2.npy".format(I) + lab_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(lab_array_I_obs, + xyz2lab(self.xyz_array, I, "2"), + decimal=2) + def test_lab2xyz(self): assert_array_almost_equal(lab2xyz(self.lab_array), self.xyz_array, decimal=3) + # Test the conversion with the rest of the illuminants. + for I in ["d50", "d55", "d65", "d75"]: + for obs in ["2", "10"]: + fname = "lab_array_{0}_{1}.npy".format(I, obs) + lab_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(lab2xyz(lab_array_I_obs, I, obs), + self.xyz_array, decimal=3) + for I in ["a", "e"]: + fname = "lab_array_{0}_2.npy".format(I, obs) + lab_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(lab2xyz(lab_array_I_obs, I, "2"), + self.xyz_array, decimal=3) + + # And we include a call to test the exception handling in the code. + try: + xs = lab2xyz(lab_array_I_obs, "NaI", "2") # Not an illuminant + except ValueError: + pass + + try: + xs = lab2xyz(lab_array_I_obs, "d50", "42") # Not a degree + except ValueError: + pass + def test_rgb2lab_brucelindbloom(self): """ Test the RGB->Lab conversion by comparing to the calculator on the @@ -267,10 +311,42 @@ class TestColorconv(TestCase): assert_array_almost_equal(xyz2luv(self.xyz_array), self.luv_array, decimal=3) + # Test the conversion with the rest of the illuminants. + for I in ["d50", "d55", "d65", "d75"]: + for obs in ["2", "10"]: + fname = "luv_array_{0}_{1}.npy".format(I, obs) + luv_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(luv_array_I_obs, + xyz2luv(self.xyz_array, I, obs), + decimal=2) + for I in ["a", "e"]: + fname = "luv_array_{0}_2.npy".format(I) + luv_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(luv_array_I_obs, + xyz2luv(self.xyz_array, I, "2"), + decimal=2) + def test_luv2xyz(self): assert_array_almost_equal(luv2xyz(self.luv_array), self.xyz_array, decimal=3) + # Test the conversion with the rest of the illuminants. + for I in ["d50", "d55", "d65", "d75"]: + for obs in ["2", "10"]: + fname = "luv_array_{0}_{1}.npy".format(I, obs) + luv_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(luv2xyz(luv_array_I_obs, I, obs), + self.xyz_array, decimal=3) + for I in ["a", "e"]: + fname = "luv_array_{0}_2.npy".format(I, obs) + luv_array_I_obs = np.load( + os.path.join(os.path.dirname(__file__), 'data', fname)) + assert_array_almost_equal(luv2xyz(luv_array_I_obs, I, "2"), + self.xyz_array, decimal=3) + def test_rgb2luv_brucelindbloom(self): """ Test the RGB->Lab conversion by comparing to the calculator on the