def test_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition. """ np.testing.assert_almost_equal( xy_to_xyY(np.array([0.54369557, 0.32107944])), np.array([0.54369557, 0.32107944, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.29777735, 0.48246446])), np.array([0.29777735, 0.48246446, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.18582823, 0.14633764])), np.array([0.18582823, 0.14633764, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.31270000, 0.32900000, 1.00000000])), np.array([0.31270000, 0.32900000, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.31270000, 0.32900000]), 100), np.array([0.31270000, 0.32900000, 100.00000000]), decimal=7)
def test_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition. """ np.testing.assert_almost_equal( xy_to_xyY(np.array([0.26414772, 0.37770001])), np.array([0.26414772, 0.37770001, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.50453169, 0.37440000])), np.array([0.50453169, 0.37440000, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.47670437, 0.35790000])), np.array([0.47670437, 0.35790000, 1.00000000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.34570000, 0.35850000, 0.10080000])), np.array([0.34570000, 0.35850000, 0.10080000]), decimal=7) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.34570000, 0.35850000]), 100), np.array([0.34570000, 0.35850000, 100.00000000]), decimal=7)
def test_n_dimensional_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition n-dimensions support. """ xy = np.array([0.26414772236966133, 0.37770000704815188]) XYZ = np.array([0.26414772, 0.37770001, 1.]) np.testing.assert_almost_equal( xy_to_xyY(xy), XYZ, decimal=7) xy = np.tile(xy, (6, 1)) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal( xy_to_xyY(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_xyY(xy), XYZ, decimal=7)
def test_domain_range_scale_xy_to_xyY(self): """ Test :func:`colour.models.cie_xyy.xy_to_xyY` definition domain and range scale support. """ xy = np.array([0.54369557, 0.32107944, 0.12197225]) xyY = xy_to_xyY(xy) xy = np.reshape(np.tile(xy, (6, 1)), (2, 3, 3)) xyY = np.reshape(np.tile(xyY, (6, 1)), (2, 3, 3)) d_r = ( ("reference", 1, 1), (1, 1, 1), ( 100, np.array([1, 1, 100]), np.array([1, 1, 100]), ), ) for scale, factor_a, factor_b in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal(xy_to_xyY(xy * factor_a), xyY * factor_b, decimal=7)
def test_nan_xy_to_xyY(self): """Test :func:`colour.models.cie_xyy.xy_to_xyY` 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_xyY(xy)
def test_nan_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` 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_xyY(xy)
def test_n_dimensional_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition n-dimensional support. """ xy = np.array([0.54369557, 0.32107944]) xyY = xy_to_xyY(xy) xy = np.tile(xy, (6, 1)) xyY = np.tile(xyY, (6, 1)) np.testing.assert_almost_equal(xy_to_xyY(xy), xyY, decimal=7) xy = np.reshape(xy, (2, 3, 2)) xyY = np.reshape(xyY, (2, 3, 3)) np.testing.assert_almost_equal(xy_to_xyY(xy), xyY, decimal=7)
def test_n_dimensional_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition n-dimensions support. """ xy = np.array([0.26414772236966133, 0.37770000704815188]) XYZ = np.array([0.26414772, 0.37770001, 1.0]) np.testing.assert_almost_equal(xy_to_xyY(xy), XYZ, decimal=7) xy = np.tile(xy, (6, 1)) XYZ = np.tile(XYZ, (6, 1)) np.testing.assert_almost_equal(xy_to_xyY(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_xyY(xy), XYZ, decimal=7)
def XYZ_to_hdr_CIELab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50'], Y_s=0.2, Y_abs=100): """ Converts from *CIE XYZ* tristimulus values to *hdr-CIELAB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround in domain [0, 1]. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. Returns ------- ndarray *hdr-CIELAB* colourspace array. Notes ----- - Conversion to polar coordinates to compute the *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.Lab_to_LCHab` definition. - Conversion to cartesian coordinates from the *Lightness* :math:`L_{hdr}`, *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.LCHab_to_Lab` definition. - Input *CIE XYZ* tristimulus values are in domain [0, math:`\infty`]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> XYZ_to_hdr_CIELab(XYZ) # doctest: +ELLIPSIS array([ 24.9020664..., -46.8312760..., -10.14274843]) """ X, Y, Z = tsplit(XYZ) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) e = exponent_hdr_CIELab(Y_s, Y_abs) L_hdr = lightness_Fairchild2010(Y / Y_n, e) a_hdr = 5 * (lightness_Fairchild2010(X / X_n, e) - L_hdr) b_hdr = 2 * (L_hdr - lightness_Fairchild2010(Z / Z_n, e)) Lab_hdr = tstack((L_hdr, a_hdr, b_hdr)) return Lab_hdr
def ProLab_to_XYZ( ProLab: ArrayLike, illuminant: ArrayLike = CCS_ILLUMINANTS[ "CIE 1931 2 Degree Standard Observer"]["D65"], ) -> NDArray: """ Convert from *ProLab* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- ProLab *ProLab* colourspace array. illuminant Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- :class:`numpy.ndarray` *CIE XYZ* tristimulus values. Notes ----- +------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+=================+ | ``Lab`` | ``L`` : [0, 1] | ``L`` : [0, 1] | | | | | | | ``a`` : [-1, 1] | ``a`` : [-1, 1] | | | | | | | ``b`` : [-1, 1] | ``b`` : [-1, 1] | +------------+-----------------------+-----------------+ +------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +------------+-----------------------+-----------------+ References ---------- :cite:`Ivan2021` Examples -------- >>> ProLab = np.array([59.8466286, 115.0396354, 20.12510352]) >>> ProLab_to_XYZ(ProLab) # doctest: +ELLIPSIS array([ 0.5163401..., 0.154695 ..., 0.0628957...]) """ ProLab = to_domain_1(ProLab) XYZ_n = xyY_to_XYZ(xy_to_xyY(illuminant)) XYZ = projective_transformation(ProLab, MATRIX_INVERSE_Q) XYZ *= XYZ_n return from_range_1(XYZ)
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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input :math:`L^*` is in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [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.80219593, -1.35800706]) >>> 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(xyY_to_XYZ(xy_to_xyY(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 XYZ_to_UVW( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE 1964 U\*V\*W\** colourspace array. Warning ------- The input domain and output range of that definition are non standard! Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE 1964 U\*V\*W\** colourspace array is in range [0, 100]. References ---------- - :cite:`Wikipediacj` Examples -------- >>> import numpy as np >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) * 100 >>> XYZ_to_UVW(XYZ) # doctest: +ELLIPSIS array([-28.0579733..., -0.8819449..., 37.0041149...]) """ xyY = XYZ_to_xyY(XYZ, xyY_to_xy(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(xyY_to_XYZ(xy_to_xyY(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 Luv_to_XYZ( Luv, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']): """ Converts from *CIE L\*u\*v\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Luv : array_like *CIE L\*u\*v\** colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input :math:`L^*` is in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [0, 1]. References ---------- - :cite:`CIETC1-482004m` - :cite:`Wikipediaby` Examples -------- >>> Luv = np.array([37.9856291 , -28.80219593, -1.35800706]) >>> 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(xyY_to_XYZ(xy_to_xyY(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 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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE Lab* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - 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 = xyY_to_XYZ(xy_to_xyY(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 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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE Lab* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *Lightness* :math:`L^*` is in range [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.6290768..., -4.4174661...]) """ XYZ = np.asarray(XYZ) XYZ_r = xyY_to_XYZ(xy_to_xyY(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_domain_range_scale_xy_to_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition domain and range scale support. """ xy = np.array([0.54369557, 0.32107944, 0.12197225]) xyY = xy_to_xyY(xy) xy = np.tile(xy, (6, 1)).reshape(2, 3, 3) xyY = np.tile(xyY, (6, 1)).reshape(2, 3, 3) d_r = (('reference', 1, 1), (1, 1, 1), ( 100, np.array([1, 1, 100]), np.array([1, 1, 100]), )) for scale, factor_a, factor_b in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal( xy_to_xyY(xy * factor_a), xyY * factor_b, decimal=7)
def XYZ_to_Lab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']): """ Converts from *CIE XYZ* tristimulus values to *CIE L\*a\*b\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE L\*a\*b\** colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *Lightness* :math:`L^*` is in range [0, 100]. References ---------- - :cite:`CIETC1-482004m` Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS array([ 37.9856291..., -23.6290768..., -4.4174661...]) """ XYZ = np.asarray(XYZ) XYZ_r = xyY_to_XYZ(xy_to_xyY(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 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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE 1964 U\*V\*W\** colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE UVW* colourspace array is in range [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.0579733..., -0.8819449..., 37.0041149...]) """ xyY = XYZ_to_xyY(XYZ, xyY_to_xy(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(xyY_to_XYZ(xy_to_xyY(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 XYZ_to_Luv( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']): """ Converts from *CIE XYZ* tristimulus values to *CIE L\*u\*v\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE L\*u\*v\** colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output :math:`L^*` is in range [0, 100]. References ---------- - :cite:`CIETC1-482004m` - :cite:`Wikipediaby` Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> XYZ_to_Luv(XYZ) # doctest: +ELLIPSIS array([ 37.9856291..., -28.8021959..., -1.3580070...]) """ X, Y, Z = tsplit(XYZ) X_r, Y_r, Z_r = tsplit(xyY_to_XYZ(xy_to_xyY(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_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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE Luv* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output :math:`L^*` is in range [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.8021959..., -1.3580070...]) """ X, Y, Z = tsplit(XYZ) X_r, Y_r, Z_r = tsplit(xyY_to_XYZ(xy_to_xyY(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 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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - 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 = xyY_to_XYZ(xy_to_xyY(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 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* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - 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 = xyY_to_XYZ(xy_to_xyY(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 Lab_to_XYZ( Lab, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']): """ Converts from *CIE L\*a\*b\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab : array_like *CIE L\*a\*b\** colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *Lightness* :math:`L^*` is in domain [0, 100]. - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [0, 1]. References ---------- - :cite:`CIETC1-482004m` Examples -------- >>> Lab = np.array([37.98562910, -23.62907688, -4.41746615]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ L, a, b = tsplit(Lab) XYZ_r = xyY_to_XYZ(xy_to_xyY(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 hdr_CIELab_to_XYZ( Lab_hdr, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50'], Y_s=0.2, Y_abs=100): """ Converts from *hdr-CIELAB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab_hdr : array_like *hdr-CIELAB* colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround in domain [0, 1]. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [0, math:`\infty`]. Examples -------- >>> Lab_hdr = np.array([24.90206646, -46.83127607, -10.14274843]) >>> hdr_CIELab_to_XYZ(Lab_hdr) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ L_hdr, a_hdr, b_hdr = tsplit(Lab_hdr) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) e = exponent_hdr_CIELab(Y_s, Y_abs) Y = luminance_Fairchild2010(L_hdr, e) * Y_n X = luminance_Fairchild2010((a_hdr + 5 * L_hdr) / 5, e) * X_n Z = luminance_Fairchild2010((-b_hdr + 2 * L_hdr) / 2, e) * Z_n XYZ = tstack((X, Y, Z)) 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_xyY(self): """ Tests :func:`colour.models.cie_xyy.xy_to_xyY` definition. """ np.testing.assert_almost_equal( xy_to_xyY(np.array([0.26414772, 0.37770001])), np.array([0.26414772, 0.37770001, 1.0]), decimal=7 ) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.50453169, 0.37440000])), np.array([0.50453169, 0.3744, 1.0]), decimal=7 ) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.47670437, 0.35790000])), np.array([0.47670437, 0.3579, 1.0]), decimal=7 ) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.34567, 0.35850, 0.10080])), np.array([0.34567, 0.3585, 0.1008]), decimal=7 ) np.testing.assert_almost_equal( xy_to_xyY(np.array([0.34567, 0.35850]), 100), np.array([0.34567, 0.3585, 100.0]), decimal=7 )
def XYZ_to_hdr_CIELab( XYZ: ArrayLike, illuminant: ArrayLike = CCS_ILLUMINANTS[ "CIE 1931 2 Degree Standard Observer"]["D65"], Y_s: FloatingOrArrayLike = 0.2, Y_abs: FloatingOrArrayLike = 100, method: Union[Literal["Fairchild 2011", "Fairchild 2010"], str] = "Fairchild 2011", ) -> NDArray: """ Convert from *CIE XYZ* tristimulus values to *hdr-CIELAB* colourspace. Parameters ---------- XYZ *CIE XYZ* tristimulus values. illuminant Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s Relative luminance :math:`Y_s` of the surround. Y_abs Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method Computation method. Returns ------- :class:`numpy.ndarray` *hdr-CIELAB* colourspace array. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ - Conversion to polar coordinates to compute the *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.Lab_to_LCHab` definition. - Conversion to cartesian coordinates from the *Lightness* :math:`L_{hdr}`, *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.LCHab_to_Lab` definition. References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_hdr_CIELab(XYZ) # doctest: +ELLIPSIS array([ 51.8700206..., 60.4763385..., 32.1455191...]) >>> XYZ_to_hdr_CIELab(XYZ, method='Fairchild 2010') # doctest: +ELLIPSIS array([ 31.9962111..., 128.0076303..., 48.7695230...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) method = validate_method(method, HDR_CIELAB_METHODS) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) if method == "fairchild 2010": lightness_callable = lightness_Fairchild2010 else: lightness_callable = lightness_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already be handled. with domain_range_scale("ignore"): L_hdr = lightness_callable(Y / Y_n, e) a_hdr = 5 * (lightness_callable(X / X_n, e) - L_hdr) b_hdr = 2 * (L_hdr - lightness_callable(Z / Z_n, e)) Lab_hdr = tstack([L_hdr, a_hdr, b_hdr]) return from_range_100(Lab_hdr)
def hdr_CIELab_to_XYZ( Lab_hdr: ArrayLike, illuminant: ArrayLike = CCS_ILLUMINANTS[ "CIE 1931 2 Degree Standard Observer"]["D65"], Y_s: FloatingOrArrayLike = 0.2, Y_abs: FloatingOrArrayLike = 100, method: Union[Literal["Fairchild 2011", "Fairchild 2010"], str] = "Fairchild 2011", ) -> NDArray: """ Convert from *hdr-CIELAB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab_hdr *hdr-CIELAB* colourspace array. illuminant Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s Relative luminance :math:`Y_s` of the surround. Y_abs Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method Computation method. Returns ------- :class:`numpy.ndarray` *CIE XYZ* tristimulus values. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> Lab_hdr = np.array([51.87002062, 60.4763385, 32.14551912]) >>> hdr_CIELab_to_XYZ(Lab_hdr) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) >>> Lab_hdr = np.array([31.99621114, 128.00763036, 48.76952309]) >>> hdr_CIELab_to_XYZ(Lab_hdr, method='Fairchild 2010') ... # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L_hdr, a_hdr, b_hdr = tsplit(to_domain_100(Lab_hdr)) method = validate_method(method, HDR_CIELAB_METHODS) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) if method == "fairchild 2010": luminance_callable = luminance_Fairchild2010 else: luminance_callable = luminance_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already been handled. with domain_range_scale("ignore"): Y = luminance_callable(L_hdr, e) * Y_n X = luminance_callable((a_hdr + 5 * L_hdr) / 5, e) * X_n Z = luminance_callable((-b_hdr + 2 * L_hdr) / 2, e) * Z_n XYZ = tstack([X, Y, Z]) return from_range_1(XYZ)
def XYZ_to_hdr_CIELab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], Y_s=0.2, Y_abs=100, method='Fairchild 2011'): """ Converts from *CIE XYZ* tristimulus values to *hdr-CIELAB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method : unicode, optional **{'Fairchild 2011', 'Fairchild 2010'}**, Computation method. Returns ------- ndarray *hdr-CIELAB* colourspace array. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ - Conversion to polar coordinates to compute the *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.Lab_to_LCHab` definition. - Conversion to cartesian coordinates from the *Lightness* :math:`L_{hdr}`, *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.LCHab_to_Lab` definition. References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_hdr_CIELab(XYZ) # doctest: +ELLIPSIS array([ 51.8700206..., 60.4763385..., 32.1455191...]) >>> XYZ_to_hdr_CIELab(XYZ, method='Fairchild 2010') # doctest: +ELLIPSIS array([ 31.9962111..., 128.0076303..., 48.7695230...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) method_l = method.lower() assert method.lower() in [ m.lower() for m in HDR_CIELAB_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, HDR_CIELAB_METHODS)) if method_l == 'fairchild 2010': lightness_callable = lightness_Fairchild2010 else: lightness_callable = lightness_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already be handled. with domain_range_scale('ignore'): L_hdr = lightness_callable(Y / Y_n, e) a_hdr = 5 * (lightness_callable(X / X_n, e) - L_hdr) b_hdr = 2 * (L_hdr - lightness_callable(Z / Z_n, e)) Lab_hdr = tstack([L_hdr, a_hdr, b_hdr]) return from_range_100(Lab_hdr)
def hdr_CIELab_to_XYZ( Lab_hdr, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], Y_s=0.2, Y_abs=100, method='Fairchild 2011'): """ Converts from *hdr-CIELAB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab_hdr : array_like *hdr-CIELAB* colourspace array. illuminant : array_like, optional Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method : unicode, optional **{'Fairchild 2011', 'Fairchild 2010'}**, Computation method. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> Lab_hdr = np.array([51.87002062, 60.4763385, 32.14551912]) >>> hdr_CIELab_to_XYZ(Lab_hdr) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) >>> Lab_hdr = np.array([31.99621114, 128.00763036, 48.76952309]) >>> hdr_CIELab_to_XYZ(Lab_hdr, method='Fairchild 2010') ... # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L_hdr, a_hdr, b_hdr = tsplit(to_domain_100(Lab_hdr)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) method_l = method.lower() assert method.lower() in [ m.lower() for m in HDR_CIELAB_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, HDR_CIELAB_METHODS)) if method_l == 'fairchild 2010': luminance_callable = luminance_Fairchild2010 else: luminance_callable = luminance_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already be handled. with domain_range_scale('ignore'): Y = luminance_callable(L_hdr, e) * Y_n X = luminance_callable((a_hdr + 5 * L_hdr) / 5, e) * X_n Z = luminance_callable((-b_hdr + 2 * L_hdr) / 2, e) * Z_n XYZ = tstack([X, Y, Z]) return from_range_1(XYZ)
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', OECF=None): """ Converts from *CIE XYZ* tristimulus values to given *RGB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. XYZ_to_RGB_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. OECF : object, optional *Opto-electronic conversion function*. Returns ------- ndarray *RGB* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *RGB* colourspace array is in domain [0, 1]. Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> illuminant_XYZ = np.array([0.34567, 0.35850]) >>> illuminant_RGB = np.array([0.31271, 0.32902]) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array([ ... [3.24100326, -1.53739899, -0.49861587], ... [-0.96922426, 1.87592999, 0.04155422], ... [0.05563942, -0.20401120, 1.05714897]]) >>> XYZ_to_RGB( ... XYZ, ... illuminant_XYZ, ... illuminant_RGB, ... XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0110360..., 0.1273446..., 0.1163103...]) """ M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), transform=chromatic_adaptation_transform) XYZ_a = dot_vector(M, XYZ) RGB = dot_vector(XYZ_to_RGB_matrix, XYZ_a) if OECF is not None: RGB = OECF(RGB) return RGB
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', decoding_cctf=None): """ Converts given *RGB* colourspace array to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. 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. decoding_cctf : object, optional Decoding colour component transfer function (Decoding CCTF) or electro-optical transfer function (EOTF / EOCF). Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +--------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ +--------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ Examples -------- >>> RGB = np.array([0.45595571, 0.03039702, 0.04087245]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array( ... [[0.41240000, 0.35760000, 0.18050000], ... [0.21260000, 0.71520000, 0.07220000], ... [0.01930000, 0.11920000, 0.95050000]] ... ) >>> RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.2163881..., 0.1257 , 0.0384749...]) """ RGB = to_domain_1(RGB) if decoding_cctf is not None: with domain_range_scale('ignore'): RGB = decoding_cctf(RGB) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(M_CAT, XYZ) return from_range_1(XYZ)
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', encoding_cctf=None): """ Converts from *CIE XYZ* tristimulus values to *RGB* colourspace array. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. XYZ_to_RGB_matrix : array_like *Normalised primary matrix*. 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. encoding_cctf : object, optional Encoding colour component transfer function (Encoding CCTF) or opto-electronic transfer function (OETF / OECF). Returns ------- ndarray *RGB* colourspace array. Notes ----- +--------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ +--------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ Examples -------- >>> XYZ = np.array([0.21638819, 0.12570000, 0.03847493]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array( ... [[3.24062548, -1.53720797, -0.49862860], ... [-0.96893071, 1.87575606, 0.04151752], ... [0.05571012, -0.20402105, 1.05699594]] ... ) >>> XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.4559557..., 0.0303970..., 0.0408724...]) """ XYZ = to_domain_1(XYZ) if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), transform=chromatic_adaptation_transform) XYZ = dot_vector(M_CAT, XYZ) RGB = dot_vector(XYZ_to_RGB_matrix, XYZ) if encoding_cctf is not None: with domain_range_scale('ignore'): RGB = encoding_cctf(RGB) return from_range_1(RGB)
def Luv_to_XYZ( Luv, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE L\\*u\\*v\\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Luv : array_like *CIE L\\*u\\*v\\** colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Luv`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``u`` : [-100, 100] | ``u`` : [-1, 1] | | | | | | | ``v`` : [-100, 100] | ``v`` : [-1, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m`, :cite:`Wikipedia2007b` Examples -------- >>> Luv = np.array([41.52787529, 96.83626054, 17.75210149]) >>> Luv_to_XYZ(Luv) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L, u, v = tsplit(to_domain_100(Luv)) X_r, Y_r, Z_r = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) with domain_range_scale('100'): Y = luminance_CIE1976(L, Y_r) 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 from_range_1(XYZ)
def Lab_to_XYZ( Lab, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE L\\*a\\*b\\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab : array_like *CIE L\\*a\\*b\\** colourspace array. illuminant : array_like, optional Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``a`` : [-100, 100] | ``a`` : [-1, 1] | | | | | | | ``b`` : [-100, 100] | ``b`` : [-1, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m` Examples -------- >>> import numpy as np >>> Lab = np.array([41.52787529, 52.63858304, 26.92317922]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L, a, b = tsplit(to_domain_100(Lab)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) f_Y_Y_n = (L + 16) / 116 f_X_X_n = a / 500 + f_Y_Y_n f_Z_Z_n = f_Y_Y_n - b / 200 X = intermediate_luminance_function_CIE1976(f_X_X_n, X_n) Y = intermediate_luminance_function_CIE1976(f_Y_Y_n, Y_n) Z = intermediate_luminance_function_CIE1976(f_Z_Z_n, Z_n) XYZ = tstack([X, Y, Z]) return from_range_1(XYZ)
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', decoding_cctf=None): """ Converts from given *RGB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. decoding_cctf : object, optional Decoding colour component transfer function (Decoding CCTF) or electro-optical transfer function (EOTF / EOCF). Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *RGB* colourspace array is in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [0, 1]. Examples -------- >>> RGB = np.array([0.01100154, 0.12735048, 0.11632713]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array([ ... [0.41240000, 0.35760000, 0.18050000], ... [0.21260000, 0.71520000, 0.07220000], ... [0.01930000, 0.11920000, 0.95050000]]) >>> RGB_to_XYZ( ... RGB, ... illuminant_RGB, ... illuminant_XYZ, ... RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ if decoding_cctf is not None: RGB = decoding_cctf(RGB) M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) XYZ_a = dot_vector(M, XYZ) return XYZ_a
def XYZ_to_Lab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE XYZ* tristimulus values to *CIE L\\*a\\*b\\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE L\\*a\\*b\\** colourspace array. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``a`` : [-100, 100] | ``a`` : [-1, 1] | | | | | | | ``b`` : [-100, 100] | ``b`` : [-1, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS array([ 41.5278752..., 52.6385830..., 26.9231792...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) f_X_X_n = intermediate_lightness_function_CIE1976(X, X_n) f_Y_Y_n = intermediate_lightness_function_CIE1976(Y, Y_n) f_Z_Z_n = intermediate_lightness_function_CIE1976(Z, Z_n) L = 116 * f_Y_Y_n - 16 a = 500 * (f_X_X_n - f_Y_Y_n) b = 200 * (f_Y_Y_n - f_Z_Z_n) Lab = tstack([L, a, b]) return from_range_100(Lab)
def Luv_to_XYZ( Luv, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE L\\*u\\*v\\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Luv : array_like *CIE L\\*u\\*v\\** colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Luv`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``u`` : [-100, 100] | ``u`` : [-1, 1] | | | | | | | ``v`` : [-100, 100] | ``v`` : [-1, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m`, :cite:`Wikipedia2007b` Examples -------- >>> Luv = np.array([41.52787529, 96.83626054, 17.75210149]) >>> Luv_to_XYZ(Luv) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L, u, v = tsplit(to_domain_100(Luv)) X_r, Y_r, Z_r = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) with domain_range_scale('100'): Y = luminance_CIE1976(L, Y_r) 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 from_range_1(XYZ)
def XYZ_to_Luv( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE XYZ* tristimulus values to *CIE L\\*u\\*v\\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE L\\*u\\*v\\** colourspace array. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Luv`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``u`` : [-100, 100] | ``u`` : [-1, 1] | | | | | | | ``v`` : [-100, 100] | ``v`` : [-1, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m`, :cite:`Wikipedia2007b` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_Luv(XYZ) # doctest: +ELLIPSIS array([ 41.5278752..., 96.8362605..., 17.7521014...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) X_r, Y_r, Z_r = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) with domain_range_scale('100'): L = lightness_CIE1976(Y, 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 from_range_100(Luv)
def XYZ_to_hdr_CIELab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], Y_s=0.2, Y_abs=100, method='Fairchild 2011'): """ Converts from *CIE XYZ* tristimulus values to *hdr-CIELAB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method : unicode, optional **{'Fairchild 2011', 'Fairchild 2010'}**, Computation method. Returns ------- ndarray *hdr-CIELAB* colourspace array. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ - Conversion to polar coordinates to compute the *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.Lab_to_LCHab` definition. - Conversion to cartesian coordinates from the *Lightness* :math:`L_{hdr}`, *chroma* :math:`C_{hdr}` and *hue* :math:`h_{hdr}` correlates can be safely performed with :func:`colour.LCHab_to_Lab` definition. References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_hdr_CIELab(XYZ) # doctest: +ELLIPSIS array([ 51.8700206..., 60.4763385..., 32.1455191...]) >>> XYZ_to_hdr_CIELab(XYZ, method='Fairchild 2010') # doctest: +ELLIPSIS array([ 31.9962111..., 128.0076303..., 48.7695230...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) method_l = method.lower() assert method.lower() in [ m.lower() for m in HDR_CIELAB_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, HDR_CIELAB_METHODS)) if method_l == 'fairchild 2010': lightness_callable = lightness_Fairchild2010 else: lightness_callable = lightness_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already be handled. with domain_range_scale('ignore'): L_hdr = lightness_callable(Y / Y_n, e) a_hdr = 5 * (lightness_callable(X / X_n, e) - L_hdr) b_hdr = 2 * (L_hdr - lightness_callable(Z / Z_n, e)) Lab_hdr = tstack([L_hdr, a_hdr, b_hdr]) return from_range_100(Lab_hdr)
def Lab_to_XYZ( Lab, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE L\\*a\\*b\\** colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab : array_like *CIE L\\*a\\*b\\** colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``a`` : [-100, 100] | ``a`` : [-1, 1] | | | | | | | ``b`` : [-100, 100] | ``b`` : [-1, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m` Examples -------- >>> Lab = np.array([41.52787529, 52.63858304, 26.92317922]) >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L, a, b = tsplit(to_domain_100(Lab)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) f_Y_Y_n = (L + 16) / 116 f_X_X_n = a / 500 + f_Y_Y_n f_Z_Z_n = f_Y_Y_n - b / 200 X = intermediate_luminance_function_CIE1976(f_X_X_n, X_n) Y = intermediate_luminance_function_CIE1976(f_Y_Y_n, Y_n) Z = intermediate_luminance_function_CIE1976(f_Z_Z_n, Z_n) XYZ = tstack([X, Y, Z]) return from_range_1(XYZ)
def XYZ_to_Lab( XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']): """ Converts from *CIE XYZ* tristimulus values to *CIE L\\*a\\*b\\** colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant : array_like, optional Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY* colourspace array. Returns ------- ndarray *CIE L\\*a\\*b\\** colourspace array. Notes ----- +----------------+-----------------------+-----------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-----------------------+-----------------+ +----------------+-----------------------+-----------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=======================+=================+ | ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] | | | | | | | ``a`` : [-100, 100] | ``a`` : [-1, 1] | | | | | | | ``b`` : [-100, 100] | ``b`` : [-1, 1] | +----------------+-----------------------+-----------------+ References ---------- :cite:`CIETC1-482004m` Examples -------- >>> import numpy as np >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS array([ 41.5278752..., 52.6385830..., 26.9231792...]) """ X, Y, Z = tsplit(to_domain_1(XYZ)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) f_X_X_n = intermediate_lightness_function_CIE1976(X, X_n) f_Y_Y_n = intermediate_lightness_function_CIE1976(Y, Y_n) f_Z_Z_n = intermediate_lightness_function_CIE1976(Z, Z_n) L = 116 * f_Y_Y_n - 16 a = 500 * (f_X_X_n - f_Y_Y_n) b = 200 * (f_Y_Y_n - f_Z_Z_n) Lab = tstack([L, a, b]) return from_range_100(Lab)
def hdr_CIELab_to_XYZ( Lab_hdr, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], Y_s=0.2, Y_abs=100, method='Fairchild 2011'): """ Converts from *hdr-CIELAB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- Lab_hdr : array_like *hdr-CIELAB* colourspace array. illuminant : array_like, optional Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. Y_s : numeric or array_like Relative luminance :math:`Y_s` of the surround. Y_abs : numeric or array_like Absolute luminance :math:`Y_{abs}` of the scene diffuse white in :math:`cd/m^2`. method : unicode, optional **{'Fairchild 2011', 'Fairchild 2010'}**, Computation method. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +----------------+-------------------------+---------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``Lab_hdr`` | ``L_hdr`` : [0, 100] | ``L_hdr`` : [0, 1] | | | | | | | ``a_hdr`` : [-100, 100] | ``a_hdr`` : [-1, 1] | | | | | | | ``b_hdr`` : [-100, 100] | ``b_hdr`` : [-1, 1] | +----------------+-------------------------+---------------------+ | ``illuminant`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ | ``Y_s`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ +----------------+-------------------------+---------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================+=========================+=====================+ | ``XYZ`` | [0, 1] | [0, 1] | +----------------+-------------------------+---------------------+ References ---------- :cite:`Fairchild2010`, :cite:`Fairchild2011` Examples -------- >>> Lab_hdr = np.array([51.87002062, 60.4763385, 32.14551912]) >>> hdr_CIELab_to_XYZ(Lab_hdr) # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) >>> Lab_hdr = np.array([31.99621114, 128.00763036, 48.76952309]) >>> hdr_CIELab_to_XYZ(Lab_hdr, method='Fairchild 2010') ... # doctest: +ELLIPSIS array([ 0.2065400..., 0.1219722..., 0.0513695...]) """ L_hdr, a_hdr, b_hdr = tsplit(to_domain_100(Lab_hdr)) X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant))) method_l = method.lower() assert method.lower() in [ m.lower() for m in HDR_CIELAB_METHODS ], ('"{0}" method is invalid, must be one of {1}!'.format( method, HDR_CIELAB_METHODS)) if method_l == 'fairchild 2010': luminance_callable = luminance_Fairchild2010 else: luminance_callable = luminance_Fairchild2011 e = exponent_hdr_CIELab(Y_s, Y_abs, method) # Domain and range scaling has already be handled. with domain_range_scale('ignore'): Y = luminance_callable(L_hdr, e) * Y_n X = luminance_callable((a_hdr + 5 * L_hdr) / 5, e) * X_n Z = luminance_callable((-b_hdr + 2 * L_hdr) / 2, e) * Z_n XYZ = tstack([X, Y, Z]) return from_range_1(XYZ)
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', EOCF=None): """ Converts from given *RGB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. EOCF : object, optional *Electro-optical conversion function*. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *RGB* colourspace array is in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in domain [0, 1]. Examples -------- >>> RGB = np.array([0.01103604, 0.12734466, 0.11631037]) >>> illuminant_RGB = np.array([0.31271, 0.32902]) >>> illuminant_XYZ = np.array([0.34567, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array([ ... [0.41238656, 0.35759149, 0.18045049], ... [0.21263682, 0.71518298, 0.07218020], ... [0.01933062, 0.11919716, 0.95037259]]) >>> RGB_to_XYZ( ... RGB, ... illuminant_RGB, ... illuminant_XYZ, ... RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ if EOCF is not None: RGB = EOCF(RGB) M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) XYZ_a = dot_vector(M, XYZ) return XYZ_a