Пример #1
0
    def test_as_numeric(self):
        """
        Tests :func:`colour.utilities.array.as_numeric` definition.
        """

        self.assertEqual(as_numeric(1), 1)

        self.assertEqual(as_numeric(np.array([1])), 1)

        np.testing.assert_almost_equal(as_numeric(np.array([1, 2, 3])),
                                       np.array([1, 2, 3]))
Пример #2
0
    def test_as_numeric(self):
        """
        Tests :func:`colour.utilities.array.as_numeric` definition.
        """

        self.assertEqual(as_numeric(1), 1.0)

        self.assertEqual(as_numeric(np.array([1])), 1.0)

        np.testing.assert_almost_equal(
            as_numeric(np.array([1, 2, 3])), np.array([1.0, 2.0, 3.0]))

        self.assertIsInstance(as_numeric(1), DEFAULT_FLOAT_DTYPE)

        self.assertIsInstance(as_numeric(1, int), int)
Пример #3
0
def log_decoding_ACEScc(ACEScc):
    """
    Defines the *ACEScc* colourspace log decoding / electro-optical transfer
    function.

    Parameters
    ----------
    ACEScc : numeric or array_like
        *ACEScc* non-linear value.

    Returns
    -------
    numeric or ndarray
        *ACESccLin* linear value.

    Examples
    --------
    >>> log_decoding_ACEScc(0.413588402492442)  # doctest: +ELLIPSIS
    0.1799999...
    """

    ACEScc = np.asarray(ACEScc)

    output = np.where(ACEScc < (9.72 - 15) / 17.52,
                      (2 ** (ACEScc * 17.52 - 9.72) - 2 ** -16) * 2,
                      2 ** (ACEScc * 17.52 - 9.72))
    output = np.where(ACEScc >= (np.log2(65504) + 9.72) / 17.52,
                      65504,
                      output)

    return as_numeric(output)
Пример #4
0
def daylight_locus_function(x_D):
    """
    Returns the daylight locus as *xy* chromaticity coordinates.

    Parameters
    ----------
    x_D : numeric or array_like
        *x* chromaticity coordinates

    Returns
    -------
    numeric or array_like
        Daylight locus as *xy* chromaticity coordinates.

    References
    ----------
    :cite:`Wyszecki2000a`

    Examples
    --------
    >>> daylight_locus_function(0.31270)  # doctest: +ELLIPSIS
    0.3291051...
    """

    x_D = as_float_array(x_D)

    y_D = -3.000 * x_D ** 2 + 2.870 * x_D - 0.275

    return as_numeric(y_D)
Пример #5
0
def log_decoding_VLog(V_out):
    """
    Defines the *Panasonic V-Log* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    V_out : numeric or array_like
        Non-linear data :math:`V_{out}`.

    Returns
    -------
    numeric or ndarray
        Linear reflection data :math`L_{in}`.

    Examples
    --------
    >>> log_decoding_VLog(0.423311448760136)  # doctest: +ELLIPSIS
    0.1799999...
    """

    V_out = np.asarray(V_out)

    cut2 = VLOG_CONSTANTS.cut2
    b = VLOG_CONSTANTS.b
    c = VLOG_CONSTANTS.c
    d = VLOG_CONSTANTS.d

    V_out = np.where(V_out < cut2,
                     (V_out - 0.125) / 5.6,
                     np.power(10, ((V_out - d) / c)) - b)

    return as_numeric(V_out)
Пример #6
0
def oetf_ROMMRGB(X):
    """
    Defines the *ROMM RGB* encoding opto-electronic transfer function
    (OETF / OECF).

    Parameters
    ----------
    X : numeric or array_like
        Linear data :math:`X_{ROMM}`.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`X'_{ROMM}`.

    Examples
    --------
    >>> oetf_ROMMRGB(0.18)  # doctest: +ELLIPSIS
    0.3857114...
    """

    X = np.asarray(X)

    E_t = 16 ** (1.8 / (1 - 1.8))

    return as_numeric(np.where(X < E_t,
                               X * 16,
                               X ** (1 / 1.8)))
Пример #7
0
def log_encoding_VLog(L_in):
    """
    Defines the *Panasonic V-Log* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    L_in : numeric or array_like
        Linear reflection data :math`L_{in}`.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`V_{out}`.

    Examples
    --------
    >>> log_encoding_VLog(0.18)  # doctest: +ELLIPSIS
    0.4233114...
    """

    L_in = np.asarray(L_in)

    cut1 = VLOG_CONSTANTS.cut1
    b = VLOG_CONSTANTS.b
    c = VLOG_CONSTANTS.c
    d = VLOG_CONSTANTS.d

    L_in = np.where(L_in < cut1,
                    5.6 * L_in + 0.125,
                    c * np.log10(L_in + b) + d)

    return as_numeric(L_in)
Пример #8
0
def eotf_BT2020(E_p, is_12_bits_system=False):
    """
    Defines *Recommendation ITU-R BT.2020* electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    E_p : numeric or array_like
        Non-linear signal :math:`E'`.
    is_12_bits_system : bool
        *BT.709* *alpha* and *beta* constants are used if system is not 12-bit.

    Returns
    -------
    numeric or ndarray
        Resulting voltage :math:`E`.

    Examples
    --------
    >>> eotf_BT2020(0.705515089922121)  # doctest: +ELLIPSIS
    0.4999999...
    """

    E_p = np.asarray(E_p)

    a = BT2020_CONSTANTS.alpha(is_12_bits_system)
    b = BT2020_CONSTANTS.beta(is_12_bits_system)

    return as_numeric(np.where(E_p < oetf_BT2020(b),
                               E_p / 4.5,
                               ((E_p + (a - 1)) / a) ** (1 / 0.45)))
Пример #9
0
def log_encoding_SLog3(t):
    """
    Defines the *Sony S-Log3* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    t : numeric or array_like
        Input light level :math:`t` to a camera.

    Returns
    -------
    numeric or ndarray
        Camera output code :math:`y`.

    Examples
    --------
    >>> log_encoding_SLog3(0.18)  # doctest: +ELLIPSIS
    0.4105571...
    """

    t = np.asarray(t)

    return as_numeric(
        np.where(t >= 0.01125000,
                 (420 + np.log10((t + 0.01) /
                                 (0.18 + 0.01)) * 261.5) / 1023,
                 (t * (171.2102946929 - 95) / 0.01125000 + 95) / 1023))
