def corresponding_chromaticities_prediction_Fairchild1990(experiment=1, **kwargs): """ Returns the corresponding chromaticities prediction for Fairchild (1990) chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. \*\*kwargs : \*\* Keywords arguments. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_Fairchild1990(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2089528677990308, 0.47240345174230519)), ((0.449, 0.511), (0.43756528098582792, 0.51210303139041924)), ((0.263, 0.505), (0.26213623665658092, 0.49725385033264224)), ((0.322, 0.545), (0.3235312762825191, 0.54756652922585702)), ((0.316, 0.537), (0.3151390992740366, 0.53983332031574016)), ((0.265, 0.553), (0.26347459238415272, 0.55443357809543037)), ((0.221, 0.538), (0.22115956537655593, 0.53244703908294599)), ((0.135, 0.532), (0.13969494108553854, 0.52072342107668024)), ((0.145, 0.472), (0.1512288710743511, 0.45330415352961834)), ((0.163, 0.331), (0.17156913711903982, 0.30262647410866889)), ((0.176, 0.431), (0.18257922398137369, 0.40778921192793854)), ((0.244, 0.349), (0.24189049501108895, 0.34134012046930529))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) XYZ_n = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) * 100 XYZ_r = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) * 100 xy_r = XYZ_to_xy(XYZ_r) Y_n = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get(experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_Fairchild1990( XYZ_1, XYZ_n, XYZ_r, Y_n) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_r), xy_r) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def test_n_dimensional_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition n-dimensions support. """ xy = np.array([0.26414772236966133, 0.37770000704815188]) XYZ = np.array([0.69935853, 1., 0.94824534]) np.testing.assert_almost_equal( xy_to_XYZ(xy), XYZ, decimal=7) xy = np.tile(xy, (6, 1)) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal( xy_to_XYZ(xy), XYZ, decimal=7) xy = np.reshape(xy, (2, 3, 2)) XYZ = np.reshape(XYZ, (2, 3, 3)) np.testing.assert_almost_equal( xy_to_XYZ(xy), XYZ, decimal=7)
def corresponding_chromaticities_prediction_CMCCAT2000(experiment=1, **kwargs): """ Returns the corresponding chromaticities prediction for CMCCAT2000 chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. \*\*kwargs : \*\* Keywords arguments. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_CMCCAT2000(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.20832101929657834, 0.47271680534693694)), ((0.449, 0.511), (0.44592707020371486, 0.50777351504395707)), ((0.263, 0.505), (0.26402624712986333, 0.4955361681706304)), ((0.322, 0.545), (0.33168840090358015, 0.54315801981008516)), ((0.316, 0.537), (0.32226245779851387, 0.53576245377085929)), ((0.265, 0.553), (0.27107058097430181, 0.5501997842556422)), ((0.221, 0.538), (0.22618269421847523, 0.52947407170848704)), ((0.135, 0.532), (0.14396930475660724, 0.51909841743126817)), ((0.145, 0.472), (0.14948357434418671, 0.45567605010224305)), ((0.163, 0.331), (0.15631720730028753, 0.31641514460738623)), ((0.176, 0.431), (0.17631993066748047, 0.41275893424542082)), ((0.244, 0.349), (0.22876382018951744, 0.3499324084859976))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) XYZ_w = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) * 100 XYZ_wr = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) * 100 xy_wr = XYZ_to_xy(XYZ_wr) L_A1 = L_A2 = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get( experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_CMCCAT2000( XYZ_1, XYZ_w, XYZ_wr, L_A1, L_A2) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def corresponding_chromaticities_prediction_VonKries(experiment=1, transform='CAT02'): """ Returns the corresponding chromaticities prediction for Von Kries chromatic adaptation model using given transform. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. transform : unicode, optional {'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}, Chromatic adaptation transform. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_VonKries(2, 'Bradford') >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.20820148430638033, 0.47229226819364528)), ((0.449, 0.511), (0.44891022948064191, 0.50716028901449561)), ((0.263, 0.505), (0.26435459360846608, 0.49596314494922683)), ((0.322, 0.545), (0.33487309037107632, 0.54712207251983425)), ((0.316, 0.537), (0.32487581236911361, 0.53905899356457776)), ((0.265, 0.553), (0.27331050571632376, 0.55550280647813977)), ((0.221, 0.538), (0.22714800102072819, 0.53313179748041983)), ((0.135, 0.532), (0.14427303768336433, 0.52268044497913713)), ((0.145, 0.472), (0.14987451889726533, 0.45507852741116867)), ((0.163, 0.331), (0.15649757464732098, 0.31487959772753954)), ((0.176, 0.431), (0.17605936460371163, 0.41037722722471409)), ((0.244, 0.349), (0.22598059059292835, 0.34652914678030416))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) XYZ_w = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) XYZ_wr = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) xy_wr = XYZ_to_xy(XYZ_wr) prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) XYZ_2 = chromatic_adaptation_VonKries(XYZ_1, XYZ_w, XYZ_wr, transform) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def corresponding_chromaticities_prediction_CMCCAT2000(experiment=1): """ Returns the corresponding chromaticities prediction for CMCCAT2000 chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_CMCCAT2000(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2083210..., 0.4727168...)), ((0.449, 0.511), (0.4459270..., 0.5077735...)), ((0.263, 0.505), (0.2640262..., 0.4955361...)), ((0.322, 0.545), (0.3316884..., 0.5431580...)), ((0.316, 0.537), (0.3222624..., 0.5357624...)), ((0.265, 0.553), (0.2710705..., 0.5501997...)), ((0.221, 0.538), (0.2261826..., 0.5294740...)), ((0.135, 0.532), (0.1439693..., 0.5190984...)), ((0.145, 0.472), (0.1494835..., 0.4556760...)), ((0.163, 0.331), (0.1563172..., 0.3164151...)), ((0.176, 0.431), (0.1763199..., 0.4127589...)), ((0.244, 0.349), (0.2287638..., 0.3499324...))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) XYZ_w = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) * 100 XYZ_wr = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) * 100 xy_wr = XYZ_to_xy(XYZ_wr) L_A1 = L_A2 = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get( experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_CMCCAT2000( XYZ_1, XYZ_w, XYZ_wr, L_A1, L_A2) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def corresponding_chromaticities_prediction_Fairchild1990(experiment=1): """ Returns the corresponding chromaticities prediction for Fairchild (1990) chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_Fairchild1990(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2089528..., 0.4724034...)), ((0.449, 0.511), (0.4375652..., 0.5121030...)), ((0.263, 0.505), (0.2621362..., 0.4972538...)), ((0.322, 0.545), (0.3235312..., 0.5475665...)), ((0.316, 0.537), (0.3151390..., 0.5398333...)), ((0.265, 0.553), (0.2634745..., 0.5544335...)), ((0.221, 0.538), (0.2211595..., 0.5324470...)), ((0.135, 0.532), (0.1396949..., 0.5207234...)), ((0.145, 0.472), (0.1512288..., 0.4533041...)), ((0.163, 0.331), (0.1715691..., 0.3026264...)), ((0.176, 0.431), (0.1825792..., 0.4077892...)), ((0.244, 0.349), (0.2418904..., 0.3413401...))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) XYZ_n = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) * 100 XYZ_r = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) * 100 xy_r = XYZ_to_xy(XYZ_r) Y_n = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get(experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_Fairchild1990( XYZ_1, XYZ_n, XYZ_r, Y_n) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_r), xy_r) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def test_nan_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition nan support. """ cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] cases = set(permutations(cases * 3, r=2)) for case in cases: xy = np.array(case) xy_to_XYZ(xy)
def RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Converts from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- RGB : array_like *RGB* colourspace array. input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. Returns ------- ndarray *RGB* colourspace array. Notes ----- - *RGB* colourspace arrays are in domain [0, 1]. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.01103604, 0.12734466, 0.11631037]) >>> RGB_to_RGB( ... RGB, ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([ 0.0643338..., 0.1157362..., 0.1157614...]) """ cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(cat, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) RGB = dot_vector(M, RGB) return RGB
def chromatically_adapted_primaries(primaries, whitepoint_t, whitepoint_r, chromatic_adaptation_transform='CAT02'): """ Chromatically adapts given *primaries* :math:`xy` chromaticity coordinates from test ``whitepoint_t`` to reference ``whitepoint_r``. Parameters ---------- primaries : array_like, (3, 2) Primaries :math:`xy` chromaticity coordinates. whitepoint_t : array_like Test illuminant / whitepoint :math:`xy` chromaticity coordinates. whitepoint_r : array_like Reference illuminant / whitepoint :math:`xy` chromaticity coordinates. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. Returns ------- ndarray Chromatically adapted primaries :math:`xy` chromaticity coordinates. Examples -------- >>> p = np.array([0.64, 0.33, 0.30, 0.60, 0.15, 0.06]) >>> w_t = np.array([0.31270, 0.32900]) >>> w_r = np.array([0.34570, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> chromatically_adapted_primaries(p, w_t, w_r, ... chromatic_adaptation_transform) ... # doctest: +ELLIPSIS array([[ 0.6484414..., 0.3308533...], [ 0.3211951..., 0.5978443...], [ 0.1558932..., 0.0660492...]]) """ primaries = np.reshape(primaries, (3, 2)) XYZ_a = chromatic_adaptation_VonKries( xy_to_XYZ(primaries), xy_to_XYZ(whitepoint_t), xy_to_XYZ(whitepoint_r), chromatic_adaptation_transform) P_a = XYZ_to_xyY(XYZ_a)[..., 0:2] return P_a
def RGB_to_RGB_matrix(input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Computes the matrix :math:`M` converting from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC', None}**, *Chromatic adaptation* transform, if *None* no chromatic adaptation is performed. Returns ------- ndarray Conversion matrix :math:`M`. Examples -------- >>> from colour.models import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB_to_RGB_matrix(sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE) ... # doctest: +ELLIPSIS array([[ 0.5288241..., 0.3340609..., 0.1373616...], [ 0.0975294..., 0.8790074..., 0.0233981...], [ 0.0163599..., 0.1066124..., 0.8772485...]]) """ M = input_colourspace.RGB_to_XYZ_matrix if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(M_CAT, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) return M
def test_n_dimensional_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition n-dimensional support. """ xy = np.array([0.54369557, 0.32107944]) XYZ = xy_to_XYZ(xy) xy = np.tile(xy, (6, 1)) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal(xy_to_XYZ(xy), XYZ, decimal=7) xy = np.reshape(xy, (2, 3, 2)) XYZ = np.reshape(XYZ, (2, 3, 3)) np.testing.assert_almost_equal(xy_to_XYZ(xy), XYZ, decimal=7)
def CCT_factor(reference_data, XYZ_r): """ Returns the correlated colour temperature factor penalizing lamps with extremely low correlated colour temperatures. Parameters ---------- reference_data : VS_ColorimetryData Reference colorimetry data. XYZ_r : array_like *CIE XYZ* tristimulus values for reference. Returns ------- numeric Correlated colour temperature factor. """ xy_w = ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'] XYZ_w = xy_to_XYZ(xy_w) Labs = [] for vs_colorimetry_data_ in reference_data: _name, XYZ, _Lab, _C = vs_colorimetry_data_ XYZ_a = chromatic_adaptation_VonKries( XYZ, XYZ_r, XYZ_w, transform='CMCCAT2000') Lab = XYZ_to_Lab(XYZ_a, illuminant=xy_w) Labs.append(Lab) G_r = gamut_area(Labs) / D65_GAMUT_AREA CCT_f = 1 if G_r > 1 else G_r return CCT_f
def xy_to_ij(xy): """ Converts given *CIE xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(xy)))
def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(xy)))
def RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_method='CAT02'): """ Converts from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- RGB : array_like, (3,) *RGB* colourspace matrix. input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_method : unicode, optional ('XYZ Scaling', 'Bradford', 'Von Kries', 'Fairchild', 'CAT02') *Chromatic adaptation* method. ndarray, (3,) *RGB* colourspace matrix. Notes ----- - *RGB* colourspace matrices are in domain [0, 1]. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.35521588, 0.41, 0.24177934]) >>> RGB_to_RGB( ... RGB, ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([ 0.3579334..., 0.4007138..., 0.2615704...]) """ cat = chromatic_adaptation_matrix( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_method) trs_matrix = np.dot(output_colourspace.to_RGB, np.dot(cat, input_colourspace.to_XYZ)) return np.dot(trs_matrix, RGB)
def chromaticity_diagram_colours_CIE1976UCS( samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', antialiasing=True): """ Plots the *CIE 1976 UCS Chromaticity Diagram* colours. Parameters ---------- samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. antialiasing : bool, optional Whether to apply anti-aliasing to the image. Other Parameters ---------------- \**kwargs : dict, optional {:func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definition. Returns ------- Figure Current figure or None. Examples -------- >>> chromaticity_diagram_colours_CIE1976UCS() # doctest: +SKIP """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT triangulation = Delaunay(Luv_to_uv(XYZ_to_Luv(cmfs.values, illuminant), illuminant), qhull_options='Qu QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(1, 0, samples)) xy = tstack((xx, yy)) mask = (triangulation.find_simplex(xy) < 0).astype(DEFAULT_FLOAT_DTYPE) if antialiasing: kernel = np.array([ [0, 1, 0], [1, 2, 1], [0, 1, 0], ]).astype(DEFAULT_FLOAT_DTYPE) kernel /= np.sum(kernel) mask = convolve(mask, kernel) mask = 1 - mask[:, :, np.newaxis] XYZ = xy_to_XYZ(Luv_uv_to_xy(xy)) RGB = normalise_maximum(XYZ_to_sRGB(XYZ, illuminant), axis=-1) return np.dstack([RGB, mask])
def corresponding_chromaticities_prediction_CIE1994(experiment=1): """ Returns the corresponding chromaticities prediction for CIE 1994 chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_CIE1994(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2133909..., 0.4939794...)), ((0.449, 0.511), (0.4450345..., 0.5120939...)), ((0.263, 0.505), (0.2693262..., 0.5083212...)), ((0.322, 0.545), (0.3308593..., 0.5443940...)), ((0.316, 0.537), (0.3225195..., 0.5377826...)), ((0.265, 0.553), (0.2709737..., 0.5513666...)), ((0.221, 0.538), (0.2280786..., 0.5351592...)), ((0.135, 0.532), (0.1439436..., 0.5303576...)), ((0.145, 0.472), (0.1500743..., 0.4842895...)), ((0.163, 0.331), (0.1559955..., 0.3772379...)), ((0.176, 0.431), (0.1806318..., 0.4518475...)), ((0.244, 0.349), (0.2454445..., 0.4018004...))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) xy_o1 = Luv_uv_to_xy(illuminants.uvp_t) xy_o2 = Luv_uv_to_xy(illuminants.uvp_m) # :math:`Y_o` is set to an arbitrary value in domain [18, 100]. Y_o = 18 E_o1 = E_o2 = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get( experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_CIE1994( XYZ_1, xy_o1, xy_o2, Y_o, E_o1, E_o2) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_o2), xy_o2) prediction.append(CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_method='CAT02'): """ Converts from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- RGB : array_like, (3,) *RGB* colourspace matrix. input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_method : unicode, optional ('XYZ Scaling', 'Bradford', 'Von Kries', 'Fairchild', 'CAT02') *Chromatic adaptation* method. ndarray, (3,) *RGB* colourspace matrix. Notes ----- - *RGB* colourspace matrices are in domain [0, 1]. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.35521588, 0.41, 0.24177934]) >>> RGB_to_RGB( ... RGB, ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([ 0.3579334..., 0.4007138..., 0.2615704...]) """ cat = chromatic_adaptation_matrix(xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_method) trs_matrix = np.dot(output_colourspace.to_RGB, np.dot(cat, input_colourspace.to_XYZ)) return np.dot(trs_matrix, RGB)
def test_n_dimensional_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition n-dimensions support. """ xy = np.array([0.26414772, 0.37770001]) XYZ = np.array([0.69935852, 1.00000000, 0.94824533]) np.testing.assert_almost_equal(xy_to_XYZ(xy), XYZ, decimal=7) xy = np.tile(xy, (6, 1)) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal(xy_to_XYZ(xy), XYZ, decimal=7) xy = np.reshape(xy, (2, 3, 2)) XYZ = np.reshape(XYZ, (2, 3, 3)) np.testing.assert_almost_equal(xy_to_XYZ(xy), XYZ, decimal=7)
def RGB_to_RGB_matrix(input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Computes the matrix :math:`M` converting from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. Returns ------- ndarray Conversion matrix :math:`M`. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.01103742, 0.12734226, 0.11632971]) >>> RGB_to_RGB_matrix( ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([[ 0.5288241..., 0.3340609..., 0.1373616...], [ 0.0975294..., 0.8790074..., 0.0233981...], [ 0.0163599..., 0.1066124..., 0.8772485...]]) """ cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(cat, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) return M
def corresponding_chromaticities_prediction_CIE1994(experiment=1): """ Returns the corresponding chromaticities prediction for CIE 1994 chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} Breneman (1987) experiment number. Returns ------- tuple Corresponding chromaticities prediction. Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_CIE1994(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2133909..., 0.4939794...)), ((0.449, 0.511), (0.4450345..., 0.5120939...)), ((0.263, 0.505), (0.2693262..., 0.5083212...)), ((0.322, 0.545), (0.3308593..., 0.5443940...)), ((0.316, 0.537), (0.3225195..., 0.5377826...)), ((0.265, 0.553), (0.2709737..., 0.5513666...)), ((0.221, 0.538), (0.2280786..., 0.5351592...)), ((0.135, 0.532), (0.1439436..., 0.5303576...)), ((0.145, 0.472), (0.1500743..., 0.4842895...)), ((0.163, 0.331), (0.1559955..., 0.3772379...)), ((0.176, 0.431), (0.1806318..., 0.4518475...)), ((0.244, 0.349), (0.2454445..., 0.4018004...))] """ experiment_results = list(BRENEMAN_EXPERIMENTS.get(experiment)) illuminants = experiment_results.pop(0) xy_o1 = Luv_uv_to_xy(illuminants.uvp_t) xy_o2 = Luv_uv_to_xy(illuminants.uvp_m) # :math:`Y_o` is set to an arbitrary value in domain [18, 100]. Y_o = 18 E_o1 = E_o2 = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES.get( experiment).Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) * 100 XYZ_2 = chromatic_adaptation_CIE1994(XYZ_1, xy_o1, xy_o2, Y_o, E_o1, E_o2) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_o2), xy_o2) prediction.append( CorrespondingChromaticitiesPrediction(result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def test_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition. """ np.testing.assert_almost_equal( xy_to_XYZ((0.32207410281368043, 0.3315655001362353)), np.array([0.97137399, 1., 1.04462134]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ((0.32174206617150575, 0.337609723160027)), np.array([0.953, 1.000, 1.009]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ((0.4474327628361859, 0.4074979625101875)), np.array([1.098, 1.000, 0.356]), decimal=7)
def test_domain_range_scale_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition domain and range scale support. """ xy = np.array([0.54369557, 0.32107944, 0.12197225]) XYZ = xy_to_XYZ(xy) xy = np.tile(xy, (6, 1)).reshape(2, 3, 3) XYZ = np.tile(XYZ, (6, 1)).reshape(2, 3, 3) d_r = (('reference', 1, 1), (1, 1, 1), ( 100, np.array([1, 1, 100]), 100, )) for scale, factor_a, factor_b in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal( xy_to_XYZ(xy * factor_a), XYZ * factor_b, decimal=7)
def XYZ_to_Lab(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* tristimulus values to *CIE Lab* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray *CIE Lab* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *Lightness* :math:`L^*` is in domain [0, 100]. References ---------- .. [2] Lindbloom, B. (2003). XYZ to Lab. Retrieved February 24, 2014, from http://www.brucelindbloom.com/Eqn_XYZ_to_Lab.html Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS array([ 37.9856291..., -23.6230288..., -4.4141703...]) """ XYZ = np.asarray(XYZ) XYZ_r = xy_to_XYZ(illuminant) XYZ_f = XYZ / XYZ_r XYZ_f = np.where(XYZ_f > CIE_E, np.power(XYZ_f, 1 / 3), (CIE_K * XYZ_f + 16) / 116) X_f, Y_f, Z_f = tsplit(XYZ_f) L = 116 * Y_f - 16 a = 500 * (X_f - Y_f) b = 200 * (Y_f - Z_f) Lab = tstack((L, a, b)) return Lab
def test_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition. """ np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.26414772, 0.37770001])), np.array([0.69935852, 1.0, 0.94824533]), decimal=7 ) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.50453169, 0.37440000])), np.array([1.34757396, 1.0, 0.32336621]), decimal=7 ) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.47670437, 0.35790000])), np.array([1.33194851, 1.0, 0.46212805]), decimal=7 ) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.34567, 0.35850])), np.array([0.96421199, 1.0, 0.82518828]), decimal=7 )
def Luv_to_XYZ(Luv, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Luv* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Luv : array_like *CIE Luv* colourspace array. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* tristimulus values are in domain [0, 1]. References ---------- .. [3] Lindbloom, B. (2003). Luv to XYZ. Retrieved February 24, 2014, from http://brucelindbloom.com/Eqn_Luv_to_XYZ.html Examples -------- >>> Luv = np.array([37.98562910, -28.79229446, -1.35581950]) >>> Luv_to_XYZ(Luv) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ L, u, v = tsplit(Luv) X_r, Y_r, Z_r = tsplit(xy_to_XYZ(illuminant)) Y = np.where(L > CIE_E * CIE_K, ((L + 16) / 116) ** 3, L / CIE_K) a = 1 / 3 * ((52 * L / (u + 13 * L * (4 * X_r / (X_r + 15 * Y_r + 3 * Z_r)))) - 1) b = -5 * Y c = -1 / 3.0 d = Y * (39 * L / (v + 13 * L * (9 * Y_r / (X_r + 15 * Y_r + 3 * Z_r))) - 5) X = (d - b) / (a - c) Z = X * a + b XYZ = tstack((X, Y, Z)) return XYZ
def CCT_D_uv_to_plotting_colourspace(CCT_D_uv): """ Convert given *uv* chromaticity coordinates to the default plotting colourspace. """ return normalise_maximum( XYZ_to_plotting_colourspace( xy_to_XYZ(UCS_uv_to_xy(CCT_to_uv(CCT_D_uv, "Robertson 1968")))), axis=-1, )
def Luv_to_XYZ(Luv, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Luv* colourspace to *CIE XYZ* colourspace. Parameters ---------- Luv : array_like, (3,) *CIE Luv* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE XYZ* colourspace matrix. Notes ----- - Input :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* colourspace matrix is in domain [0, 1]. References ---------- .. [3] Lindbloom, B. (2003). Luv to XYZ. Retrieved February 24, 2014, from http://brucelindbloom.com/Eqn_Luv_to_XYZ.html Examples -------- >>> Luv = np.array([37.9856291, -28.79229446, -1.3558195]) >>> Luv_to_XYZ(Luv) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ L, u, v = np.ravel(Luv) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) Y = ((L + 16) / 116) ** 3 if L > CIE_E * CIE_K else L / CIE_K a = 1 / 3 * ((52 * L / (u + 13 * L * (4 * Xr / (Xr + 15 * Yr + 3 * Zr)))) - 1) b = -5 * Y c = -1 / 3.0 d = Y * (39 * L / (v + 13 * L * (9 * Yr / (Xr + 15 * Yr + 3 * Zr))) - 5) X = (d - b) / (a - c) Z = X * a + b return np.array([X, Y, Z])
def Lab_to_XYZ(Lab, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Lab* colourspace to *CIE XYZ* colourspace. Parameters ---------- Lab : array_like, (3,) *CIE Lab* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE XYZ* colourspace matrix. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* colourspace matrix is in domain [0, 1]. References ---------- .. [3] http://www.brucelindbloom.com/Eqn_Lab_to_XYZ.html (Last accessed 24 February 2014) Examples -------- >>> Lab = np.array([100, -7.41787844, -15.85742105]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.9219310..., 1. , 1.0374424...]) """ L, a, b = np.ravel(Lab) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) fy = (L + 16) / 116 fx = a / 500 + fy fz = fy - b / 200 xr = fx**3 if fx**3 > CIE_E else (116 * fx - 16) / CIE_K yr = ((L + 16) / 116)**3 if L > CIE_K * CIE_E else L / CIE_K zr = fz**3 if fz**3 > CIE_E else (116 * fz - 16) / CIE_K X = xr * Xr Y = yr * Yr Z = zr * Zr return np.array([X, Y, Z])
def Luv_to_XYZ(Luv, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Luv* colourspace to *CIE XYZ* colourspace. Parameters ---------- Luv : array_like, (3,) *CIE Luv* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE XYZ* colourspace matrix. Notes ----- - Input :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* colourspace matrix is in domain [0, 1]. References ---------- .. [3] http://brucelindbloom.com/Eqn_Luv_to_XYZ.html (Last accessed 24 February 2014) Examples -------- >>> Luv = np.array([100, -20.04304247, -19.81676035]) >>> Luv_to_XYZ(Luv) # doctest: +ELLIPSIS array([ 0.9219310..., 1. , 1.0374424...]) """ L, u, v = np.ravel(Luv) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) Y = ((L + 16) / 116) ** 3 if L > CIE_E * CIE_K else L / CIE_K a = 1 / 3 * ((52 * L / (u + 13 * L * (4 * Xr / (Xr + 15 * Yr + 3 * Zr)))) - 1) b = -5 * Y c = -1 / 3.0 d = Y * (39 * L / (v + 13 * L * (9 * Yr / (Xr + 15 * Yr + 3 * Zr))) - 5) X = (d - b) / (a - c) Z = X * a + b return np.array([X, Y, Z])
def Lab_to_XYZ(Lab, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Lab* colourspace to *CIE XYZ* colourspace. Parameters ---------- Lab : array_like, (3,) *CIE Lab* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE XYZ* colourspace matrix. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* colourspace matrix is in domain [0, 1]. References ---------- .. [3] http://www.brucelindbloom.com/Eqn_Lab_to_XYZ.html (Last accessed 24 February 2014) Examples -------- >>> Lab = np.array([100, -7.41787844, -15.85742105]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.9219310..., 1. , 1.0374424...]) """ L, a, b = np.ravel(Lab) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) fy = (L + 16) / 116 fx = a / 500 + fy fz = fy - b / 200 xr = fx ** 3 if fx ** 3 > CIE_E else (116 * fx - 16) / CIE_K yr = ((L + 16) / 116) ** 3 if L > CIE_K * CIE_E else L / CIE_K zr = fz ** 3 if fz ** 3 > CIE_E else (116 * fz - 16) / CIE_K X = xr * Xr Y = yr * Yr Z = zr * Zr return np.array([X, Y, Z])
def get_rgb_to_xyz_matrix(name): """ RGB to XYZ の Matrix を求める。 DCI-P3 で D65 の係数を返せるように内部関数化した。 """ if name != "DCI-P3": rgb_to_xyz_matrix = RGB_COLOURSPACES[name].RGB_to_XYZ_matrix else: rgb_to_xyz_matrix\ = calc_rgb_to_xyz_matrix(RGB_COLOURSPACES[DCI_P3].primaries, xy_to_XYZ(ILLUMINANTS[CMFS_NAME]['D65'])) return rgb_to_xyz_matrix
def XYZ_to_Lab(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* colourspace to *CIE Lab* colourspace. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE Lab* colourspace matrix. Notes ----- - Input *CIE XYZ* is in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *Lightness* :math:`L^*` is in domain [0, 100]. References ---------- .. [2] http://www.brucelindbloom.com/Eqn_XYZ_to_Lab.html (Last accessed 24 February 2014) Examples -------- >>> XYZ_to_Lab(np.array([0.92193107, 1, 1.03744246])) # doctest: +ELLIPSIS array([ 100. , -7.4178784..., -15.8574210...]) """ X, Y, Z = np.ravel(XYZ) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) xr = X / Xr yr = Y / Yr zr = Z / Zr fx = xr**(1 / 3) if xr > CIE_E else (CIE_K * xr + 16) / 116 fy = yr**(1 / 3) if yr > CIE_E else (CIE_K * yr + 16) / 116 fz = zr**(1 / 3) if zr > CIE_E else (CIE_K * zr + 16) / 116 L = 116 * fy - 16 a = 500 * (fx - fy) b = 200 * (fy - fz) return np.array([L, a, b])
def XYZ_to_Lab(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* colourspace to *CIE Lab* colourspace. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE Lab* colourspace matrix. Notes ----- - Input *CIE XYZ* is in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *Lightness* :math:`L^*` is in domain [0, 100]. References ---------- .. [2] http://www.brucelindbloom.com/Eqn_XYZ_to_Lab.html (Last accessed 24 February 2014) Examples -------- >>> XYZ_to_Lab(np.array([0.92193107, 1, 1.03744246])) # doctest: +ELLIPSIS array([ 100. , -7.4178784..., -15.8574210...]) """ X, Y, Z = np.ravel(XYZ) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) xr = X / Xr yr = Y / Yr zr = Z / Zr fx = xr ** (1 / 3) if xr > CIE_E else (CIE_K * xr + 16) / 116 fy = yr ** (1 / 3) if yr > CIE_E else (CIE_K * yr + 16) / 116 fz = zr ** (1 / 3) if zr > CIE_E else (CIE_K * zr + 16) / 116 L = 116 * fy - 16 a = 500 * (fx - fy) b = 200 * (fy - fz) return np.array([L, a, b])
def XYZ_to_Luv(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* tristimulus values to *CIE Luv* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray *CIE Luv* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output :math:`L^*` is in domain [0, 100]. References ---------- .. [2] Lindbloom, B. (2003). XYZ to Luv. Retrieved February 24, 2014, from http://brucelindbloom.com/Eqn_XYZ_to_Luv.html Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> XYZ_to_Luv(XYZ) # doctest: +ELLIPSIS array([ 37.9856291..., -28.7922944..., -1.3558195...]) """ X, Y, Z = tsplit(XYZ) X_r, Y_r, Z_r = tsplit(xy_to_XYZ(illuminant)) y_r = Y / Y_r L = np.where(y_r > CIE_E, 116 * y_r ** (1 / 3) - 16, CIE_K * y_r) u = (13 * L * ((4 * X / (X + 15 * Y + 3 * Z)) - (4 * X_r / (X_r + 15 * Y_r + 3 * Z_r)))) v = (13 * L * ((9 * Y / (X + 15 * Y + 3 * Z)) - (9 * Y_r / (X_r + 15 * Y_r + 3 * Z_r)))) Luv = tstack((L, u, v)) return Luv
def XYZ_to_UVW(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* tristimulus values to *CIE 1964 U\*V\*W\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray *CIE 1964 U\*V\*W\** colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 100]. - Output *CIE UVW* colourspace array is in domain [0, 100]. Warning ------- The input / output domains of that definition are non standard! Examples -------- >>> import numpy as np >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) * 100 >>> XYZ_to_UVW(XYZ) # doctest: +ELLIPSIS array([-28.0483277..., -0.8805242..., 37.0041149...]) """ xyY = XYZ_to_xyY(XYZ, illuminant) _x, y, Y = tsplit(xyY) u, v = tsplit(UCS_to_uv(XYZ_to_UCS(XYZ))) u_0, v_0 = tsplit(UCS_to_uv(XYZ_to_UCS( xy_to_XYZ(illuminant)))) W = 25 * Y ** (1 / 3) - 17 U = 13 * W * (u - u_0) V = 13 * W * (v - v_0) UVW = tstack((U, V, W)) return UVW
def get_xyz_to_rgb_matrix(name): """ XYZ to RGB の Matrix を求める。 DCI-P3 で D65 の係数を返せるように内部関数化した。 """ if name != "DCI-P3": xyz_to_rgb_matrix = RGB_COLOURSPACES[name].XYZ_to_RGB_matrix else: rgb_to_xyz_matrix\ = calc_rgb_to_xyz_matrix(RGB_COLOURSPACES[DCI_P3].primaries, xy_to_XYZ(ILLUMINANTS[CMFS_NAME]['D65'])) xyz_to_rgb_matrix = linalg.inv(rgb_to_xyz_matrix) return xyz_to_rgb_matrix
def Lab_to_XYZ(Lab, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE Lab* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab : array_like *CIE Lab* colourspace array. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* tristimulus values are in domain [0, 1]. References ---------- .. [3] Lindbloom, B. (2008). Lab to XYZ. Retrieved February 24, 2014, from http://www.brucelindbloom.com/Eqn_Lab_to_XYZ.html Examples -------- >>> Lab = np.array([37.98562910, -23.62302887, -4.41417036]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ L, a, b = tsplit(Lab) XYZ_r = xy_to_XYZ(illuminant) f_y = (L + 16) / 116 f_x = a / 500 + f_y f_z = f_y - b / 200 x_r = np.where(f_x ** 3 > CIE_E, f_x ** 3, (116 * f_x - 16) / CIE_K) y_r = np.where(L > CIE_K * CIE_E, ((L + 16) / 116) ** 3, L / CIE_K) z_r = np.where(f_z ** 3 > CIE_E, f_z ** 3, (116 * f_z - 16) / CIE_K) XYZ = tstack((x_r, y_r, z_r)) * XYZ_r return XYZ
def xy_to_rgb(xy, name='ITU-R BT.2020', normalize='maximum', specific=None): """ xy値からRGB値を算出する。 いい感じに正規化もしておく。 Parameters ---------- xy : array_like xy value. name : string color space name. normalize : string normalize method. You can select 'maximum', 'specific' or None. Returns ------- array_like rgb value. the value is normalized. """ illuminant_XYZ = D65_WHITE illuminant_RGB = D65_WHITE chromatic_adaptation_transform = 'CAT02' large_xyz_to_rgb_matrix = get_xyz_to_rgb_matrix(name) if normalize == 'specific': xyY = xy_to_xyY(xy) xyY[..., 2] = specific large_xyz = xyY_to_XYZ(xyY) else: large_xyz = xy_to_XYZ(xy) rgb = XYZ_to_RGB(large_xyz, illuminant_XYZ, illuminant_RGB, large_xyz_to_rgb_matrix, chromatic_adaptation_transform) """ そのままだとビデオレベルが低かったりするので、 各ドット毎にRGB値を正規化&最大化する。必要であれば。 """ if normalize == 'maximum': rgb = normalise_maximum(rgb, axis=-1) else: if(np.sum(rgb > 1.0) > 0): print("warning: over flow has occured at xy_to_rgb") if(np.sum(rgb < 0.0) > 0): print("warning: under flow has occured at xy_to_rgb") rgb[rgb < 0] = 0 rgb[rgb > 1.0] = 1.0 return rgb
def test_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition. """ np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.26414772, 0.37770001])), np.array([0.69935852, 1.00000000, 0.94824533]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.50453169, 0.37440000])), np.array([1.34757396, 1.00000000, 0.32336621]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.47670437, 0.35790000])), np.array([1.33194851, 1.00000000, 0.46212805]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.34570000, 0.35850000])), np.array([0.96429568, 1.00000000, 0.82510460]), decimal=7)
def test_xy_to_XYZ(self): """ Tests :func:`colour.models.cie_xyy.xy_to_XYZ` definition. """ np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.54369557, 0.32107944])), np.array([1.69333661, 1.00000000, 0.42115742]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.29777735, 0.48246446])), np.array([0.61720059, 1.00000000, 0.45549094]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.18582823, 0.14633764])), np.array([1.26985942, 1.00000000, 4.56365245]), decimal=7) np.testing.assert_almost_equal( xy_to_XYZ(np.array([0.31270000, 0.32900000])), np.array([0.95045593, 1.00000000, 1.08905775]), decimal=7)
def XYZ_to_Luv(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* colourspace to *CIE Luv* colourspace. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE Luv* colourspace matrix. Notes ----- - Input *CIE XYZ* colourspace matrix is in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output :math:`L^*` is in domain [0, 100]. References ---------- .. [2] Lindbloom, B. (2003). XYZ to Luv. Retrieved February 24, 2014, from http://brucelindbloom.com/Eqn_XYZ_to_Luv.html Examples -------- >>> XYZ = np.array([0.07049534, 0.1008, 0.09558313]) >>> XYZ_to_Luv(XYZ) # doctest: +ELLIPSIS array([ 37.9856291..., -28.7922944..., -1.3558195...]) """ X, Y, Z = np.ravel(XYZ) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) yr = Y / Yr L = 116 * yr ** (1 / 3) - 16 if yr > CIE_E else CIE_K * yr u = (13 * L * ((4 * X / (X + 15 * Y + 3 * Z)) - (4 * Xr / (Xr + 15 * Yr + 3 * Zr)))) v = (13 * L * ((9 * Y / (X + 15 * Y + 3 * Z)) - (9 * Yr / (Xr + 15 * Yr + 3 * Zr)))) return np.array([L, u, v])
def XYZ_to_Luv(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* colourspace to *CIE Luv* colourspace. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE Luv* colourspace matrix. Notes ----- - Input *CIE XYZ* colourspace matrix is in domain [0, 1]. - Input *illuminant* chromaticity coordinates are in domain [0, 1]. - Output :math:`L^*` is in domain [0, 100]. References ---------- .. [2] http://brucelindbloom.com/Eqn_XYZ_to_Luv.html (Last accessed 24 February 2014) Examples -------- >>> XYZ_to_Luv(np.array([0.92193107, 1, 1.03744246])) # doctest: +ELLIPSIS array([ 100. , -20.0430424..., -19.8167603...]) """ X, Y, Z = np.ravel(XYZ) Xr, Yr, Zr = np.ravel(xy_to_XYZ(illuminant)) yr = Y / Yr L = 116 * yr ** (1 / 3) - 16 if yr > CIE_E else CIE_K * yr u = (13 * L * ((4 * X / (X + 15 * Y + 3 * Z)) - (4 * Xr / (Xr + 15 * Yr + 3 * Zr)))) v = (13 * L * ((9 * Y / (X + 15 * Y + 3 * Z)) - (9 * Yr / (Xr + 15 * Yr + 3 * Zr)))) return np.array([L, u, v])
def normalised_primary_matrix(primaries: ArrayLike, whitepoint: ArrayLike) -> NDArray: """ Compute the *Normalised Primary Matrix* (NPM) converting a *RGB* colourspace array to *CIE XYZ* tristimulus values using given *primaries* and *whitepoint* :math:`xy` chromaticity coordinates. Parameters ---------- primaries Primaries :math:`xy` chromaticity coordinates. whitepoint Illuminant / whitepoint :math:`xy` chromaticity coordinates. Returns ------- :class:`numpy.ndarray` *Normalised Primary Matrix* (NPM). References ---------- :cite:`SocietyofMotionPictureandTelevisionEngineers1993a` Examples -------- >>> p = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]) >>> w = np.array([0.32168, 0.33767]) >>> normalised_primary_matrix(p, w) # doctest: +ELLIPSIS array([[ 9.5255239...e-01, 0.0000000...e+00, 9.3678631...e-05], [ 3.4396645...e-01, 7.2816609...e-01, -7.2132546...e-02], [ 0.0000000...e+00, 0.0000000...e+00, 1.0088251...e+00]]) """ primaries = np.reshape(primaries, (3, 2)) z = as_float_array(xy_to_z(primaries))[..., np.newaxis] primaries = np.transpose(np.hstack([primaries, z])) whitepoint = xy_to_XYZ(whitepoint) coefficients = np.dot(np.linalg.inv(primaries), whitepoint) coefficients = np.diagflat(coefficients) npm = np.dot(primaries, coefficients) return npm
def normalised_primary_matrix(primaries, whitepoint): """ Returns the *normalised primary matrix* using given *primaries* and *whitepoint* :math:`xy` chromaticity coordinates. Parameters ---------- primaries : array_like, (3, 2) Primaries :math:`xy` chromaticity coordinates. whitepoint : array_like Illuminant / whitepoint :math:`xy` chromaticity coordinates. Returns ------- ndarray, (3, 3) *Normalised primary matrix*. References ---------- :cite:`SocietyofMotionPictureandTelevisionEngineers1993a` Examples -------- >>> p = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]) >>> w = np.array([0.32168, 0.33767]) >>> normalised_primary_matrix(p, w) # doctest: +ELLIPSIS array([[ 9.5255239...e-01, 0.0000000...e+00, 9.3678631...e-05], [ 3.4396645...e-01, 7.2816609...e-01, -7.2132546...e-02], [ 0.0000000...e+00, 0.0000000...e+00, 1.0088251...e+00]]) """ primaries = np.reshape(primaries, (3, 2)) z = xy_to_z(primaries)[..., np.newaxis] primaries = np.transpose(np.hstack([primaries, z])) whitepoint = xy_to_XYZ(whitepoint) coefficients = np.dot(np.linalg.inv(primaries), whitepoint) coefficients = np.diagflat(coefficients) npm = np.dot(primaries, coefficients) return npm
def XYZ_to_UVW(XYZ, illuminant=ILLUMINANTS.get( 'CIE 1931 2 Degree Standard Observer').get('D50')): """ Converts from *CIE XYZ* colourspace to *CIE 1964 U\*V*\W\** colourspace. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant : array_like, optional Reference *illuminant* chromaticity coordinates. Returns ------- ndarray, (3,) *CIE 1964 U\*V*\W\** colourspace matrix. Notes ----- - Input *CIE XYZ* colourspace matrix is in domain [0, 100]. - Output *CIE UVW* colourspace matrix is in domain [0, 100]. Warning ------- The input / output domains of that definition are non standard! Examples -------- >>> XYZ = np.array([11.80583421, 10.34, 5.15089229]) >>> XYZ_to_UVW(XYZ) # doctest: +ELLIPSIS array([ 24.2543371..., 7.2205484..., 37.4645000...]) """ x, y, Y = np.ravel(XYZ_to_xyY(XYZ, illuminant)) u, v = np.ravel(UCS_to_uv(XYZ_to_UCS(XYZ))) u0, v0 = np.ravel(UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(illuminant)))) W = 25 * Y**(1 / 3) - 17 U = 13 * W * (u - u0) V = 13 * W * (v - v0) return np.array([U, V, W])
def CCT_factor(reference_data, XYZ_r): xy_w = ILLUMINANTS.get('CIE 1931 2 Degree Standard Observer').get('D65') XYZ_w = xy_to_XYZ(xy_w) Labs = [] for vs_colorimetry_data_ in reference_data: _name, XYZ, _Lab, _C = vs_colorimetry_data_ XYZ_a = chromatic_adaptation_VonKries(XYZ, XYZ_r, XYZ_w, transform='CMCCAT2000') Lab = XYZ_to_Lab(XYZ_a, illuminant=xy_w) Labs.append(Lab) G_r = gamut_area(Labs) / D65_GAMUT_AREA CCT_f = 1 if G_r > 1 else G_r return CCT_f
def CCT_factor(reference_data, XYZ_r): """ Returns the correlated colour temperature factor penalizing lamps with extremely low correlated colour temperatures. Parameters ---------- reference_data : VS_ColorimetryData Reference colorimetry data. XYZ_r : array_like *CIE XYZ* tristimulus values for reference. Returns ------- numeric Correlated colour temperature factor. """ xy_w = ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'] XYZ_w = xy_to_XYZ(xy_w) Labs = [] for vs_colorimetry_data_ in reference_data: _name, XYZ, _Lab, _C = vs_colorimetry_data_ XYZ_a = chromatic_adaptation_VonKries(XYZ, XYZ_r, XYZ_w, transform='CMCCAT2000') Lab = XYZ_to_Lab(XYZ_a, illuminant=xy_w) Labs.append(Lab) G_r = gamut_area(Labs) / D65_GAMUT_AREA CCT_f = 1 if G_r > 1 else G_r return CCT_f
def CCT_factor(reference_data: Tuple[VS_ColorimetryData, ...], XYZ_r: ArrayLike) -> Floating: """ Return the correlated colour temperature factor penalizing lamps with extremely low correlated colour temperatures. Parameters ---------- reference_data Reference colorimetry data. XYZ_r *CIE XYZ* tristimulus values for reference. Returns ------- :class:`numpy.floating` Correlated colour temperature factor. """ xy_w = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"]["D65"] XYZ_w = xy_to_XYZ(xy_w) Lab = XYZ_to_Lab( chromatic_adaptation_VonKries( [colorimetry_data.XYZ for colorimetry_data in reference_data], XYZ_r, XYZ_w, transform="CMCCAT2000", ), illuminant=xy_w, ) G_r = gamut_area(Lab) / GAMUT_AREA_D65 CCT_f = 1 if G_r > 1 else G_r return CCT_f
def CIE_1931_chromaticity_diagram_colours_plot( surface=1, samples=4096, cmfs='CIE 1931 2 Degree Standard Observer', **kwargs): """ Plots the *CIE 1931 Chromaticity Diagram* colours. Parameters ---------- surface : numeric, optional Generated markers surface. samples : numeric, optional Samples count on one axis. cmfs : unicode, optional Standard observer colour matching functions used for diagram bounds. Other Parameters ---------------- \**kwargs : dict, optional {:func:`boundaries`, :func:`canvas`, :func:`decorate`, :func:`display`}, Please refer to the documentation of the previously listed definitions. Returns ------- Figure Current figure or None. Examples -------- >>> CIE_1931_chromaticity_diagram_colours_plot() # doctest: +SKIP """ settings = {'figure_size': (64, 64)} settings.update(kwargs) canvas(**settings) cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT triangulation = Delaunay(XYZ_to_xy(cmfs.values, illuminant), qhull_options='QJ') xx, yy = np.meshgrid(np.linspace(0, 1, samples), np.linspace(0, 1, samples)) xy = tstack((xx, yy)) xy = xy[triangulation.find_simplex(xy) > 0] XYZ = xy_to_XYZ(xy) RGB = normalise_maximum(XYZ_to_sRGB(XYZ, illuminant), axis=-1) x_dot, y_dot = tsplit(xy) pylab.scatter(x_dot, y_dot, color=RGB, s=surface) settings.update({ 'x_ticker': False, 'y_ticker': False, 'bounding_box': (0, 1, 0, 1) }) settings.update(kwargs) ax = matplotlib.pyplot.gca() matplotlib.pyplot.setp(ax, frame_on=False) boundaries(**settings) decorate(**settings) return display(**settings)
def plot_spectral_locus(cmfs='CIE 1931 2 Degree Standard Observer', spectral_locus_colours=None, spectral_locus_labels=None, method='CIE 1931', **kwargs): """ Plots the *Spectral Locus* according to given method. Parameters ---------- cmfs : unicode, optional Standard observer colour matching functions defining the *Spectral Locus*. spectral_locus_colours : array_like or unicode, optional *Spectral Locus* colours, if ``spectral_locus_colours`` is set to *RGB*, the colours will be computed according to the corresponding chromaticity coordinates. spectral_locus_labels : array_like, optional Array of wavelength labels used to customise which labels will be drawn around the spectral locus. Passing an empty array will result in no wavelength labels being drawn. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_spectral_locus(spectral_locus_colours='RGB') # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Spectral_Locus.png :align: center :alt: plot_spectral_locus """ if spectral_locus_colours is None: spectral_locus_colours = COLOUR_STYLE_CONSTANTS.colour.dark settings = {'uniform': True} settings.update(kwargs) figure, axes = artist(**settings) method = method.upper() cmfs = first_item(filter_cmfs(cmfs).values()) illuminant = COLOUR_STYLE_CONSTANTS.colour.colourspace.whitepoint wavelengths = cmfs.wavelengths equal_energy = np.array([1 / 3] * 2) if method == 'CIE 1931': ij = XYZ_to_xy(cmfs.values, illuminant) labels = ((390, 460, 470, 480, 490, 500, 510, 520, 540, 560, 580, 600, 620, 700) if spectral_locus_labels is None else spectral_locus_labels) elif method == 'CIE 1960 UCS': ij = UCS_to_uv(XYZ_to_UCS(cmfs.values)) labels = ((420, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 645, 680) if spectral_locus_labels is None else spectral_locus_labels) elif method == 'CIE 1976 UCS': ij = Luv_to_uv(XYZ_to_Luv(cmfs.values, illuminant), illuminant) labels = ((420, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 645, 680) if spectral_locus_labels is None else spectral_locus_labels) else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}'.format( method)) pl_ij = tstack([ np.linspace(ij[0][0], ij[-1][0], 20), np.linspace(ij[0][1], ij[-1][1], 20) ]).reshape(-1, 1, 2) sl_ij = np.copy(ij).reshape(-1, 1, 2) if spectral_locus_colours.upper() == 'RGB': spectral_locus_colours = normalise_maximum( XYZ_to_plotting_colourspace(cmfs.values), axis=-1) if method == 'CIE 1931': XYZ = xy_to_XYZ(pl_ij) elif method == 'CIE 1960 UCS': XYZ = xy_to_XYZ(UCS_uv_to_xy(pl_ij)) elif method == 'CIE 1976 UCS': XYZ = xy_to_XYZ(Luv_uv_to_xy(pl_ij)) purple_line_colours = normalise_maximum( XYZ_to_plotting_colourspace(XYZ.reshape(-1, 3)), axis=-1) else: purple_line_colours = spectral_locus_colours for slp_ij, slp_colours in ((pl_ij, purple_line_colours), (sl_ij, spectral_locus_colours)): line_collection = LineCollection( np.concatenate([slp_ij[:-1], slp_ij[1:]], axis=1), colors=slp_colours) axes.add_collection(line_collection) wl_ij = dict(tuple(zip(wavelengths, ij))) for label in labels: i, j = wl_ij[label] index = bisect.bisect(wavelengths, label) left = wavelengths[index - 1] if index >= 0 else wavelengths[index] right = (wavelengths[index] if index < len(wavelengths) else wavelengths[-1]) dx = wl_ij[right][0] - wl_ij[left][0] dy = wl_ij[right][1] - wl_ij[left][1] ij = np.array([i, j]) direction = np.array([-dy, dx]) normal = (np.array([-dy, dx]) if np.dot( normalise_vector(ij - equal_energy), normalise_vector(direction)) > 0 else np.array([dy, -dx])) normal = normalise_vector(normal) / 30 label_colour = (spectral_locus_colours if is_string(spectral_locus_colours) else spectral_locus_colours[index]) axes.plot( (i, i + normal[0] * 0.75), (j, j + normal[1] * 0.75), color=label_colour) axes.plot(i, j, 'o', color=label_colour) axes.text( i + normal[0], j + normal[1], label, clip_on=True, ha='left' if normal[0] >= 0 else 'right', va='center', fontdict={'size': 'small'}) settings = {'axes': axes} settings.update(kwargs) return render(**kwargs)
def plot_chromaticity_diagram_colours( samples=256, diagram_opacity=1.0, diagram_clipping_path=None, cmfs='CIE 1931 2 Degree Standard Observer', method='CIE 1931', **kwargs): """ Plots the *Chromaticity Diagram* colours according to given method. Parameters ---------- samples : numeric, optional Samples count on one axis. diagram_opacity : numeric, optional Opacity of the *Chromaticity Diagram* colours. diagram_clipping_path : array_like, optional Path of points used to clip the *Chromaticity Diagram* colours. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_chromaticity_diagram_colours() # doctest: +SKIP .. image:: ../_static/Plotting_Plot_Chromaticity_Diagram_Colours.png :align: center :alt: plot_chromaticity_diagram_colours """ settings = {'uniform': True} settings.update(kwargs) figure, axes = artist(**settings) method = method.upper() cmfs = first_item(filter_cmfs(cmfs).values()) illuminant = COLOUR_STYLE_CONSTANTS.colour.colourspace.whitepoint ii, jj = np.meshgrid( np.linspace(0, 1, samples), np.linspace(1, 0, samples)) ij = tstack([ii, jj]) if method == 'CIE 1931': XYZ = xy_to_XYZ(ij) spectral_locus = XYZ_to_xy(cmfs.values, illuminant) elif method == 'CIE 1960 UCS': XYZ = xy_to_XYZ(UCS_uv_to_xy(ij)) spectral_locus = UCS_to_uv(XYZ_to_UCS(cmfs.values)) elif method == 'CIE 1976 UCS': XYZ = xy_to_XYZ(Luv_uv_to_xy(ij)) spectral_locus = Luv_to_uv( XYZ_to_Luv(cmfs.values, illuminant), illuminant) else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}'.format( method)) RGB = normalise_maximum( XYZ_to_plotting_colourspace(XYZ, illuminant), axis=-1) polygon = Polygon( spectral_locus if diagram_clipping_path is None else diagram_clipping_path, facecolor='none', edgecolor='none') axes.add_patch(polygon) # Preventing bounding box related issues as per # https://github.com/matplotlib/matplotlib/issues/10529 image = axes.imshow( RGB, interpolation='bilinear', extent=(0, 1, 0, 1), clip_path=None, alpha=diagram_opacity) image.set_clip_path(polygon) settings = {'axes': axes} settings.update(kwargs) return render(**kwargs)
def convert_experiment_results_Breneman1987(experiment): """ Converts *Breneman (1987)* experiment results to a :class:`colour.CorrespondingColourDataset` class instance. Parameters ---------- experiment : integer {1, 2, 3, 4, 6, 8, 9, 11, 12} *Breneman (1987)* experiment number. Returns ------- CorrespondingColourDataset :class:`colour.CorrespondingColourDataset` class instance. Examples -------- >>> from pprint import pprint >>> pprint(tuple(convert_experiment_results_Breneman1987(2))) ... # doctest: +ELLIPSIS (2, array([ 0.9582463..., 1. , 0.9436325...]), array([ 0.9587332..., 1. , 0.4385796...]), array([[ 388.125 , 405. , 345.625 ], [ 266.8957925..., 135. , 28.5983365...], [ 474.5717821..., 405. , 222.75 ...], [ 538.3899082..., 405. , 24.8944954...], [ 178.7430167..., 135. , 19.6089385...], [ 436.6749547..., 405. , 26.5483725...], [ 124.7746282..., 135. , 36.1965613...], [ 77.0794172..., 135. , 60.5850563...], [ 279.9390889..., 405. , 455.8395127...], [ 149.5808157..., 135. , 498.7046827...], [ 372.1113689..., 405. , 669.9883990...], [ 212.3638968..., 135. , 414.6704871...]]), array([[ 400.1039651..., 405. , 191.7287234...], [ 271.0384615..., 135. , 13.5 ...], [ 495.4705323..., 405. , 119.7290874...], [ 580.7967033..., 405. , 6.6758241...], [ 190.1933701..., 135. , 7.4585635...], [ 473.7184115..., 405. , 10.2346570...], [ 135.4936014..., 135. , 20.2376599...], [ 86.4689781..., 135. , 35.2281021...], [ 283.5396281..., 405. , 258.1775929...], [ 119.7044335..., 135. , 282.6354679...], [ 359.9532224..., 405. , 381.0031185...], [ 181.8271461..., 135. , 204.0661252...]]), array(1500), array(1500), 0.3, 0.3, {}) """ valid_experiment_results = (1, 2, 3, 4, 6, 8, 9, 11, 12) assert experiment in valid_experiment_results, ( '"Breneman (1987)" experiment result must be one of "{0}"!'.format( valid_experiment_results)) samples_luminance = [ 0.270, 0.090, 0.270, 0.270, 0.090, 0.270, 0.090, 0.090, 0.270, 0.090, 0.270, 0.090, ] experiment_results = list(BRENEMAN_EXPERIMENTS[experiment]) illuminant_chromaticities = experiment_results.pop(0) Y_r = Y_t = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES[experiment].Y B_r = B_t = 0.3 XYZ_t, XYZ_r = xy_to_XYZ( np.hstack([ Luv_uv_to_xy(illuminant_chromaticities[1:3]), np.full([2, 1], Y_r) ])) / Y_r xyY_cr, xyY_ct = [], [] for i, experiment_result in enumerate(experiment_results): xyY_cr.append( np.hstack([ Luv_uv_to_xy(experiment_result[2]), samples_luminance[i] * Y_r ])) xyY_ct.append( np.hstack([ Luv_uv_to_xy(experiment_result[1]), samples_luminance[i] * Y_t ])) XYZ_cr = xyY_to_XYZ(xyY_cr) XYZ_ct = xyY_to_XYZ(xyY_ct) return CorrespondingColourDataset(experiment, XYZ_r, XYZ_t, XYZ_cr, XYZ_ct, Y_r, Y_t, B_r, B_t, {})
def planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot( illuminants=None, **kwargs): """ Plots the planckian locus and given illuminants in *CIE 1960 UCS Chromaticity Diagram*. Parameters ---------- illuminants : array_like, optional Factory illuminants to plot. \**kwargs : dict, optional Keywords arguments. Returns ------- Figure Current figure or None. Raises ------ KeyError If one of the given illuminant is not found in the factory illuminants. Examples -------- >>> ils = ['A', 'C', 'E'] >>> planckian_locus_CIE_1960_UCS_chromaticity_diagram_plot( ... ils) # doctest: +SKIP """ if illuminants is None: illuminants = ('A', 'C', 'E') cmfs = CMFS.get('CIE 1931 2 Degree Standard Observer') settings = { 'title': ('{0} Illuminants - Planckian Locus\n' 'CIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer').format( ', '.join(illuminants)) if illuminants else ('Planckian Locus\nCIE 1960 UCS Chromaticity Diagram - ' 'CIE 1931 2 Degree Standard Observer'), 'standalone': False} settings.update(kwargs) CIE_1960_UCS_chromaticity_diagram_plot(**settings) start, end = 1667, 100000 uv = np.array([CCT_to_uv(x, 0, method='Robertson 1968') for x in np.arange(start, end + 250, 250)]) pylab.plot(uv[..., 0], uv[..., 1], color='black', linewidth=2) for i in (1667, 2000, 2500, 3000, 4000, 6000, 10000): u0, v0 = CCT_to_uv(i, -0.05, method='Robertson 1968') u1, v1 = CCT_to_uv(i, 0.05, method='Robertson 1968') pylab.plot((u0, u1), (v0, v1), color='black', linewidth=2) pylab.annotate('{0}K'.format(i), xy=(u0, v0), xytext=(0, -10), color='black', textcoords='offset points', size='x-small') for illuminant in illuminants: xy = ILLUMINANTS.get(cmfs.name).get(illuminant) if xy is None: raise KeyError( ('Illuminant "{0}" not found in factory illuminants: ' '"{1}".').format(illuminant, sorted(ILLUMINANTS.get(cmfs.name).keys()))) uv = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(xy))) pylab.plot(uv[0], uv[1], 'o', color='white', linewidth=2) pylab.annotate(illuminant, xy=(uv[0], uv[1]), xytext=(-50, 30), color='black', textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=-0.2')) settings.update({ 'x_tighten': True, 'y_tighten': True, 'limits': (-0.1, 0.7, -0.2, 0.6), 'standalone': True}) settings.update(kwargs) boundaries(**settings) decorate(**settings) return display(**settings)
def corresponding_chromaticities_prediction_VonKries(experiment=1, transform='CAT02'): """ Returns the corresponding chromaticities prediction for *Von Kries* chromatic adaptation model using given transform. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} *Breneman (1987)* experiment number. transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, Chromatic adaptation transform. Returns ------- tuple Corresponding chromaticities prediction. References ---------- :cite:`Breneman1987b`, :cite:`Fairchild2013t` Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_VonKries(2, 'Bradford') >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2082014..., 0.4722922...)), ((0.449, 0.511), (0.4489102..., 0.5071602...)), ((0.263, 0.505), (0.2643545..., 0.4959631...)), ((0.322, 0.545), (0.3348730..., 0.5471220...)), ((0.316, 0.537), (0.3248758..., 0.5390589...)), ((0.265, 0.553), (0.2733105..., 0.5555028...)), ((0.221, 0.538), (0.2271480..., 0.5331317...)), ((0.135, 0.532), (0.1442730..., 0.5226804...)), ((0.145, 0.472), (0.1498745..., 0.4550785...)), ((0.163, 0.331), (0.1564975..., 0.3148795...)), ((0.176, 0.431), (0.1760593..., 0.4103772...)), ((0.244, 0.349), (0.2259805..., 0.3465291...))] """ experiment_results = list(BRENEMAN_EXPERIMENTS[experiment]) illuminants = experiment_results.pop(0) XYZ_w = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) XYZ_wr = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) xy_wr = XYZ_to_xy(XYZ_wr) prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) XYZ_2 = chromatic_adaptation_VonKries(XYZ_1, XYZ_w, XYZ_wr, transform) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr) prediction.append( CorrespondingChromaticitiesPrediction(result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
def corresponding_chromaticities_prediction_CMCCAT2000(experiment=1): """ Returns the corresponding chromaticities prediction for *CMCCAT2000* chromatic adaptation model. Parameters ---------- experiment : integer, optional {1, 2, 3, 4, 6, 8, 9, 11, 12} *Breneman (1987)* experiment number. Returns ------- tuple Corresponding chromaticities prediction. References ---------- :cite:`Breneman1987b`, :cite:`Li2002a`, :cite:`Westland2012k` Examples -------- >>> from pprint import pprint >>> pr = corresponding_chromaticities_prediction_CMCCAT2000(2) >>> pr = [(p.uvp_m, p.uvp_p) for p in pr] >>> pprint(pr) # doctest: +SKIP [((0.207, 0.486), (0.2083210..., 0.4727168...)), ((0.449, 0.511), (0.4459270..., 0.5077735...)), ((0.263, 0.505), (0.2640262..., 0.4955361...)), ((0.322, 0.545), (0.3316884..., 0.5431580...)), ((0.316, 0.537), (0.3222624..., 0.5357624...)), ((0.265, 0.553), (0.2710705..., 0.5501997...)), ((0.221, 0.538), (0.2261826..., 0.5294740...)), ((0.135, 0.532), (0.1439693..., 0.5190984...)), ((0.145, 0.472), (0.1494835..., 0.4556760...)), ((0.163, 0.331), (0.1563172..., 0.3164151...)), ((0.176, 0.431), (0.1763199..., 0.4127589...)), ((0.244, 0.349), (0.2287638..., 0.3499324...))] """ with domain_range_scale(1): experiment_results = list(BRENEMAN_EXPERIMENTS[experiment]) illuminants = experiment_results.pop(0) XYZ_w = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_t)) XYZ_wr = xy_to_XYZ(Luv_uv_to_xy(illuminants.uvp_m)) xy_wr = XYZ_to_xy(XYZ_wr) L_A1 = L_A2 = BRENEMAN_EXPERIMENTS_PRIMARIES_CHROMATICITIES[ experiment].Y prediction = [] for result in experiment_results: XYZ_1 = xy_to_XYZ(Luv_uv_to_xy(result.uvp_t)) XYZ_2 = chromatic_adaptation_CMCCAT2000(XYZ_1, XYZ_w, XYZ_wr, L_A1, L_A2) uvp = Luv_to_uv(XYZ_to_Luv(XYZ_2, xy_wr), xy_wr) prediction.append( CorrespondingChromaticitiesPrediction( result.name, result.uvp_t, result.uvp_m, uvp)) return tuple(prediction)
""" Default automatic colour conversion graph illuminant spectral distribution. _DEFAULT_ILLUMINANT_SD : SpectralDistribution """ _DEFAULT_ILLUMINANT_XY = ILLUMINANTS['CIE 1931 2 Degree Standard Observer'][ _DEFAULT_ILLUMINANT] """ Default automatic colour conversion graph illuminant *CIE xy* chromaticity coordinates. _DEFAULT_ILLUMINANT_XY : ndarray """ _DEFAULT_ILLUMINANT_XYZ = xy_to_XYZ(_DEFAULT_ILLUMINANT_XY) """ Default automatic colour conversion graph illuminant *CIE XYZ* tristimulus values. _DEFAULT_ILLUMINANT_XYZ : ndarray """ _DEFAULT_RGB_COLOURSPACE = sRGB_COLOURSPACE """ Default automatic colour conversion graph *RGB* colourspace. _DEFAULT_RGB_COLOURSPACE : RGB_COLOURSPACE """ CONVERSION_SPECIFICATIONS_DATA = [