예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)