Пример #10
0
def oetf_BT709(L):
    """
    Defines *Recommendation ITU-R BT.709-6* opto-electronic transfer function
    (OETF / OECF).

    Parameters
    ----------
    L : numeric or array_like
        *Luminance* :math:`L` of the image.

    Returns
    -------
    numeric or ndarray
        Corresponding electrical signal :math:`V`.

    Examples
    --------
    >>> oetf_BT709(0.18)  # doctest: +ELLIPSIS
    0.4090077...
    """

    L = np.asarray(L)

    return as_numeric(np.where(L < 0.018,
                               L * 4.5,
                               1.099 * (L ** 0.45) - 0.099))
Пример #11
0
def log_decoding_SLog3(y):
    """
    Defines the *Sony S-Log3* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    y : numeric or array_like
        Camera output code :math:`y`.

    Returns
    -------
    numeric or ndarray
        Input light level :math:`t` to a camera.

    Examples
    --------
    >>> log_decoding_SLog3(0.410557184750733)  # doctest: +ELLIPSIS
    0.1...
    """

    y = np.asarray(y)

    return as_numeric(
        np.where(y >= 171.2102946929 / 1023,
                 ((10 ** ((y * 1023 - 420) / 261.5)) *
                  (0.18 + 0.01) - 0.01),
                 (y * 1023 - 95) * 0.01125000 / (171.2102946929 - 95)))
