def XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or, n=1): """ Computes the Nayatani (1995) colour appearance model correlates. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values of test sample / stimulus in domain [0, 100]. XYZ_n : array_like *CIE XYZ* tristimulus values of reference white in domain [0, 100]. Y_o : numeric or array_like Luminance factor :math:`Y_o` of achromatic background as percentage in domain [0.18, 1.0] E_o : numeric or array_like Illuminance :math:`E_o` of the viewing field in lux. E_or : numeric or array_like Normalising illuminance :math:`E_{or}` in lux usually in domain [1000, 3000] n : numeric or array_like, optional Noise term used in the non linear chromatic adaptation model. Returns ------- Nayatani95_Specification Nayatani (1995) colour appearance model specification. Warning ------- The input domain of that definition is non standard! Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 100]. - Input *CIE XYZ_n* tristimulus values are in domain [0, 100]. Examples -------- >>> XYZ = np.array([19.01, 20.00, 21.78]) >>> XYZ_n = np.array([95.05, 100.00, 108.88]) >>> Y_o = 20.0 >>> E_o = 5000.0 >>> E_or = 1000.0 >>> XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or) # doctest: +ELLIPSIS Nayatani95_Specification(Lstar_P=49.9998829..., C=0.0133550..., \ h=257.5232268..., s=0.0133550..., Q=62.6266734..., M=0.0167262..., H=None, \ HC=None, Lstar_N=50.0039154...) """ Y_o = np.asarray(Y_o) E_o = np.asarray(E_o) E_or = np.asarray(E_or) # Computing adapting luminance :math:`L_o` and normalising luminance # :math:`L_{or}` in in :math:`cd/m^2`. # L_o = illuminance_to_luminance(E_o, Y_o) L_or = illuminance_to_luminance(E_or, Y_o) # Computing :math:`\xi`, :math:`\eta`, :math:`\zeta` values. xez = intermediate_values(XYZ_to_xy(XYZ_n)) xi, eta, _zeta = tsplit(xez) # Computing adapting field cone responses. RGB_o = ((Y_o[..., np.newaxis] * E_o[..., np.newaxis]) / (100 * np.pi)) * xez # Computing stimulus cone responses. RGB = XYZ_to_RGB_Nayatani95(XYZ) R, G, _B = tsplit(RGB) # Computing exponential factors of the chromatic adaptation. bRGB_o = exponential_factors(RGB_o) bL_or = beta_1(L_or) # Computing scaling coefficients :math:`e(R)` and :math:`e(G)` eR = scaling_coefficient(R, xi) eG = scaling_coefficient(G, eta) # Computing opponent colour dimensions. # Computing achromatic response :math:`Q`: Q_response = achromatic_response(RGB, bRGB_o, xez, bL_or, eR, eG, n) # Computing tritanopic response :math:`t`: t_response = tritanopic_response(RGB, bRGB_o, xez, n) # Computing protanopic response :math:`p`: p_response = protanopic_response(RGB, bRGB_o, xez, n) # ------------------------------------------------------------------------- # Computing the correlate of *brightness* :math:`B_r`. # ------------------------------------------------------------------------- B_r = brightness_correlate(bRGB_o, bL_or, Q_response) # Computing *brightness* :math:`B_{rw}` of ideal white. brightness_ideal_white = ideal_white_brightness_correlate(bRGB_o, xez, bL_or, n) # ------------------------------------------------------------------------- # Computing the correlate of achromatic *Lightness* :math:`L_p^\star`. # ------------------------------------------------------------------------- Lstar_P = achromatic_lightness_correlate(Q_response) # ------------------------------------------------------------------------- # Computing the correlate of normalised achromatic *Lightness* # :math:`L_n^\star`. # ------------------------------------------------------------------------- Lstar_N = normalised_achromatic_lightness_correlate(B_r, brightness_ideal_white) # ------------------------------------------------------------------------- # Computing the *hue* angle :math:`\\theta`. # ------------------------------------------------------------------------- theta = hue_angle(p_response, t_response) # TODO: Implement hue quadrature & composition computation. # ------------------------------------------------------------------------- # Computing the correlate of *saturation* :math:`S`. # ------------------------------------------------------------------------- S_RG, S_YB = tsplit(saturation_components(theta, bL_or, t_response, p_response)) S = saturation_correlate(S_RG, S_YB) # ------------------------------------------------------------------------- # Computing the correlate of *chroma* :math:`C`. # ------------------------------------------------------------------------- # C_RG, C_YB = tsplit(chroma_components(Lstar_P, S_RG, S_YB)) C = chroma_correlate(Lstar_P, S) # ------------------------------------------------------------------------- # Computing the correlate of *colourfulness* :math:`M`. # ------------------------------------------------------------------------- # TODO: Investigate components usage. # M_RG, M_YB = tsplit(colourfulness_components(C_RG, C_YB, # brightness_ideal_white)) M = colourfulness_correlate(C, brightness_ideal_white) return Nayatani95_Specification(Lstar_P, C, theta, S, B_r, M, None, None, Lstar_N)
def XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or, n=1): """ Computes the *Nayatani (1995)* colour appearance model correlates. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values of test sample / stimulus. XYZ_n : array_like *CIE XYZ* tristimulus values of reference white. Y_o : numeric or array_like Luminance factor :math:`Y_o` of achromatic background as percentage normalised to domain [0.18, 1.0] in **'Reference'** domain-range scale. E_o : numeric or array_like Illuminance :math:`E_o` of the viewing field in lux. E_or : numeric or array_like Normalising illuminance :math:`E_{or}` in lux usually normalised to domain [1000, 3000]. n : numeric or array_like, optional Noise term used in the non linear chromatic adaptation model. Returns ------- Nayatani95_Specification *Nayatani (1995)* colour appearance model specification. Notes ----- +--------------------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================================+=======================+===============+ | ``XYZ`` | [0, 100] | [0, 1] | +--------------------------------+-----------------------+---------------+ | ``XYZ_n`` | [0, 100] | [0, 1] | +--------------------------------+-----------------------+---------------+ +--------------------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================================+=======================+===============+ | ``Nayatani95_Specification.h`` | [0, 360] | [0, 1] | +--------------------------------+-----------------------+---------------+ References ---------- :cite:`Fairchild2013ba`, :cite:`Nayatani1995a` Examples -------- >>> XYZ = np.array([19.01, 20.00, 21.78]) >>> XYZ_n = np.array([95.05, 100.00, 108.88]) >>> Y_o = 20.0 >>> E_o = 5000.0 >>> E_or = 1000.0 >>> XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or) # doctest: +ELLIPSIS Nayatani95_Specification(L_star_P=49.9998829..., C=0.0133550..., \ h=257.5232268..., s=0.0133550..., Q=62.6266734..., M=0.0167262..., H=None, \ HC=None, L_star_N=50.0039154...) """ XYZ = to_domain_100(XYZ) XYZ_n = to_domain_100(XYZ_n) Y_o = as_float_array(Y_o) E_o = as_float_array(E_o) E_or = as_float_array(E_or) # Computing adapting luminance :math:`L_o` and normalising luminance # :math:`L_{or}` in in :math:`cd/m^2`. # L_o = illuminance_to_luminance(E_o, Y_o) L_or = illuminance_to_luminance(E_or, Y_o) # Computing :math:`\\xi` :math:`\\eta`, :math:`\\zeta` values. xez = intermediate_values(XYZ_to_xy(XYZ_n / 100)) xi, eta, _zeta = tsplit(xez) # Computing adapting field cone responses. RGB_o = (((Y_o[..., np.newaxis] * E_o[..., np.newaxis]) / (100 * np.pi)) * xez) # Computing stimulus cone responses. RGB = XYZ_to_RGB_Nayatani95(XYZ) R, G, _B = tsplit(RGB) # Computing exponential factors of the chromatic adaptation. bRGB_o = exponential_factors(RGB_o) bL_or = beta_1(L_or) # Computing scaling coefficients :math:`e(R)` and :math:`e(G)` eR = scaling_coefficient(R, xi) eG = scaling_coefficient(G, eta) # Computing opponent colour dimensions. # Computing achromatic response :math:`Q`: Q_response = achromatic_response(RGB, bRGB_o, xez, bL_or, eR, eG, n) # Computing tritanopic response :math:`t`: t_response = tritanopic_response(RGB, bRGB_o, xez, n) # Computing protanopic response :math:`p`: p_response = protanopic_response(RGB, bRGB_o, xez, n) # Computing the correlate of *brightness* :math:`B_r`. B_r = brightness_correlate(bRGB_o, bL_or, Q_response) # Computing *brightness* :math:`B_{rw}` of ideal white. brightness_ideal_white = ideal_white_brightness_correlate( bRGB_o, xez, bL_or, n) # Computing the correlate of achromatic *Lightness* :math:`L_p^\\star`. L_star_P = (achromatic_lightness_correlate(Q_response)) # Computing the correlate of normalised achromatic *Lightness* # :math:`L_n^\\star`. L_star_N = (normalised_achromatic_lightness_correlate( B_r, brightness_ideal_white)) # Computing the *hue* angle :math:`\\theta`. theta = hue_angle(p_response, t_response) # TODO: Implement hue quadrature & composition computation. # Computing the correlate of *saturation* :math:`S`. S_RG, S_YB = tsplit( saturation_components(theta, bL_or, t_response, p_response)) S = saturation_correlate(S_RG, S_YB) # Computing the correlate of *chroma* :math:`C`. # C_RG, C_YB = tsplit(chroma_components(L_star_P, S_RG, S_YB)) C = chroma_correlate(L_star_P, S) # Computing the correlate of *colourfulness* :math:`M`. # TODO: Investigate components usage. # M_RG, M_YB = tsplit(colourfulness_components(C_RG, C_YB, # brightness_ideal_white)) M = colourfulness_correlate(C, brightness_ideal_white) return Nayatani95_Specification(L_star_P, C, from_range_degrees(theta), S, B_r, M, None, None, L_star_N)
def XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or, n=1): """ Computes the *Nayatani (1995)* colour appearance model correlates. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values of test sample / stimulus. XYZ_n : array_like *CIE XYZ* tristimulus values of reference white. Y_o : numeric or array_like Luminance factor :math:`Y_o` of achromatic background as percentage normalised to domain [0.18, 1.0] in **'Reference'** domain-range scale. E_o : numeric or array_like Illuminance :math:`E_o` of the viewing field in lux. E_or : numeric or array_like Normalising illuminance :math:`E_{or}` in lux usually normalised to domain [1000, 3000]. n : numeric or array_like, optional Noise term used in the non linear chromatic adaptation model. Returns ------- Nayatani95_Specification *Nayatani (1995)* colour appearance model specification. Notes ----- +--------------------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +================================+=======================+===============+ | ``XYZ`` | [0, 100] | [0, 1] | +--------------------------------+-----------------------+---------------+ | ``XYZ_n`` | [0, 100] | [0, 1] | +--------------------------------+-----------------------+---------------+ +--------------------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +================================+=======================+===============+ | ``Nayatani95_Specification.h`` | [0, 360] | [0, 1] | +--------------------------------+-----------------------+---------------+ References ---------- :cite:`Fairchild2013ba`, :cite:`Nayatani1995a` Examples -------- >>> XYZ = np.array([19.01, 20.00, 21.78]) >>> XYZ_n = np.array([95.05, 100.00, 108.88]) >>> Y_o = 20.0 >>> E_o = 5000.0 >>> E_or = 1000.0 >>> XYZ_to_Nayatani95(XYZ, XYZ_n, Y_o, E_o, E_or) # doctest: +ELLIPSIS Nayatani95_Specification(L_star_P=49.9998829..., C=0.0133550..., \ h=257.5232268..., s=0.0133550..., Q=62.6266734..., M=0.0167262..., H=None, \ HC=None, L_star_N=50.0039154...) """ XYZ = to_domain_100(XYZ) XYZ_n = to_domain_100(XYZ_n) Y_o = as_float_array(Y_o) E_o = as_float_array(E_o) E_or = as_float_array(E_or) # Computing adapting luminance :math:`L_o` and normalising luminance # :math:`L_{or}` in in :math:`cd/m^2`. # L_o = illuminance_to_luminance(E_o, Y_o) L_or = illuminance_to_luminance(E_or, Y_o) # Computing :math:`\\xi` :math:`\\eta`, :math:`\\zeta` values. xez = intermediate_values(XYZ_to_xy(XYZ_n / 100)) xi, eta, _zeta = tsplit(xez) # Computing adapting field cone responses. RGB_o = (( (Y_o[..., np.newaxis] * E_o[..., np.newaxis]) / (100 * np.pi)) * xez) # Computing stimulus cone responses. RGB = XYZ_to_RGB_Nayatani95(XYZ) R, G, _B = tsplit(RGB) # Computing exponential factors of the chromatic adaptation. bRGB_o = exponential_factors(RGB_o) bL_or = beta_1(L_or) # Computing scaling coefficients :math:`e(R)` and :math:`e(G)` eR = scaling_coefficient(R, xi) eG = scaling_coefficient(G, eta) # Computing opponent colour dimensions. # Computing achromatic response :math:`Q`: Q_response = achromatic_response(RGB, bRGB_o, xez, bL_or, eR, eG, n) # Computing tritanopic response :math:`t`: t_response = tritanopic_response(RGB, bRGB_o, xez, n) # Computing protanopic response :math:`p`: p_response = protanopic_response(RGB, bRGB_o, xez, n) # Computing the correlate of *brightness* :math:`B_r`. B_r = brightness_correlate(bRGB_o, bL_or, Q_response) # Computing *brightness* :math:`B_{rw}` of ideal white. brightness_ideal_white = ideal_white_brightness_correlate( bRGB_o, xez, bL_or, n) # Computing the correlate of achromatic *Lightness* :math:`L_p^\\star`. L_star_P = (achromatic_lightness_correlate(Q_response)) # Computing the correlate of normalised achromatic *Lightness* # :math:`L_n^\\star`. L_star_N = (normalised_achromatic_lightness_correlate( B_r, brightness_ideal_white)) # Computing the *hue* angle :math:`\\theta`. theta = hue_angle(p_response, t_response) # TODO: Implement hue quadrature & composition computation. # Computing the correlate of *saturation* :math:`S`. S_RG, S_YB = tsplit( saturation_components(theta, bL_or, t_response, p_response)) S = saturation_correlate(S_RG, S_YB) # Computing the correlate of *chroma* :math:`C`. # C_RG, C_YB = tsplit(chroma_components(L_star_P, S_RG, S_YB)) C = chroma_correlate(L_star_P, S) # Computing the correlate of *colourfulness* :math:`M`. # TODO: Investigate components usage. # M_RG, M_YB = tsplit(colourfulness_components(C_RG, C_YB, # brightness_ideal_white)) M = colourfulness_correlate(C, brightness_ideal_white) return Nayatani95_Specification(L_star_P, C, from_range_degrees(theta), S, B_r, M, None, None, L_star_N)