Пример #12
0
def eotf_ROMMRGB(X_p):
    """
    Defines the *ROMM RGB* encoding electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{ROMM}`.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{ROMM}`.

    Examples
    --------
    >>> eotf_ROMMRGB(0.3857114247511376) # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    E_t = 16 ** (1.8 / (1 - 1.8))

    return as_numeric(np.where(
        X_p < oetf_ROMMRGB(E_t),
        X_p / 16,
        X_p ** 1.8))
Пример #13
0
def log_encoding_ACEScc(ACEScc_l):
    """
    Defines the *ACEScc* colourspace log encoding / opto-electronic transfer
    function.

    Parameters
    ----------
    ACEScc_l : numeric or array_like
        *ACESccLin* linear value.

    Returns
    -------
    numeric or ndarray
        *ACEScc* non-linear value.

    Examples
    --------
    >>> log_encoding_ACEScc(0.18)  # doctest: +ELLIPSIS
    0.4135884...
    """

    ACEScc_l = np.asarray(ACEScc_l)

    output = np.where(ACEScc_l < 0,
                      (np.log2(2 ** -15 * 0.5) + 9.72) / 17.52,
                      (np.log2(2 ** -16 + ACEScc_l * 0.5) + 9.72) / 17.52)
    output = np.where(ACEScc_l >= 2 ** -15,
                      (np.log2(ACEScc_l) + 9.72) / 17.52,
                      output)

    return as_numeric(output)
Пример #14
0
def oetf_BT2020(E, is_12_bits_system=False):
    """
    Defines *Recommendation ITU-R BT.2020* opto-electrical transfer function
    (OETF / OECF).

    Parameters
    ----------
    E : numeric or array_like
        Voltage :math:`E` normalized by the reference white level and
        proportional to the implicit light intensity that would be detected
        with a reference camera colour channel R, G, B.
    is_12_bits_system : bool
        *BT.709* *alpha* and *beta* constants are used if system is not 12-bit.

    Returns
    -------
    numeric or ndarray
        Resulting non-linear signal :math:`E'`.

    Examples
    --------
    >>> oetf_BT2020(0.18)  # doctest: +ELLIPSIS
    0.4090077...
    """

    E = np.asarray(E)

    a = BT2020_CONSTANTS.alpha(is_12_bits_system)
    b = BT2020_CONSTANTS.beta(is_12_bits_system)

    return as_numeric(np.where(E < b,
                               E * 4.5,
                               a * (E ** 0.45) - (a - 1)))
Пример #15
0
def xy_to_CCT_Hernandez1999(xy):
    """
    Returns the correlated colour temperature :math:`T_{cp}` from given
    *CIE XYZ* tristimulus values *xy* chromaticity coordinates using
    Hernandez-Andres, Lee and Romero (1999) method.

    Parameters
    ----------
    xy : array_like
        *xy* chromaticity coordinates.

    Returns
    -------
    numeric
        Correlated colour temperature :math:`T_{cp}`.

    References
    ----------
    .. [10] Hernández-Andrés, J., Lee, R. L., & Romero, J. (1999).
            Calculating correlated color temperatures across the entire gamut
            of daylight and skylight chromaticities. Applied Optics, 38(27),
            5703–5709. doi:10.1364/AO.38.005703

    Examples
    --------
    >>> xy = np.array([0.31270, 0.32900])
    >>> xy_to_CCT_Hernandez1999(xy)  # doctest: +ELLIPSIS
    6500.7420431...
    """

    x, y = tsplit(xy)

    n = (x - 0.3366) / (y - 0.1735)
    CCT = (-949.86315 +
           6253.80338 * np.exp(-n / 0.92159) +
           28.70599 * np.exp(-n / 0.20039) +
           0.00004 * np.exp(-n / 0.07125))

    n = np.where(CCT > 50000,
                 (x - 0.3356) / (y - 0.1691),
                 n)

    CCT = np.where(CCT > 50000,
                   36284.48953 + 0.00228 * np.exp(-n / 0.07861) +
                   5.4535e-36 * np.exp(-n / 0.01543),
                   CCT)

    return as_numeric(CCT)
Пример #16
0
def log_encoding_ERIMMRGB(X,
                          I_max=255,
                          E_min=0.001,
                          E_clip=316.2):
    """
    Defines the *ERIMM RGB* log encoding curve / opto-electronic transfer
    function (OETF / OECF).

    Parameters
    ----------
    X : numeric or array_like
        Linear data :math:`X_{ERIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095, and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_min : numeric, optional
        Minimum exposure limit.
    E_clip : numeric, optional
        Maximum exposure limit.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`X'_{ERIMM}`.

    Examples
    --------
    >>> log_encoding_ERIMMRGB(0.18)  # doctest: +ELLIPSIS
    104.5633593...
    """

    X = np.asarray(X)

    E_t = np.exp(1) * E_min

    X_p = np.select(
        [X < 0.0,
         X <= E_t, X > E_t,
         X > E_clip],
        [0,
         I_max * ((np.log(E_t) - np.log(E_min)) /
                  (np.log(E_clip) - np.log(E_min))) * (X / E_t),
         I_max * ((np.log(X) - np.log(E_min)) /
                  (np.log(E_clip) - np.log(E_min))),
         I_max])

    return as_numeric(X_p)
Пример #17
0
def log_encoding_ACESproxy(ACESproxy_l, bit_depth='10 Bit'):
    """
    Defines the *ACESproxy* colourspace log encoding curve / opto-electronic
    transfer function.

    Parameters
    ----------
    ACESproxy_l : numeric or array_like
        *ACESproxyLin* linear value.
    bit_depth : unicode, optional
        **{'10 Bit', '12 Bit'}**,
        *ACESproxy* bit depth.

    Returns
    -------
    numeric or ndarray
        *ACESproxy* non-linear value.

    Examples
    --------
    >>> log_encoding_ACESproxy(0.18)
    426
    """

    ACESproxy_l = np.asarray(ACESproxy_l)

    constants = ACES_PROXY_CONSTANTS.get(bit_depth)

    CV_min = np.resize(constants.CV_min, ACESproxy_l.shape)
    CV_max = np.resize(constants.CV_max, ACESproxy_l.shape)

    def float_2_cv(x):
        """
        Converts given numeric to code value.
        """

        return np.maximum(CV_min, np.minimum(CV_max, np.round(x)))

    output = np.where(ACESproxy_l > 2 ** -9.72,
                      float_2_cv((np.log2(ACESproxy_l) +
                                  constants.mid_log_offset) *
                                 constants.steps_per_stop +
                                 constants.mid_CV_offset),
                      np.resize(CV_min, ACESproxy_l.shape))

    return as_numeric(output, int)
Пример #18
0
def log_encoding_CanonLog(x, bit_depth=10, out_legal=True, in_reflection=True):
    """
    Defines the *Canon Log* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_legal : bool, optional
        Whether the *Canon Log* non-linear data is encoded in legal
        range.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Returns
    -------
    numeric or ndarray
        *Canon Log* non-linear data.

    References
    ----------
    -   :cite:`Thorpe2012a`

    Examples
    --------
    >>> log_encoding_CanonLog(0.18) * 100  # doctest: +ELLIPSIS
    34.3389651...
    """

    x = np.asarray(x)

    if in_reflection:
        x = x / 0.9

    clog = np.where(x < log_decoding_CanonLog(0.0730597, bit_depth, False),
                    -(0.529136 * (np.log10(-x * 10.1596 + 1)) - 0.0730597),
                    0.529136 * np.log10(10.1596 * x + 1) + 0.0730597)

    clog = full_to_legal(clog, bit_depth) if out_legal else clog

    return as_numeric(clog)
Пример #19
0
def log_decoding_ALEXALogC(t,
                           firmware='SUP 3.x',
                           method='Linear Scene Exposure Factor',
                           EI=800):
    """
    Defines the *ALEXA Log C* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    t : numeric or array_like
        *ALEXA Log C* encoded data :math:`t`.
    firmware : unicode, optional
        **{'SUP 3.x', 'SUP 2.x'}**,
        Alexa firmware version.
    method : unicode,  optional
        **{'Linear Scene Exposure Factor', 'Normalised Sensor Signal'}**,
        Conversion method.
    EI : int,  optional
        Ei.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    References
    ----------
    -   :cite:`ARRI2012a`

    Examples
    --------
    >>> log_decoding_ALEXALogC(0.391006832034084)  # doctest: +ELLIPSIS
    0.18...
    """

    t = np.asarray(t)

    cut, a, b, c, d, e, f, _e_cut_f = (
        ALEXA_LOG_C_CURVE_CONVERSION_DATA[firmware][method][EI])

    return as_numeric(
        np.where(t > e * cut + f, (np.power(10, (t - d) / c) - b) / a,
                 (t - f) / e))
Пример #20
0
def luminance_CIE1976(Lstar, Y_n=100):
    """
    Returns the *luminance* :math:`Y` of given *Lightness* :math:`L^*` with
    given reference white *luminance* :math:`Y_n`.

    Parameters
    ----------
    Lstar : numeric or array_like
        *Lightness* :math:`L^*`
    Y_n : numeric or array_like
        White reference *luminance* :math:`Y_n`.

    Returns
    -------
    numeric or array_like
        *luminance* :math:`Y`.

    Notes
    -----
    -   Input *Lightness* :math:`L^*` and reference white *luminance*
        :math:`Y_n` are in domain [0, 100].
    -   Output *luminance* :math:`Y` is in range [0, 100].

    References
    ----------
    -   :cite:`Lindbloom2003d`
    -   :cite:`Wyszecki2000bd`

    Examples
    --------
    >>> luminance_CIE1976(37.98562910)  # doctest: +ELLIPSIS
    10.0800000...
    >>> luminance_CIE1976(37.98562910, 95)  # doctest: +ELLIPSIS
    9.5760000...
    """

    Lstar = np.asarray(Lstar)
    Y_n = np.asarray(Y_n)

    Y = as_numeric(
        np.where(Lstar > CIE_K * CIE_E,
                 Y_n * ((Lstar + 16) / 116)**3, Y_n * (Lstar / CIE_K)))

    return Y
Пример #21
0
def log_decoding_ERIMMRGB(X_p,
                          I_max=255,
                          E_min=0.001,
                          E_clip=316.2):
    """
    Defines the *ERIMM RGB* log decoding curve / electro-optical transfer
    function (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{ERIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095, and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_min : numeric, optional
        Minimum exposure limit.
    E_clip : numeric, optional
        Maximum exposure limit.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{ERIMM}`.

    Examples
    --------
    >>> log_decoding_ERIMMRGB(104.56335932049294) # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    E_t = np.exp(1) * E_min

    X = np.where(
        X_p <= I_max * ((np.log(E_t) - np.log(E_min)) /
                        (np.log(E_clip) - np.log(E_min))),
        (((np.log(E_clip) - np.log(E_min)) / (np.log(E_t) - np.log(E_min))) *
         ((X_p * E_t) / I_max)),
        np.exp((X_p / I_max) *
               (np.log(E_clip) - np.log(E_min)) + np.log(E_min)))

    return as_numeric(X)
Пример #22
0
def log_decoding_ERIMMRGB(X_p,
                          I_max=255,
                          E_min=0.001,
                          E_clip=316.2):
    """
    Defines the *ERIMM RGB* log decoding curve / electro-optical transfer
    function (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{ERIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_min : numeric, optional
        Minimum exposure limit.
    E_clip : numeric, optional
        Maximum exposure limit.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{ERIMM}`.

    Examples
    --------
    >>> log_decoding_ERIMMRGB(104.56335932049294) # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    E_t = np.exp(1) * E_min

    X = np.where(
        X_p <= I_max * ((np.log(E_t) - np.log(E_min)) /
                        (np.log(E_clip) - np.log(E_min))),
        (((np.log(E_clip) - np.log(E_min)) / (np.log(E_t) - np.log(E_min))) *
         ((X_p * E_t) / I_max)),
        np.exp((X_p / I_max) *
               (np.log(E_clip) - np.log(E_min)) + np.log(E_min)))

    return as_numeric(X)
Пример #23
0
def xy_to_CCT_Hernandez1999(xy):
    """
    Returns the correlated colour temperature :math:`T_{cp}` from given
    *CIE XYZ* tristimulus values *xy* chromaticity coordinates using
    Hernandez-Andres et al. (1999) method.

    Parameters
    ----------
    xy : array_like
        *xy* chromaticity coordinates.

    Returns
    -------
    numeric
        Correlated colour temperature :math:`T_{cp}`.

    References
    ----------
    .. [11] Hernández-Andrés, J., Lee, R. L., & Romero, J. (1999).
            Calculating correlated color temperatures across the entire gamut
            of daylight and skylight chromaticities. Applied Optics, 38(27),
            5703–5709. doi:10.1364/AO.38.005703

    Examples
    --------
    >>> xy = np.array([0.31270, 0.32900])
    >>> xy_to_CCT_Hernandez1999(xy)  # doctest: +ELLIPSIS
    6500.7420431...
    """

    x, y = tsplit(xy)

    n = (x - 0.3366) / (y - 0.1735)
    CCT = (-949.86315 + 6253.80338 * np.exp(-n / 0.92159) +
           28.70599 * np.exp(-n / 0.20039) + 0.00004 * np.exp(-n / 0.07125))

    n = np.where(CCT > 50000, (x - 0.3356) / (y - 0.1691), n)

    CCT = np.where(
        CCT > 50000, 36284.48953 + 0.00228 * np.exp(-n / 0.07861) +
        5.4535e-36 * np.exp(-n / 0.01543), CCT)

    return as_numeric(CCT)
Пример #24
0
def xy_to_CCT_Hernandez1999(xy):
    """
    Returns the correlated colour temperature :math:`T_{cp}` from given
    *CIE xy* chromaticity coordinates using *Hernandez-Andres et al. (1999)*
    method.

    Parameters
    ----------
    xy : array_like
        *CIE xy* chromaticity coordinates.

    Returns
    -------
    numeric
        Correlated colour temperature :math:`T_{cp}`.

    References
    ----------
    :cite:`Hernandez-Andres1999a`

    Examples
    --------
    >>> xy = np.array([0.31270, 0.32900])
    >>> xy_to_CCT_Hernandez1999(xy)  # doctest: +ELLIPSIS
    6500.7420431...
    """

    x, y = tsplit(xy)

    n = (x - 0.3366) / (y - 0.1735)
    CCT = (-949.86315 + 6253.80338 * np.exp(-n / 0.92159) +
           28.70599 * np.exp(-n / 0.20039) + 0.00004 * np.exp(-n / 0.07125))

    n = np.where(CCT > 50000, (x - 0.3356) / (y - 0.1691), n)

    CCT = np.where(
        CCT > 50000,
        36284.48953 + 0.00228 * np.exp(-n / 0.07861) +
        5.4535e-36 * np.exp(-n / 0.01543),
        CCT,
    )

    return as_numeric(CCT)
Пример #25
0
def log_encoding_ERIMMRGB(X, I_max=255, E_min=0.001, E_clip=316.2):
    """
    Defines the *ERIMM RGB* log encoding curve / opto-electronic transfer
    function (OETF / OECF).

    Parameters
    ----------
    X : numeric or array_like
        Linear data :math:`X_{ERIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_min : numeric, optional
        Minimum exposure limit.
    E_clip : numeric, optional
        Maximum exposure limit.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`X'_{ERIMM}`.

    References
    ----------
    -   :cite:`Spaulding2000b`

    Examples
    --------
    >>> log_encoding_ERIMMRGB(0.18)  # doctest: +ELLIPSIS
    104.5633593...
    """

    X = np.asarray(X)

    E_t = np.exp(1) * E_min

    X_p = np.select([X < 0.0, X <= E_t, X > E_t, X > E_clip], [
        0, I_max * ((np.log(E_t) - np.log(E_min)) /
                    (np.log(E_clip) - np.log(E_min))) * (X / E_t), I_max *
        ((np.log(X) - np.log(E_min)) / (np.log(E_clip) - np.log(E_min))), I_max
    ])

    return as_numeric(X_p)
Пример #26
0
def lightness_CIE1976(Y, Y_n=100):
    """
    Returns the *Lightness* :math:`L^*` of given *luminance* :math:`Y` using
    given reference white *luminance* :math:`Y_n` as per *CIE 1976*
    recommendation.

    Parameters
    ----------
    Y : numeric or array_like
        *luminance* :math:`Y`.
    Y_n : numeric or array_like, optional
        White reference *luminance* :math:`Y_n`.

    Returns
    -------
    numeric or array_like
        *Lightness* :math:`L^*`.

    Notes
    -----
    -   Input *luminance* :math:`Y` and :math:`Y_n` are in domain [0, 100].
    -   Output *Lightness* :math:`L^*` is in range [0, 100].

    References
    ----------
    -   :cite:`Lindbloom2003d`
    -   :cite:`Wyszecki2000bd`

    Examples
    --------
    >>> lightness_CIE1976(10.08)  # doctest: +ELLIPSIS
    37.9856290...
    """

    Y = np.asarray(Y)
    Y_n = np.asarray(Y_n)

    Lstar = Y / Y_n

    Lstar = as_numeric(
        np.where(Lstar <= CIE_E, CIE_K * Lstar, 116 * Lstar**(1 / 3) - 16))

    return Lstar
Пример #27
0
def log_encoding_ALEXALogC(x,
                           firmware='SUP 3.x',
                           method='Linear Scene Exposure Factor',
                           EI=800):
    """
    Defines the *ALEXA Log C* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    firmware : unicode, optional
        **{'SUP 3.x', 'SUP 2.x'}**,
        Alexa firmware version.
    method : unicode, optional
        **{'Linear Scene Exposure Factor', 'Normalised Sensor Signal'}**,
        Conversion method.
    EI : int,  optional
        Ei.

    Returns
    -------
    numeric or ndarray
        *ALEXA Log C* encoded data :math:`t`.

    References
    ----------
    -   :cite:`ARRI2012a`

    Examples
    --------
    >>> log_encoding_ALEXALogC(0.18)  # doctest: +ELLIPSIS
    0.3910068...
    """

    x = np.asarray(x)

    cut, a, b, c, d, e, f, _e_cut_f = (
        ALEXA_LOG_C_CURVE_CONVERSION_DATA[firmware][method][EI])

    return as_numeric(np.where(x > cut,
                               c * np.log10(a * x + b) + d, e * x + f))
Пример #28
0
def oetf_DICOMGSDF(L):
    """
    Defines the *DICOM - Grayscale Standard Display Function* opto-electronic
    transfer function (OETF / OECF).

    Parameters
    ----------
    L : numeric or array_like
        *Luminance* :math:`L`.

    Returns
    -------
    numeric or ndarray
        Just-Noticeable Difference (JND) Index, :math:`j` in domain 1 to 1023.

    References
    ----------
    -   :cite:`NationalElectricalManufacturersAssociation2004b`

    Examples
    --------
    >>> oetf_DICOMGSDF(130.065284012159790)  # doctest: +ELLIPSIS
    511.9964806...
    """

    L = np.asarray(L)

    L_lg = np.log10(L)

    A = DICOMGSDF_CONSTANTS.A
    B = DICOMGSDF_CONSTANTS.B
    C = DICOMGSDF_CONSTANTS.C
    D = DICOMGSDF_CONSTANTS.D
    E = DICOMGSDF_CONSTANTS.E
    F = DICOMGSDF_CONSTANTS.F
    G = DICOMGSDF_CONSTANTS.G
    H = DICOMGSDF_CONSTANTS.H
    I = DICOMGSDF_CONSTANTS.I  # noqa

    L = (A + B * L_lg + C * L_lg ** 2 + D * L_lg ** 3 + E * L_lg ** 4 +
         F * L_lg ** 5 + G * L_lg ** 6 + H * L_lg ** 7 + I * L_lg ** 8)

    return as_numeric(L)
Пример #29
0
def oetf_RIMMRGB(X, I_max=255, E_clip=2.0):
    """
    Defines the *RIMM RGB* encoding opto-electronic transfer function
    (OETF / OECF).

    *RIMM RGB* encoding non-linearity is based on that specified by
    *Recommendation ITU-R BT.709-6*.

    Parameters
    ----------
    X : numeric or array_like
        Linear data :math:`X_{RIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_clip : numeric, optional
        Maximum exposure level.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`X'_{RIMM}`.

    References
    ----------
    -   :cite:`Spaulding2000b`

    Examples
    --------
    >>> oetf_RIMMRGB(0.18)  # doctest: +ELLIPSIS
    74.3768017...
    """

    X = np.asarray(X)

    V_clip = 1.099 * E_clip**0.45 - 0.099
    q = I_max / V_clip

    X_p_RIMM = np.select([X < 0.0, X < 0.018, X >= 0.018, X > E_clip],
                         [0, 4.5 * X, 1.099 * (X**0.45) - 0.099, I_max])

    return as_numeric(q * X_p_RIMM)
Пример #30
0
    def __call__(self, x):
        """
        Evaluates the Extrapolator at given point(s).

        Parameters
        ----------
        x : numeric or array_like
            Point(s) to evaluate the Extrapolator at.

        Returns
        -------
        float or ndarray
            Extrapolated points value(s).
        """

        x = np.atleast_1d(x).astype(np.float_)

        xe = as_numeric(self.__evaluate(x))

        return xe
Пример #31
0
    def __call__(self, x):
        """
        Evaluates the interpolator at given point(s).

        Parameters
        ----------
        x : numeric or array_like
            Point(s) to evaluate the interpolant at.

        Returns
        -------
        float or ndarray
            Interpolated value(s).
        """

        x = np.atleast_1d(x).astype(self._dtype)

        xi = as_numeric(self._evaluate(x))

        return xi
Пример #32
0
    def __call__(self, x):
        """
        Evaluates the Extrapolator at given point(s).

        Parameters
        ----------
        x : numeric or array_like
            Point(s) to evaluate the Extrapolator at.

        Returns
        -------
        float or ndarray
            Extrapolated points value(s).
        """

        x = np.atleast_1d(x).astype(np.float_)

        xe = as_numeric(self._evaluate(x))

        return xe
Пример #33
0
def oetf_RIMMRGB(X, I_max=255, E_clip=2.0):
    """
    Defines the *RIMM RGB* encoding opto-electronic transfer function
    (OETF / OECF).

    *RIMM RGB* encoding non-linearity is based on that specified by
    *Recommendation ITU-R BT.709-6*.

    Parameters
    ----------
    X : numeric or array_like
        Linear data :math:`X_{RIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095, and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_clip : numeric, optional
        Maximum exposure level.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`X'_{RIMM}`.

    Examples
    --------
    >>> oetf_RIMMRGB(0.18)  # doctest: +ELLIPSIS
    74.3768017...
    """

    X = np.asarray(X)

    V_clip = 1.099 * E_clip ** 0.45 - 0.099
    q = I_max / V_clip

    X_p_RIMM = np.select(
        [X < 0.0,
         X < 0.018, X >= 0.018,
         X > E_clip],
        [0, 4.5 * X, 1.099 * (X ** 0.45) - 0.099, I_max])

    return as_numeric(q * X_p_RIMM)
Пример #34
0
    def __call__(self, x):
        """
        Evaluates the interpolating polynomial at given point(s).


        Parameters
        ----------
        x : numeric or array_like
            Point(s) to evaluate the interpolant at.

        Returns
        -------
        float or ndarray
            Interpolated value(s).
        """

        x = np.atleast_1d(x).astype(np.float_)

        xi = as_numeric(self._evaluate(x))

        return xi
Пример #35
0
    def domain_distance(self, a):
        """
        Returns the euclidean distance between given array and independent
        domain :math:`x` closest element.

        Parameters
        ----------
        a : numeric or array_like
            :math:`a` variable to compute the euclidean distance with
            independent domain :math:`x` variable.

        Returns
        -------
        numeric or array_like
            Euclidean distance between independent domain :math:`x` variable
            and given :math:`a` variable.
        """

        n = closest(self.domain, a)

        return as_numeric(np.abs(a - n))
Пример #36
0
    def test_as_numeric(self):
        """
        Tests :func:`colour.utilities.array.as_numeric` definition.
        """

        self.assertEqual(as_numeric(1), 1.0)

        self.assertEqual(as_numeric(np.array([1])), 1.0)

        np.testing.assert_almost_equal(as_numeric(np.array([1, 2, 3])),
                                       np.array([1.0, 2.0, 3.0]))

        self.assertIsInstance(as_numeric(1), DEFAULT_FLOAT_DTYPE)

        self.assertIsInstance(as_numeric(1, int), int)

        self.assertListEqual(as_numeric(['John', 'Doe']), ['John', 'Doe'])

        self.assertEqual(as_numeric('John Doe'), 'John Doe')
Пример #37
0
def eotf_RIMMRGB(X_p, I_max=255, E_clip=2.0):
    """
    Defines the *RIMM RGB* encoding electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{RIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_clip : numeric, optional
        Maximum exposure level.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{RIMM}`.

    References
    ----------
    -   :cite:`Spaulding2000b`

    Examples
    --------
    >>> eotf_RIMMRGB(74.37680178131521)  # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    V_clip = 1.099 * E_clip**0.45 - 0.099

    m = V_clip * X_p / I_max

    X_RIMM = np.where(X_p < oetf_RIMMRGB(0.018), m / 4.5,
                      ((m + 0.099) / 1.099)**(1 / 0.45))

    return as_numeric(X_RIMM)
Пример #38
0
def oetf_reverse_ARIBSTDB67(E_p, r=0.5):
    """
    Defines *ARIB STD-B67 (Hybrid Log-Gamma)* reverse opto-electrical transfer
    function (OETF / OECF).

    Parameters
    ----------
    E_p : numeric or array_like
        Non-linear signal :math:`E'`.
    r : numeric, optional
        Video level corresponding to reference white level.

    Returns
    -------
    numeric or ndarray
        Voltage :math:`E` normalized by the reference white level and
        proportional to the implicit light intensity that would be detected
        with a reference camera color channel R, G, B.

    References
    ----------
    -   :cite:`AssociationofRadioIndustriesandBusinesses2015a`

    Examples
    --------
    >>> oetf_reverse_ARIBSTDB67(0.212132034355964)  # doctest: +ELLIPSIS
    0.1799999...
    """

    E_p = np.asarray(E_p)

    a = ARIBSTDB67_CONSTANTS.a
    b = ARIBSTDB67_CONSTANTS.b
    c = ARIBSTDB67_CONSTANTS.c

    E = np.where(E_p <= oetf_ARIBSTDB67(1), (E_p / r)**2,
                 np.exp((E_p - c) / a) + b)

    return as_numeric(E)
Пример #39
0
def oetf_ARIBSTDB67(E, r=0.5):
    """
    Defines *ARIB STD-B67 (Hybrid Log-Gamma)* opto-electrical transfer
    function (OETF / OECF).

    Parameters
    ----------
    E : numeric or array_like
        Voltage normalized by the reference white level and proportional to
        the implicit light intensity that would be detected with a reference
        camera color channel R, G, B.
    r : numeric, optional
        Video level corresponding to reference white level.

    Returns
    -------
    numeric or ndarray
        Resulting non-linear signal :math:`E'`.

    References
    ----------
    -   :cite:`AssociationofRadioIndustriesandBusinesses2015a`

    Examples
    --------
    >>> oetf_ARIBSTDB67(0.18)  # doctest: +ELLIPSIS
    0.2121320...
    """

    E = np.asarray(E)

    a = ARIBSTDB67_CONSTANTS.a
    b = ARIBSTDB67_CONSTANTS.b
    c = ARIBSTDB67_CONSTANTS.c

    E_p = np.where(E <= 1, r * np.sqrt(E), a * np.log(E - b) + c)

    return as_numeric(E_p)
Пример #40
0
def eotf_BT709(V):
    """
    Defines *Recommendation ITU-R BT.709-6* electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    V : numeric or array_like
        Electrical signal :math:`V`.

    Returns
    -------
    numeric or ndarray
        Corresponding *luminance* :math:`L` of the image.

    Warning
    -------
    *Recommendation ITU-R BT.709-6* doesn't specify an electro-optical
    transfer function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *EOTF*.

    Examples
    --------
    >>> eotf_BT709(0.409007728864150)  # doctest: +ELLIPSIS
    0.1...
    """

    warning(('*Recommendation ITU-R BT.709-6* doesn\'t specify an '
             'electro-optical transfer function. This definition is used '
             'for symmetry in unit tests and others computations but should '
             'not be used as an *EOTF*!'))

    V = np.asarray(V)

    return as_numeric(np.where(V < oetf_BT709(0.018),
                               V / 4.5,
                               ((V + 0.099) / 1.099) ** (1 / 0.45)))
Пример #41
0
def eotf_RIMMRGB(X_p, I_max=255, E_clip=2.0):
    """
    Defines the *RIMM RGB* encoding electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{RIMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095, and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    E_clip : numeric, optional
        Maximum exposure level.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{RIMM}`.

    Examples
    --------
    >>> eotf_RIMMRGB(74.37680178131521)  # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    V_clip = 1.099 * E_clip ** 0.45 - 0.099

    m = V_clip * X_p / I_max

    X_RIMM = np.where(
        X_p < oetf_RIMMRGB(0.018),
        m / 4.5, ((m + 0.099) / 1.099) ** (1 / 0.45))

    return as_numeric(X_RIMM)
Пример #42
0
def log_encoding_ACEScct(lin_AP1):
    """
    Defines the *ACEScct* colourspace log encoding / opto-electronic transfer
    function.

    Parameters
    ----------
    lin_AP1 : numeric or array_like
        *lin_AP1* value.

    Returns
    -------
    numeric or ndarray
        *ACEScct* non-linear value.

    References
    ----------
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014q`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014r`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2016c`
    -   :cite:`TheAcademyofMotionPictureArtsandSciencese`

    Examples
    --------
    >>> log_encoding_ACEScct(0.18)  # doctest: +ELLIPSIS
    0.4135884...
    """

    constants = ACES_CCT_CONSTANTS

    lin_AP1 = np.asarray(lin_AP1)

    output = np.where(lin_AP1 <= constants.X_BRK,
                      constants.A * lin_AP1 + constants.B,
                      (np.log2(lin_AP1) + 9.72) / 17.52)

    return as_numeric(output)
Пример #43
0
def eotf_BT709(V):
    """
    Defines *Recommendation ITU-R BT.709-6* electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    V : numeric or array_like
        Electrical signal :math:`V`.

    Returns
    -------
    numeric or ndarray
        Corresponding *luminance* :math:`L` of the image.

    Warning
    -------
    *Recommendation ITU-R BT.709-6* doesn't specify an electro-optical
    transfer function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *EOTF*.

    Examples
    --------
    >>> eotf_BT709(0.409007728864150)  # doctest: +ELLIPSIS
    0.1...
    """

    warning(('*Recommendation ITU-R BT.709-6* doesn\'t specify an '
             'electro-optical transfer function. This definition is used '
             'for symmetry in unit tests and others computations but should '
             'not be used as an *EOTF*!'))

    V = np.asarray(V)

    return as_numeric(
        np.where(V < oetf_BT709(0.018), V / 4.5,
                 ((V + 0.099) / 1.099)**(1 / 0.45)))
Пример #44
0
def log_decoding_ACEScct(ACEScct):
    """
    Defines the *ACEScct* colourspace log decoding / electro-optical transfer
    function.

    Parameters
    ----------
    ACEScct : numeric or array_like
        *ACEScct* non-linear value.

    Returns
    -------
    numeric or ndarray
        *lin_AP1* value.

    References
    ----------
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014q`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014r`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2016c`
    -   :cite:`TheAcademyofMotionPictureArtsandSciencese`

    Examples
    --------
    >>> log_decoding_ACEScct(0.413588402492442)  # doctest: +ELLIPSIS
    0.1799999...
    """

    constants = ACES_CCT_CONSTANTS

    ACEScct = np.asarray(ACEScct)

    output = np.where(ACEScct > constants.Y_BRK, 2**(ACEScct * 17.52 - 9.72),
                      (ACEScct - constants.B) / constants.A)

    return as_numeric(output)
Пример #45
0
def log_decoding_CanonLog3(clog3_ire):
    """
    Defines the *Canon Log 3* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    clog3_ire : numeric or array_like
        *Canon Log 3* non-linear *IRE* data.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    Notes
    -----
    -   Input *Canon Log 3* non-linear *IRE* data should be converted from code
        value *CV* to *IRE* as follows: `IRE = (CV - 64) / (940 - 64)`.

    Examples
    --------
    >>> log_decoding_CanonLog3(32.795356721989336 / 100)  # doctest: +ELLIPSIS
    0.2000000...
    """

    clog3_ire = np.asarray(clog3_ire)

    x = np.select(
        (clog3_ire < 0.04076162, clog3_ire <= 0.105357102,
         clog3_ire > 0.105357102),
        (-(10**((0.069886632 - clog3_ire) / 0.42889912) - 1) / 14.98325,
         (clog3_ire - 0.073059361) / 2.3069815,
         (10**((clog3_ire - 0.069886632) / 0.42889912) - 1) / 14.98325))

    return as_numeric(x)
Пример #46
0
def log_encoding_CanonLog3(x):
    """
    Defines the *Canon Log 3* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.

    Returns
    -------
    numeric or ndarray
        *Canon Log 3* non-linear *IRE* data.
    Notes
    -----
    -   Output *Canon Log 3* non-linear *IRE* data should be converted to code
        value *CV* as follows: `CV = IRE * (940 - 64) + 64`.

    Examples
    --------
    >>> log_encoding_CanonLog3(0.20) * 100  # doctest: +ELLIPSIS
    32.7953567...
    """

    x = np.asarray(x)

    clog3_ire = np.select(
        (x < log_decoding_CanonLog3(0.04076162),
         x <= log_decoding_CanonLog3(0.105357102),
         x > log_decoding_CanonLog3(0.105357102)),
        (-(0.42889912 *
           (np.log10(-x * 14.98325 + 1)) - 0.069886632), 2.3069815 * x +
         0.073059361, 0.42889912 * np.log10(x * 14.98325 + 1) + 0.069886632))

    return as_numeric(clog3_ire)
Пример #47
0
def eotf_ROMMRGB(X_p, I_max=255):
    """
    Defines the *ROMM RGB* encoding electro-optical transfer function
    (EOTF / EOCF).

    Parameters
    ----------
    X_p : numeric or array_like
        Non-linear data :math:`X'_{ROMM}`.
    I_max : numeric, optional
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`X_{ROMM}`.

    References
    ----------
    -   :cite:`ANSI2003a`
    -   :cite:`Spaulding2000b`

    Examples
    --------
    >>> eotf_ROMMRGB(98.356413311540095) # doctest: +ELLIPSIS
    0.1...
    """

    X_p = np.asarray(X_p)

    E_t = 16**(1.8 / (1 - 1.8))

    return as_numeric(
        np.where(X_p < 16 * E_t * I_max, X_p / (16 * I_max),
                 (X_p / I_max)**1.8))
Пример #48
0
def log_decoding_ACEScc(ACEScc):
    """
    Defines the *ACEScc* colourspace log decoding / electro-optical transfer
    function.

    Parameters
    ----------
    ACEScc : numeric or array_like
        *ACEScc* non-linear value.

    Returns
    -------
    numeric or ndarray
        *lin_AP1* value.

    References
    ----------
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014q`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014r`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014t`
    -   :cite:`TheAcademyofMotionPictureArtsandSciencese`

    Examples
    --------
    >>> log_decoding_ACEScc(0.413588402492442)  # doctest: +ELLIPSIS
    0.1799999...
    """

    ACEScc = np.asarray(ACEScc)

    output = np.where(ACEScc < (9.72 - 15) / 17.52,
                      (2**(ACEScc * 17.52 - 9.72) - 2**-16) * 2,
                      2**(ACEScc * 17.52 - 9.72))
    output = np.where(ACEScc >= (np.log2(65504) + 9.72) / 17.52, 65504, output)

    return as_numeric(output)
Пример #49
0
def log_encoding_ACEScc(lin_AP1):
    """
    Defines the *ACEScc* colourspace log encoding / opto-electronic transfer
    function.

    Parameters
    ----------
    lin_AP1 : numeric or array_like
        *lin_AP1* value.

    Returns
    -------
    numeric or ndarray
        *ACEScc* non-linear value.

    References
    ----------
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014q`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014r`
    -   :cite:`TheAcademyofMotionPictureArtsandSciences2014t`
    -   :cite:`TheAcademyofMotionPictureArtsandSciencese`

    Examples
    --------
    >>> log_encoding_ACEScc(0.18)  # doctest: +ELLIPSIS
    0.4135884...
    """

    lin_AP1 = np.asarray(lin_AP1)

    output = np.where(lin_AP1 < 0, (np.log2(2**-16) + 9.72) / 17.52,
                      (np.log2(2**-16 + lin_AP1 * 0.5) + 9.72) / 17.52)
    output = np.where(lin_AP1 >= 2**-15, (np.log2(lin_AP1) + 9.72) / 17.52,
                      output)

    return as_numeric(output)
Пример #50
0
def oetf_BT709(L):
    """
    Defines *Recommendation ITU-R BT.709-6* opto-electronic transfer function
    (OETF / OECF).

    Parameters
    ----------
    L : numeric or array_like
        *Luminance* :math:`L` of the image.

    Returns
    -------
    numeric or ndarray
        Corresponding electrical signal :math:`V`.

    Examples
    --------
    >>> oetf_BT709(0.18)  # doctest: +ELLIPSIS
    0.4090077...
    """

    L = np.asarray(L)

    return as_numeric(np.where(L < 0.018, L * 4.5, 1.099 * (L**0.45) - 0.099))
Пример #51
0
def CCT_to_xy_Hernandez1999(CCT, optimisation_kwargs=None, **kwargs):
    """
    Returns the *CIE xy* chromaticity coordinates from given correlated colour
    temperature :math:`T_{cp}` using *Hernandez-Andres et al. (1999)* method.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.
    optimisation_kwargs : dict_like, optional
        Parameters for :func:`scipy.optimize.minimize` definition.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *CIE xy* chromaticity coordinates.

    Warnings
    --------
    *Hernandez-Andres et al. (1999)* method for computing *CIE xy* chromaticity
    coordinates from given correlated colour temperature is not a bijective
    function and might produce unexpected results. It is given for consistency
    with other correlated colour temperature computation methods but should be
    avoided for practical applications. The current implementation relies on
    optimization using :func:`scipy.optimize.minimize` definition and thus has
    reduced precision and poor performance.

    References
    ----------
    :cite:`Hernandez-Andres1999a`

    Examples
    --------
    >>> CCT_to_xy_Hernandez1999(6500.7420431786531)  # doctest: +ELLIPSIS
    array([ 0.3127...,  0.329...])
    """

    optimisation_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed':
            [['optimisation_parameters', 'optimisation_kwargs']],
        }, **kwargs).get('optimisation_kwargs', optimisation_kwargs)

    usage_warning('"Hernandez-Andres et al. (1999)" method for computing '
                  '"CIE xy" chromaticity coordinates from given correlated '
                  'colour temperature is not a bijective function and and'
                  'might produce unexpected results. It is given for '
                  'consistency with other correlated colour temperature '
                  'computation methods but should be avoided for practical '
                  'applications.')

    CCT = as_float_array(CCT)
    shape = list(CCT.shape)
    CCT = np.atleast_1d(CCT.reshape([-1, 1]))

    def objective_function(xy, CCT):
        """
        Objective function.
        """

        objective = np.linalg.norm(xy_to_CCT_Hernandez1999(xy) - CCT)

        return objective

    optimisation_settings = {
        'method': 'Nelder-Mead',
        'options': {
            'fatol': 1e-10,
        },
    }
    if optimisation_kwargs is not None:
        optimisation_settings.update(optimisation_kwargs)

    CCT = as_float_array([
        minimize(
            objective_function,
            x0=CCS_ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'],
            args=(CCT_i, ),
            **optimisation_settings).x for CCT_i in CCT
    ])

    return as_numeric(CCT.reshape(shape + [2]))
Пример #52
0
def gamma_function(a, exponent=1, negative_number_handling='indeterminate'):
    """
    Defines a typical gamma encoding / decoding function.

    Parameters
    ----------
    a : numeric or array_like
        Array to encode / decode.
    exponent : numeric or array_like, optional
        Encoding / decoding exponent.
    negative_number_handling : unicode, optional
        **{'Indeterminate', 'Mirror', 'Preserve', 'Clamp'}**,
        Defines the behaviour for `a` negative numbers and / or the definition
        return value:

        -   *Indeterminate*: The behaviour will be indeterminate and
            definition return value might contain *nans*.
        -   *Mirror*: The definition return value will be mirrored around
            abscissa and ordinate axis, i.e. Blackmagic Design: Davinci Resolve
            behaviour.
        -   *Preserve*: The definition will preserve any negative number in
            `a`, i.e. The Foundry Nuke behaviour.
        -   *Clamp*: The definition will clamp any negative number in `a` to 0.

    Returns
    -------
    numeric or ndarray
        Encoded / decoded array.

    Raises
    ------
    ValueError
        If the negative number handling method is not defined.

    Examples
    --------
    >>> gamma_function(0.18, 2.2)  # doctest: +ELLIPSIS
    0.0229932...
    >>> gamma_function(-0.18, 2.0)  # doctest: +ELLIPSIS
    0.0323999...
    >>> gamma_function(-0.18, 2.2)
    nan
    >>> gamma_function(-0.18, 2.2, 'Mirror')  # doctest: +ELLIPSIS
    -0.0229932...
    >>> gamma_function(-0.18, 2.2, 'Preserve')  # doctest: +ELLIPSIS
    -0.1...
    >>> gamma_function(-0.18, 2.2, 'Clamp')  # doctest: +ELLIPSIS
    0.0
    """

    a = np.asarray(a)
    exponent = np.asarray(exponent)

    negative_number_handling = negative_number_handling.lower()
    if negative_number_handling == 'indeterminate':
        return as_numeric(a**exponent)
    elif negative_number_handling == 'mirror':
        return as_numeric(np.sign(a) * np.abs(a)**exponent)
    elif negative_number_handling == 'preserve':
        return as_numeric(np.where(a < 0, a, a**exponent))
    elif negative_number_handling == 'clamp':
        return as_numeric(np.where(a < 0, 0, a**exponent))
    else:
        raise ValueError(
            'Undefined negative number handling method: "{0}".'.format(
                negative_number_handling))
Пример #53
0
def uv_to_CCT_Krystek1985(uv, optimisation_parameters=None):
    """
    Returns the correlated colour temperature :math:`T_{cp}` from given
    *CIE UCS* colourspace *uv* chromaticity coordinates using *Krystek (1985)*
    method.

    Parameters
    ----------
    uv : array_like
         *CIE UCS* colourspace *uv* chromaticity coordinates.
    optimisation_parameters : dict_like, optional
        Parameters for :func:`scipy.optimize.minimize` definition.

    Returns
    -------
    ndarray
        Correlated colour temperature :math:`T_{cp}`.

    Warnings
    --------
    *Krystek (1985)* does not give an analytical inverse transformation to
    compute the correlated colour temperature :math:`T_{cp}` from given
    *CIE UCS* colourspace *uv* chromaticity coordinates, the current
    implementation relies on optimization using :func:`scipy.optimize.minimize`
    definition and thus has reduced precision and poor performance.

    Notes
    -----
    -   *Krystek (1985)* method computations are valid for correlated colour
        temperature :math:`T_{cp}` normalised to domain [1000, 15000].

    References
    ----------
    :cite:`Krystek1985b`

    Examples
    --------
    >>> uv_to_CCT_Krystek1985(np.array([0.20047203, 0.31029290]))
    ... # doctest: +ELLIPSIS
    6504.3894290...
    """

    uv = as_float_array(uv)
    shape = uv.shape
    uv = np.atleast_1d(uv.reshape([-1, 2]))

    def objective_function(CCT, uv):
        """
        Objective function.
        """

        objective = np.linalg.norm(CCT_to_uv_Krystek1985(CCT) - uv)

        return objective

    optimisation_settings = {
        'method': 'Nelder-Mead',
        'options': {
            'fatol': 1e-10,
        },
    }
    if optimisation_parameters is not None:
        optimisation_settings.update(optimisation_parameters)

    CCT = as_float_array([
        minimize(objective_function,
                 x0=6500,
                 args=(uv_i, ),
                 **optimisation_settings).x for uv_i in uv
    ])

    return as_numeric(CCT.reshape(shape[:-1]))