예제 #1
0
파일: rec_709.py 프로젝트: scooperly/colour
def _rec_709_EOCF(value):
    """
    Defines the *Rec. 709* colourspace electro-optical conversion function.

    Parameters
    ----------
    value : numeric or array_like
        Value.

    Returns
    -------
    numeric or ndarray
        Companded value.

    Warning
    -------
    *Recommendation ITU-R BT.709-5* doesn't specify an electro-optical
    conversion function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *EOCF* for *Rec. 709*
    colourspace!
    """

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

    value = np.asarray(value)

    return np.where(value < _rec_709_OECF(0.018), value / 4.5,
                    ((value + 0.099) / 1.099)**(1 / 0.45))
예제 #2
0
파일: test_verbose.py 프로젝트: yixw/colour
    def test_suppress_warnings(self):
        """
        Tests :func:`colour.utilities.verbose.suppress_warnings` definition.
        """

        with suppress_warnings():
            warning('This is a suppressed unit test warning!')
예제 #3
0
    def x(self, value):
        """
        Setter for the **self.x** property.
        """

        if value is not None:
            value = np.atleast_1d(value).astype(self._dtype)

            assert value.ndim == 1, (
                '"x" independent variable must have exactly one dimension!')

            value_interval = interval(value)

            if value_interval.size != 1:
                warning(('"x" independent variable is not uniform, '
                         'unpredictable results may occur!'))

            self._x = value

            if self._window is not None:
                self._x_p = np.pad(
                    self._x, (self._window, self._window),
                    'linear_ramp',
                    end_values=(
                        np.min(self._x) - self._window * value_interval[0],
                        np.max(self._x) + self._window * value_interval[0]))
예제 #4
0
def eotf_sRGB(V):
    """
    Defines the *sRGB* colourspace 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.

    Examples
    --------
    >>> eotf_sRGB(0.461356129500442)  # doctest: +ELLIPSIS
    0.1...
    """

    warning(('*sRGB* *OETF* is a piece-wise function: in order to reduce '
             'noise in dark region, a line segment limits the slope of the '
             'power function (slope of a power function is infinite at zero). '
             'This is not needed for *sRGB* *EOTF*, a pure gamma 2.2 function '
             'should be use instead. 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_sRGB(0.0031308), V / 12.92,
                 ((V + 0.055) / 1.055)**2.4))
예제 #5
0
def _rec_709_EOCF(value):
    """
    Defines the *Rec. 709* colourspace electro-optical conversion function.

    Parameters
    ----------
    value : numeric or array_like
        Value.

    Returns
    -------
    numeric or ndarray
        Companded value.

    Warning
    -------
    *Recommendation ITU-R BT.709-5* doesn't specify an electro-optical
    conversion function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *EOCF* for *Rec. 709*
    colourspace!
    """

    warning(
        (
            "*Recommendation ITU-R BT.709-5* doesn't specify an"
            "electro-optical conversion function. This definition is used "
            "for symmetry in unit tests and others computations but should "
            "not be used as an *EOCF* for *Rec. 709* colourspace!"
        )
    )

    value = np.asarray(value)

    return np.where(value < _rec_709_OECF(0.018), value / 4.5, ((value + 0.099) / 1.099) ** (1 / 0.45))
예제 #6
0
    def __getattr__(self, attribute):
        """
        Returns given attribute value while handling deprecation.

        Parameters
        ----------
        attribute : unicode
            Attribute name.

        Returns
        -------
        object
            Attribute value.

        Raises
        ------
        AttributeError
            If the attribute is not defined.
        """

        change = self._changes.get(attribute)
        if change is not None:
            if not isinstance(change, Removed):
                warning(str(change))
                return get_attribute(change[1])
            else:
                raise AttributeError(str(change))

        return getattr(self._module, attribute)
예제 #7
0
def random_triplet_generator(size,
                             limits=np.array([[0, 1], [0, 1], [0, 1]]),
                             random_state=RANDOM_STATE):
    """
    Returns a generator yielding random triplets.

    Parameters
    ----------
    size : integer
        Generator size.
    limits : array_like, (3, 2)
        Random values limits on each triplet axis.
    random_state : RandomState
         Mersenne Twister pseudo-random number generator.

    Returns
    -------
    generator
        Random triplets generator.

    Notes
    -----
    The doctest is assuming that :func:`np.random.RandomState` definition will
    return the same sequence no matter which *OS* or *Python* version is used.
    There is however no formal promise about the *prng* sequence
    reproducibility of either *Python* or *Numpy* implementations: Laurent.
    (2012). Reproducibility of python pseudo-random numbers across systems and
    versions? Retrieved January 20, 2015, from http://stackoverflow.com/\
questions/8786084/reproducibility-of-python-pseudo-random-numbers-\
across-systems-and-versions

    Examples
    --------
    >>> from pprint import pprint
    >>> prng = np.random.RandomState(4)
    >>> pprint(  # doctest: +ELLIPSIS
    ...     tuple(random_triplet_generator(10, random_state=prng)))
    (array([ 0.9670298...,  0.5472322...,  0.9726843...]),
     array([ 0.7148159...,  0.6977288...,  0.2160895...]),
     array([ 0.9762744...,  0.0062302...,  0.2529823...]),
     array([ 0.4347915...,  0.7793829...,  0.1976850...]),
     array([ 0.8629932...,  0.9834006...,  0.1638422...]),
     array([ 0.5973339...,  0.0089861...,  0.3865712...]),
     array([ 0.0441600...,  0.9566529...,  0.4361466...]),
     array([ 0.9489773...,  0.7863059...,  0.8662893...]),
     array([ 0.1731654...,  0.0749485...,  0.6007427...]),
     array([ 0.1679721...,  0.7333801...,  0.4084438...]))
    """

    integer_size = int(size)
    if integer_size != size:
        warning(('"size" has been cast to integer: {0}'.format(integer_size)))

    for _ in range(integer_size):
        yield np.array([
            random_state.uniform(*limits[0]),
            random_state.uniform(*limits[1]),
            random_state.uniform(*limits[2])
        ])
예제 #8
0
파일: random.py 프로젝트: Nick-Shaw/colour
def random_triplet_generator(size,
                             limits=np.array([[0, 1], [0, 1], [0, 1]]),
                             random_state=RANDOM_STATE):
    """
    Returns a generator yielding random triplets.

    Parameters
    ----------
    size : integer
        Generator size.
    limits : array_like, (3, 2)
        Random values limits on each triplet axis.
    random_state : RandomState
         Mersenne Twister pseudo-random number generator.

    Returns
    -------
    generator
        Random triplets generator.

    Notes
    -----
    The doctest is assuming that :func:`np.random.RandomState` definition will
    return the same sequence no matter which *OS* or *Python* version is used.
    There is however no formal promise about the *prng* sequence
    reproducibility of either *Python* or *Numpy* implementations: Laurent.
    (2012). Reproducibility of python pseudo-random numbers across systems and
    versions? Retrieved January 20, 2015, from http://stackoverflow.com/\
questions/8786084/reproducibility-of-python-pseudo-random-numbers-\
across-systems-and-versions

    Examples
    --------
    >>> from pprint import pprint
    >>> prng = np.random.RandomState(4)
    >>> pprint(  # doctest: +ELLIPSIS
    ...     tuple(random_triplet_generator(10, random_state=prng)))
    (array([ 0.9670298...,  0.5472322...,  0.9726843...]),
     array([ 0.7148159...,  0.6977288...,  0.2160895...]),
     array([ 0.9762744...,  0.0062302...,  0.2529823...]),
     array([ 0.4347915...,  0.7793829...,  0.1976850...]),
     array([ 0.8629932...,  0.9834006...,  0.1638422...]),
     array([ 0.5973339...,  0.0089861...,  0.3865712...]),
     array([ 0.0441600...,  0.9566529...,  0.4361466...]),
     array([ 0.9489773...,  0.7863059...,  0.8662893...]),
     array([ 0.1731654...,  0.0749485...,  0.6007427...]),
     array([ 0.1679721...,  0.7333801...,  0.4084438...]))
    """

    integer_size = int(size)
    if integer_size != size:
        warning(('"size" has been cast to integer: {0}'.format(
            integer_size)))

    for _ in range(integer_size):
        yield np.array([random_state.uniform(*limits[0]),
                        random_state.uniform(*limits[1]),
                        random_state.uniform(*limits[2])])
예제 #9
0
파일: cct.py 프로젝트: scooperly/colour
def CCT_to_xy_Kang2002(CCT):
    """
    Returns the *CIE XYZ* tristimulus values *xy* chromaticity coordinates from
    given correlated colour temperature :math:`T_{cp}` using Kang et al. (2002)
    method.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    .. [11] Kang, B., Moon, O., Hong, C., Lee, H., Cho, B., & Kim, Y. (2002).
            Design of advanced color: Temperature control system for HDTV
            applications. Journal of the Korean …, 41(6), 865–871. Retrieved
            from http://cat.inist.fr/?aModele=afficheN&cpsidt=14448733

    Examples
    --------
    >>> CCT_to_xy_Kang2002(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.313426...,  0.3235959...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 1667, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[1667, 25000], unpredictable results may occur!'))

    x = np.where(
        CCT <= 4000, -0.2661239 * 10**9 / CCT**3 - 0.2343589 * 10**6 / CCT**2 +
        0.8776956 * 10**3 / CCT + 0.179910, -3.0258469 * 10**9 / CCT**3 +
        2.1070379 * 10**6 / CCT**2 + 0.2226347 * 10**3 / CCT + 0.24039)

    y = np.select([
        CCT <= 2222,
        np.logical_and(CCT > 2222, CCT <= 4000), CCT > 4000
    ], [
        -1.1063814 * x**3 - 1.34811020 * x**2 + 2.18555832 * x - 0.20219683,
        -0.9549476 * x**3 - 1.37418593 * x**2 + 2.09137015 * x - 0.16748867,
        3.0817580 * x**3 - 5.8733867 * x**2 + 3.75112997 * x - 0.37001483
    ])

    xy = tstack((x, y))

    return xy
예제 #10
0
def CCT_to_xy_CIE_D(CCT):
    """
    Converts from the correlated colour temperature :math:`T_{cp}` of a
    *CIE Illuminant D Series* to the chromaticity of that
    *CIE Illuminant D Series* illuminant.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    .. [12] Wyszecki, G., & Stiles, W. S. (2000). CIE Method of Calculating
            D-Illuminants. In Color Science: Concepts and Methods,
            Quantitative Data and Formulae (pp. 145–146). Wiley.
            ISBN:978-0471399186

    Examples
    --------
    >>> CCT_to_xy_CIE_D(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.3127077...,  0.3291128...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 4000, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[4000, 25000], unpredictable results may occur!'))

    x = np.where(CCT <= 7000,
                 -4.607 * 10 ** 9 / CCT ** 3 +
                 2.9678 * 10 ** 6 / CCT ** 2 +
                 0.09911 * 10 ** 3 / CCT +
                 0.244063,
                 -2.0064 * 10 ** 9 / CCT ** 3 +
                 1.9018 * 10 ** 6 / CCT ** 2 +
                 0.24748 * 10 ** 3 / CCT +
                 0.23704)

    y = -3 * x ** 2 + 2.87 * x - 0.275

    xy = tstack((x, y))

    return xy
예제 #11
0
파일: cct.py 프로젝트: fangjy88/colour
def CCT_to_xy_CIE_D(CCT):
    """
    Converts from the correlated colour temperature :math:`T_{cp}` of a
    *CIE Illuminant D Series* to the chromaticity of that
    *CIE Illuminant D Series* illuminant.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    .. [12] Wyszecki, G., & Stiles, W. S. (2000). CIE Method of Calculating
            D-Illuminants. In Color Science: Concepts and Methods,
            Quantitative Data and Formulae (pp. 145–146). Wiley.
            ISBN:978-0471399186

    Examples
    --------
    >>> CCT_to_xy_CIE_D(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.3127077...,  0.3291128...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 4000, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[4000, 25000], unpredictable results may occur!'))

    x = np.where(CCT <= 7000,
                 -4.607 * 10 ** 9 / CCT ** 3 +
                 2.9678 * 10 ** 6 / CCT ** 2 +
                 0.09911 * 10 ** 3 / CCT +
                 0.244063,
                 -2.0064 * 10 ** 9 / CCT ** 3 +
                 1.9018 * 10 ** 6 / CCT ** 2 +
                 0.24748 * 10 ** 3 / CCT +
                 0.23704)

    y = -3 * x ** 2 + 2.87 * x - 0.275

    xy = tstack((x, y))

    return xy
예제 #12
0
    def read_metadata(self):
        """
        Reads image relevant exif metadata at :attr:`Image.path` attribute.

        Returns
        -------
        Metadata
            Image relevant exif metadata.
        """

        logging.info('Reading "{0}" image metadata.'.format(self._path))
        exif_data = read_exif_tags(self._path)

        if not exif_data.get('EXIF'):
            warning(
                '"{0}" file has no "Exif" data, metadata will be undefined!'.
                format(self._path))
            self.metadata = Metadata(*[None] * 6)
            return self.metadata

        f_number = exif_data['EXIF'].get('F Number')
        if f_number is not None:
            f_number = parse_exif_numeric(f_number[0])

        exposure_time = exif_data['EXIF'].get('Exposure Time')
        if exposure_time is not None:
            exposure_time = parse_exif_fraction(exposure_time[0])

        iso = exif_data['EXIF'].get('ISO')
        if iso is not None:
            iso = parse_exif_numeric(iso[0])

        black_level = exif_data['EXIF'].get('Black Level')
        if black_level is not None:
            black_level = parse_exif_array(black_level[0])
            black_level = as_float_array(black_level) / 65535

        white_level = exif_data['EXIF'].get('White Level')
        if white_level is not None:
            white_level = parse_exif_array(white_level[0])
            white_level = as_float_array(white_level) / 65535

        white_balance_multipliers = exif_data['EXIF'].get('As Shot Neutral')
        if white_balance_multipliers is not None:
            white_balance_multipliers = parse_exif_array(
                white_balance_multipliers[0])
            white_balance_multipliers = as_float_array(
                white_balance_multipliers) / white_balance_multipliers[1]

        self.metadata = Metadata(f_number, exposure_time, iso, black_level,
                                 white_level, white_balance_multipliers)

        return self.metadata
예제 #13
0
파일: cct.py 프로젝트: ajun73/Work_Code
def CCT_to_xy_Kang2002(CCT):
    """
    Returns the *CIE XYZ* tristimulus values *xy* chromaticity coordinates from
    given correlated colour temperature :math:`T_{cp}` using
    *Kang et alii (2002)* method.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    -   :cite:`Kang2002a`

    Examples
    --------
    >>> CCT_to_xy_Kang2002(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.313426...,  0.3235959...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 1667, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[1667, 25000], unpredictable results may occur!'))

    x = np.where(
        CCT <= 4000, -0.2661239 * 10 ** 9 / CCT ** 3 -
        0.2343589 * 10 ** 6 / CCT ** 2 + 0.8776956 * 10 ** 3 / CCT + 0.179910,
        -3.0258469 * 10 ** 9 / CCT ** 3 + 2.1070379 * 10 ** 6 / CCT ** 2 +
        0.2226347 * 10 ** 3 / CCT + 0.24039)

    cnd_l = [CCT <= 2222, np.logical_and(CCT > 2222, CCT <= 4000), CCT > 4000]
    i = -1.1063814 * x ** 3 - 1.34811020 * x ** 2 + 2.18555832 * x - 0.20219683
    j = -0.9549476 * x ** 3 - 1.37418593 * x ** 2 + 2.09137015 * x - 0.16748867
    k = 3.0817580 * x ** 3 - 5.8733867 * x ** 2 + 3.75112997 * x - 0.37001483
    y = np.select(cnd_l, [i, j, k])

    xy = tstack((x, y))

    return xy
예제 #14
0
def light_probe_sampling_variance_minimization_Viriyothai2009(
        light_probe, lights_count=16, colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Sample given light probe to find lights using *Viriyothai (2009)* variance
    minimization light probe sampling algorithm.

    Parameters
    ----------
    light_probe : array_like
        Array to sample for lights.
    lights_count : int
        Amount of lights to generate.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    list
        list of
        :class:`colour_hdri.sampling.variance_minimization.Light_Specification`
        lights.

    References
    ----------
    :cite:`Viriyothai2009`
    """

    light_probe = as_float_array(light_probe)

    iterations = np.sqrt(lights_count).astype(np.int_)
    if iterations**2 != lights_count:
        warning(
            '{0} lights requested, {1} will be effectively computed!'.format(
                lights_count, iterations**2))

    Y = RGB_luminance(light_probe, colourspace.primaries,
                      colourspace.whitepoint)
    regions = find_regions_variance_minimization_Viriyothai2009(Y, iterations)

    lights = []
    for region in regions:
        y_min, y_max, x_min, x_max = region
        c = centroid(Y[y_min:y_max, x_min:x_max])
        c = (c + np.array([y_min, x_min]))
        light_probe_c = light_probe[y_min:y_max, x_min:x_max]
        lights.append(
            Light_Specification((c / np.array(Y.shape))[::-1],
                                np.sum(np.sum(light_probe_c, 0), 0), c))

    return lights
예제 #15
0
파일: bt_1886.py 프로젝트: Nick-Shaw/colour
def oetf_BT1886(L, L_B=64, L_W=940):
    """
    Defines *Recommendation ITU-R BT.1886* opto-electrical transfer function
    (OETF / OECF).

    Parameters
    ----------
    L : numeric or array_like
        Screen luminance in :math:`cd/m^2`.
    L_B : numeric, optional
        Screen luminance for black.
    L_W : numeric, optional
        Screen luminance for white.

    Returns
    -------
    numeric or ndarray
        Input video signal level (normalized, black at :math:`V = 0`, to white
        at :math:`V = 1`.

    Warning
    -------
    *Recommendation ITU-R BT.1886* doesn't specify an opto-electrical
    transfer function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *OETF*.

    Examples
    --------
    >>> oetf_BT1886(277.98159179331145)  # doctest: +ELLIPSIS
    0.4090077...
    """

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

    L = np.asarray(L)

    gamma = 2.40
    gamma_d = 1 / gamma

    n = L_W ** gamma_d - L_B ** gamma_d
    a = n ** gamma
    b = L_B ** gamma_d / n

    V = (L / a) ** gamma_d - b

    return V
예제 #16
0
파일: bt_1886.py 프로젝트: yeekzhang/colour
def oetf_BT1886(L, L_B=0, L_W=1):
    """
    Defines *Recommendation ITU-R BT.1886* opto-electrical transfer function
    (OETF / OECF).

    Parameters
    ----------
    L : numeric or array_like
        Screen luminance in :math:`cd/m^2`.
    L_B : numeric, optional
        Screen luminance for black.
    L_W : numeric, optional
        Screen luminance for white.

    Returns
    -------
    numeric or ndarray
        Input video signal level (normalized, black at :math:`V = 0`, to white
        at :math:`V = 1`.

    Warning
    -------
    *Recommendation ITU-R BT.1886* doesn't specify an opto-electrical
    transfer function. This definition is used for symmetry in unit tests and
    other computations but should not be used as an *OETF*.

    Examples
    --------
    >>> oetf_BT1886(0.11699185725296059)  # doctest: +ELLIPSIS
    0.4090077...
    """

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

    L = np.asarray(L)

    gamma = 2.40
    gamma_d = 1 / gamma

    n = L_W**gamma_d - L_B**gamma_d
    a = n**gamma
    b = L_B**gamma_d / n

    V = (L / a)**gamma_d - b

    return V
예제 #17
0
        def luminance_average_key(image):
            """
            Comparison key function.
            """

            f_number = image.metadata.f_number
            exposure_time = image.metadata.exposure_time
            iso = image.metadata.iso

            if None in (f_number, exposure_time, iso):
                warning('"{0}" exposure data is missing, average luminance '
                        'sorting is inapplicable!'.format(image.path))
                return None

            return 1 / average_luminance(f_number, exposure_time, iso)
예제 #18
0
파일: cct.py 프로젝트: ajun73/Work_Code
def CCT_to_xy_CIE_D(CCT):
    """
    Converts from the correlated colour temperature :math:`T_{cp}` of a
    *CIE Illuminant D Series* to the chromaticity of that
    *CIE Illuminant D Series* illuminant.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    -   :cite:`Wyszecki2000z`

    Examples
    --------
    >>> CCT_to_xy_CIE_D(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.3127077...,  0.3291128...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 4000, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[4000, 25000], unpredictable results may occur!'))

    x = np.where(
        CCT <= 7000, -4.607 * 10 ** 9 / CCT ** 3 + 2.9678 * 10 ** 6 / CCT ** 2
        + 0.09911 * 10 ** 3 / CCT + 0.244063, -2.0064 * 10 ** 9 / CCT ** 3 +
        1.9018 * 10 ** 6 / CCT ** 2 + 0.24748 * 10 ** 3 / CCT + 0.23704)

    y = -3 * x ** 2 + 2.87 * x - 0.275

    xy = tstack((x, y))

    return xy
예제 #19
0
def eotf_ARIBSTDB67(E_p, r=0.5):
    """
    Defines *ARIB STD-B67 (Hybrid Log-Gamma)* electro-optical transfer
    function (EOTF / EOCF).

    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.

    Warning
    -------
    *ARIB STD-B67 (Hybrid Log-Gamma)* 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_ARIBSTDB67(0.212132034355964)  # doctest: +ELLIPSIS
    0.1799999...
    """

    warning(('*ARIB STD-B67 (Hybrid Log-Gamma)* 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*!'))

    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)
예제 #20
0
    def test_nan_first_order_colour_fit(self):
        """
        Tests :func:`colour.characterisation.fitting.first_order_colour_fit`
        definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            try:
                first_order_colour_fit(np.vstack((M1, case)),
                                       np.vstack((M2, case)))
            except ValueError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #21
0
    def test_nan_first_order_colour_fit(self):
        """
        Tests :func:`colour.characterisation.fitting.first_order_colour_fit`
        definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            try:
                first_order_colour_fit(np.vstack((M1, case)),
                                       np.vstack((M2, case)))
            except (ValueError, LinAlgError):
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #22
0
    def test_nan_normalised_primary_matrix(self):
        """
        Tests :func:`colour.models.rgb.derivation.normalised_primary_matrix`
        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:
            P = np.array(np.vstack((case, case, case)))
            W = np.array(case)
            try:
                normalised_primary_matrix(P, W)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #23
0
    def test_nan_normalised_primary_matrix(self):
        """
        Tests :func:`colour.models.rgb.derivation.normalised_primary_matrix`
        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:
            P = np.array(np.vstack((case, case, case)))
            W = np.array(case)
            try:
                normalised_primary_matrix(P, W)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #24
0
    def test_nan__call__(self):
        """
        Tests :func:`colour.algebra.interpolation.SpragueInterpolator.__call__`
        method nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            try:
                sprague_interpolator = SpragueInterpolator(
                    np.array(case), np.array(case))
                sprague_interpolator(case[0])
            except AssertionError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #25
0
파일: signal.py 프로젝트: ajun73/Work_Code
    def range(self, value):
        """
        Setter for the **self.range** property.
        """

        if value is not None:
            if not np.all(np.isfinite(value)):
                warning('"range" variable is not finite, '
                        'unpredictable results may occur!\n{0}'.format(value))

            value = np.copy(value).astype(self.dtype)

            if self._domain is not None:
                assert value.size == self._domain.size, (
                    '"domain" and "range" variables must have same size!')

            self._range = value
            self._create_function()
예제 #26
0
    def test_nan__call__(self):
        """
        Tests :func:`colour.algebra.interpolation.SpragueInterpolator.__call__`
        method nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            try:
                sprague_interpolator = SpragueInterpolator(
                    np.array(case), np.array(case))
                sprague_interpolator(case[0])
            except AssertionError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #27
0
def lightness_Wyszecki1963(Y, **kwargs):
    """
    Returns the *Lightness* :math:`W` of given *luminance* :math:`Y` using
    *Wyszecki (1963)* method.


    Parameters
    ----------
    Y : numeric or array_like
        *luminance* :math:`Y`.
    \**kwargs : dict, optional
        Unused parameter provided for signature compatibility with other
        *Lightness* computation objects.

    Returns
    -------
    numeric or array_like
        *Lightness* :math:`W`.

    Notes
    -----
    -   Input *luminance* :math:`Y` is in domain [0, 100].
    -   Output *Lightness* :math:`W` is in domain [0, 100].

    References
    ----------
    .. [3]  Wyszecki, G. (1963). Proposal for a New Color-Difference Formula.
            J. Opt. Soc. Am., 53(11), 1318–1319. doi:10.1364/JOSA.53.001318

    Examples
    --------
    >>> lightness_Wyszecki1963(10.08)  # doctest: +ELLIPSIS
    37.0041149...
    """

    Y = np.asarray(Y)

    if np.any(Y < 1) or np.any(Y > 98):
        warning(('"W*" Lightness computation is only applicable for '
                 '1% < "Y" < 98%, unpredictable results may occur!'))

    W = 25 * (Y**(1 / 3)) - 17

    return W
예제 #28
0
파일: lightness.py 프로젝트: brehm/colour
def lightness_Wyszecki1963(Y, **kwargs):
    """
    Returns the *Lightness* :math:`W` of given *luminance* :math:`Y` using
    *Wyszecki (1963)* method.


    Parameters
    ----------
    Y : numeric or array_like
        *luminance* :math:`Y`.
    \**kwargs : dict, optional
        Unused parameter provided for signature compatibility with other
        *Lightness* computation objects.

    Returns
    -------
    numeric or array_like
        *Lightness* :math:`W`.

    Notes
    -----
    -   Input *luminance* :math:`Y` is in domain [0, 100].
    -   Output *Lightness* :math:`W` is in domain [0, 100].

    References
    ----------
    .. [3]  Wyszecki, G. (1963). Proposal for a New Color-Difference Formula.
            J. Opt. Soc. Am., 53(11), 1318–1319. doi:10.1364/JOSA.53.001318

    Examples
    --------
    >>> lightness_Wyszecki1963(10.08)  # doctest: +ELLIPSIS
    37.0041149...
    """

    Y = np.asarray(Y)

    if np.any(Y < 1) or np.any(Y > 98):
        warning(('"W*" Lightness computation is only applicable for '
                 '1% < "Y" < 98%, unpredictable results may occur!'))

    W = 25 * (Y ** (1 / 3)) - 17

    return W
예제 #29
0
    def test_nan_RGB_luminance(self):
        """
        Tests :func:`colour.models.rgb.derivation.RGB_luminance`
        definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            RGB = np.array(case)
            P = np.array(np.vstack((case[0:2], case[0:2], case[0:2])))
            W = np.array(case[0:2])
            try:
                RGB_luminance(RGB, P, W)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #30
0
def lightness_wyszecki1964(Y, **kwargs):
    """
    Returns the *Lightness* :math:`W^*` of given *luminance* :math:`Y` using
    *Wyszecki (1964)* method.


    Parameters
    ----------
    Y : numeric
        *luminance* :math:`Y`.
    \*\*kwargs : \*\*, optional
        Unused parameter provided for signature compatibility with other
        *Lightness* computation objects.

    Returns
    -------
    numeric
        *Lightness* :math:`W^*`.

    Notes
    -----
    -   Input *luminance* :math:`Y` is in domain [0, 100].
    -   Output *Lightness* :math:`W^*` is in domain [0, 100].

    References
    ----------
    .. [2]  http://en.wikipedia.org/wiki/Lightness
            (Last accessed 13 April 2014)

    Examples
    --------
    >>> lightness_wyszecki1964(10.08)  # doctest: +ELLIPSIS
    37.0041149...
    """

    if not 1 < Y < 98:
        warning(('"W*" Lightness computation is only applicable for '
                 '1% < "Y" < 98%, unpredictable results may occur!'))

    W = 25 * (Y**(1 / 3)) - 17

    return W
예제 #31
0
파일: lightness.py 프로젝트: KevinJW/colour
def lightness_wyszecki1964(Y, **kwargs):
    """
    Returns the *Lightness* :math:`W^*` of given *luminance* :math:`Y` using
    *Wyszecki (1964)* method.


    Parameters
    ----------
    Y : numeric
        *luminance* :math:`Y`.
    \*\*kwargs : \*\*, optional
        Unused parameter provided for signature compatibility with other
        *Lightness* computation objects.

    Returns
    -------
    numeric
        *Lightness* :math:`W^*`.

    Notes
    -----
    -   Input *luminance* :math:`Y` is in domain [0, 100].
    -   Output *Lightness* :math:`W^*` is in domain [0, 100].

    References
    ----------
    .. [2]  http://en.wikipedia.org/wiki/Lightness
            (Last accessed 13 April 2014)

    Examples
    --------
    >>> lightness_wyszecki1964(10.08)  # doctest: +ELLIPSIS
    37.0041149...
    """

    if not 1 < Y < 98:
        warning(('"W*" Lightness computation is only applicable for '
                 '1% < "Y" < 98%, unpredictable results may occur!'))

    W = 25 * (Y ** (1 / 3)) - 17

    return W
예제 #32
0
    def test_nan_chromatic_adaptation_Fairchild1990(self):
        """
        Tests :func:`colour.adaptation.fairchild1990.\
chromatic_adaptation_Fairchild1990` definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            XYZ_1 = np.array(case)
            XYZ_n = np.array(case)
            XYZ_r = np.array(case)
            Y_n = case[0]
            try:
                chromatic_adaptation_Fairchild1990(XYZ_1, XYZ_n, XYZ_r, Y_n)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #33
0
    def test_nan_chromatic_adaptation_Fairchild1990(self):
        """
        Tests :func:`colour.adaptation.fairchild1990.\
chromatic_adaptation_Fairchild1990` definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            XYZ_1 = np.array(case)
            XYZ_n = np.array(case)
            XYZ_r = np.array(case)
            Y_n = case[0]
            try:
                chromatic_adaptation_Fairchild1990(XYZ_1, XYZ_n, XYZ_r, Y_n)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #34
0
def load(dataset):
    """
    Loads given dataset: The dataset is pulled locally, i.e. synced if required
    and then its data is loaded.

    Parameters
    ----------
    dataset : unicode or int
        Dataset id, i.e. the *Zenodo* record number or title.

    Returns
    -------
    object
        Dataset data.

    Examples
    --------
    >>> len(load('3245883').keys())
    28
    >>> len(load(
    ...     'Camera Spectral Sensitivity Database - '
    ...     'Jiang et al. (2013)').keys())
    28
    """

    global _HAS_TITLE_KEYS

    if not _HAS_TITLE_KEYS:
        for key in list(DATASET_LOADERS.keys())[:]:
            dataset_loader = datasets().get(key)
            if not dataset_loader:
                continue

            title = dataset_loader.title
            if title in DATASET_LOADERS:
                warning('"{0}" key is already defined in the dataset loaders!'.
                        format(title))
            DATASET_LOADERS[title] = DATASET_LOADERS[key]
        _HAS_TITLE_KEYS = True

    return DATASET_LOADERS[six.text_type(dataset)]().content
예제 #35
0
def lightness_Wyszecki1963(Y):
    """
    Returns the *Lightness* :math:`W` of given *luminance* :math:`Y` using
    *Wyszecki (1963)* method.


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

    Returns
    -------
    numeric or array_like
        *Lightness* :math:`W`.

    Notes
    -----
    -   Input *luminance* :math:`Y` is in domain [0, 100].
    -   Output *Lightness* :math:`W` is in range [0, 100].

    References
    ----------
    -   :cite:`Wyszecki1963b`

    Examples
    --------
    >>> lightness_Wyszecki1963(10.08)  # doctest: +ELLIPSIS
    37.0041149...
    """

    Y = np.asarray(Y)

    if np.any(Y < 1) or np.any(Y > 98):
        warning(('"W*" Lightness computation is only applicable for '
                 '1% < "Y" < 98%, unpredictable results may occur!'))

    W = 25 * (Y**(1 / 3)) - 17

    return W
예제 #36
0
파일: signal.py 프로젝트: ajun73/Work_Code
    def domain(self, value):
        """
        Setter for the **self.domain** property.
        """

        if value is not None:
            if not np.all(np.isfinite(value)):
                warning('"domain" variable is not finite, '
                        'unpredictable results may occur!\n{0}'.format(value))

            value = np.copy(value).astype(self.dtype)

            if self._range is not None:
                if value.size != self._range.size:
                    warning(
                        '"domain" and "range" variables have different size, '
                        '"range" variable will be resized to '
                        '"domain" variable shape!')
                    self._range = np.resize(self._range, value.shape)

            self._domain = value
            self._create_function()
예제 #37
0
파일: bt_709.py 프로젝트: crowsonkb/colour
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)))
예제 #38
0
파일: bt_709.py 프로젝트: Nick-Shaw/colour
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)))
예제 #39
0
파일: cct.py 프로젝트: fangjy88/colour
def CCT_to_xy_Kang2002(CCT):
    """
    Returns the *CIE XYZ* tristimulus values *xy* chromaticity coordinates from
    given correlated colour temperature :math:`T_{cp}` using Kang et al. (2002)
    method.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.

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

    Raises
    ------
    ValueError
        If the correlated colour temperature is not in appropriate domain.

    References
    ----------
    .. [11] Kang, B., Moon, O., Hong, C., Lee, H., Cho, B., & Kim, Y. (2002).
            Design of advanced color: Temperature control system for HDTV
            applications. Journal of the Korean …, 41(6), 865–871. Retrieved
            from http://cat.inist.fr/?aModele=afficheN&cpsidt=14448733

    Examples
    --------
    >>> CCT_to_xy_Kang2002(6504.38938305)  # doctest: +ELLIPSIS
    array([ 0.313426...,  0.3235959...])
    """

    CCT = np.asarray(CCT)

    if np.any(CCT[np.asarray(np.logical_or(CCT < 1667, CCT > 25000))]):
        warning(('Correlated colour temperature must be in domain '
                 '[1667, 25000], unpredictable results may occur!'))

    x = np.where(CCT <= 4000,
                 -0.2661239 * 10 ** 9 / CCT ** 3 -
                 0.2343589 * 10 ** 6 / CCT ** 2 +
                 0.8776956 * 10 ** 3 / CCT +
                 0.179910,
                 -3.0258469 * 10 ** 9 / CCT ** 3 +
                 2.1070379 * 10 ** 6 / CCT ** 2 +
                 0.2226347 * 10 ** 3 / CCT +
                 0.24039)

    y = np.select([CCT <= 2222,
                   np.logical_and(CCT > 2222, CCT <= 4000),
                   CCT > 4000],
                  [-1.1063814 * x ** 3 -
                   1.34811020 * x ** 2 +
                   2.18555832 * x -
                   0.20219683,
                   -0.9549476 * x ** 3 -
                   1.37418593 * x ** 2 +
                   2.09137015 * x -
                   0.16748867,
                   3.0817580 * x ** 3 -
                   5.8733867 * x ** 2 +
                   3.75112997 * x -
                   0.37001483])

    xy = tstack((x, y))

    return xy
예제 #40
0
        """
        Interpolates a 1-D function using cubic spline interpolation.

        Notes
        -----
        This class is a wrapper around *scipy.interpolate.interp1d* class.
        """

        def __init__(self, *args, **kwargs):
            # TODO: Implements proper wrapper to ensure return values
            # consistency and avoid having to cast to numeric in
            # :meth:`SpectralPowerDistribution.interpolate` method.
            super(SplineInterpolator, self).__init__(
                kind='cubic', *args, **kwargs)
else:
    warning(('"scipy.interpolate.interp1d" interpolator is unavailable, using '
             '"LinearInterpolator1d" instead!'))

    SplineInterpolator = LinearInterpolator1d


class SpragueInterpolator(object):
    """
    Constructs a fifth-order polynomial that passes through :math:`y` dependent
    variable.

    Sprague (1880) method is recommended by the *CIE* for interpolating
    functions having a uniformly spaced independent variable.

    Parameters
    ----------
    x : array_like
예제 #41
0
def main():
    """
    Starts the application.

    Return
    ------
    bool
        Definition success.
    """

    arguments = command_line_arguments()

    if arguments.version:
        print('{0} - {1}'.format(__application_name__, __version__))

        return True

    settings = json.load(open(SETTINGS_FILE))
    if arguments.settings_file is not None:
        assert os.path.exists(
            arguments.settings_file), ('"{0}" file doesn\'t exists!'.format(
                arguments.settings_file))
        settings.update(json.load(open(arguments.settings_file)))

    input_linearity = arguments.input_linearity.lower()
    if input_linearity == 'linear':
        input_linear = True
    elif input_linearity == 'oecf':
        input_linear = False
    else:
        input_extension = os.path.splitext(arguments.input_image)[1].lower()
        if input_extension in LINEAR_IMAGE_FORMATS:
            input_linear = True
        else:
            input_linear = False

    if arguments.input_image is not None:
        assert os.path.exists(arguments.input_image), (
            '"{0}" input image doesn\'t exists!'.format(arguments.input_image))

        image_path = arguments.input_image
    else:
        image_path = DEFAULT_IMAGE_PATH

    try:
        image = read_image(str(image_path))
        if not input_linear:
            colourspace = RGB_COLOURSPACES[arguments.input_oecf]
            image = colourspace.decoding_cctf(image)

        # Keeping RGB channels only.
        image = image[..., 0:3]

        image = image[::int(arguments.input_resample), ::int(
            arguments.input_resample)]
    except ImportError:
        warning(
            '"OpenImageIO" is not available, image reading is not supported, '
            'falling back to some random noise!')

        image = None

    if not arguments.enable_warnings:
        warnings.filterwarnings("ignore")

    ColourAnalysis(image, arguments.input_image, arguments.input_colourspace,
                   arguments.input_oecf, input_linear,
                   arguments.reference_colourspace,
                   arguments.correlate_colourspace, settings, arguments.layout)
    return run()
예제 #42
0
파일: cct.py 프로젝트: fangjy88/colour
def uv_to_CCT_Ohno2013(uv,
                       cmfs=STANDARD_OBSERVERS_CMFS.get(
                           'CIE 1931 2 Degree Standard Observer'),
                       start=CCT_MINIMAL,
                       end=CCT_MAXIMAL,
                       count=CCT_SAMPLES,
                       iterations=CCT_CALCULATION_ITERATIONS):
    """
    Returns the correlated colour temperature :math:`T_{cp}` and
    :math:`\Delta_{uv}` from given *CIE UCS* colourspace *uv* chromaticity
    coordinates, colour matching functions and temperature range using
    Ohno (2013) method.

    The iterations parameter defines the calculations precision: The higher its
    value, the more planckian tables will be generated through cascade
    expansion in order to converge to the exact solution.

    Parameters
    ----------
    uv : array_like
        *CIE UCS* colourspace *uv* chromaticity coordinates.
    cmfs : XYZ_ColourMatchingFunctions, optional
        Standard observer colour matching functions.
    start : numeric, optional
        Temperature range start in kelvins.
    end : numeric, optional
        Temperature range end in kelvins.
    count : int, optional
        Temperatures count in the planckian tables.
    iterations : int, optional
        Number of planckian tables to generate.

    Returns
    -------
    ndarray
        Correlated colour temperature :math:`T_{cp}`, :math:`\Delta_{uv}`.

    References
    ----------
    .. [3]  Ohno, Y. (2014). Practical Use and Calculation of CCT and Duv.
            LEUKOS, 10(1), 47–55. doi:10.1080/15502724.2014.839020

    Examples
    --------
    >>> from colour import STANDARD_OBSERVERS_CMFS
    >>> cmfs = 'CIE 1931 2 Degree Standard Observer'
    >>> cmfs = STANDARD_OBSERVERS_CMFS.get(cmfs)
    >>> uv = np.array([0.1978, 0.3122])
    >>> uv_to_CCT_Ohno2013(uv, cmfs)  # doctest: +ELLIPSIS
    array([  6.5075470...e+03,   3.2236908...e-03])
    """

    # Ensuring we do at least one iteration to initialise variables.
    if iterations <= 0:
        iterations = 1

    # Planckian table creation through cascade expansion.
    for _i in range(iterations):
        table = planckian_table(uv, cmfs, start, end, count)
        index = planckian_table_minimal_distance_index(table)
        if index == 0:
            warning(
                ('Minimal distance index is on lowest planckian table bound, '
                 'unpredictable results may occur!'))
            index += 1
        elif index == len(table) - 1:
            warning(
                ('Minimal distance index is on highest planckian table bound, '
                 'unpredictable results may occur!'))
            index -= 1

        start = table[index - 1].Ti
        end = table[index + 1].Ti

    _ux, vx = uv

    Tuvdip, Tuvdi, Tuvdin = (table[index - 1], table[index], table[index + 1])
    Tip, uip, vip, dip = Tuvdip.Ti, Tuvdip.ui, Tuvdip.vi, Tuvdip.di
    Ti, di = Tuvdi.Ti, Tuvdi.di
    Tin, uin, vin, din = Tuvdin.Ti, Tuvdin.ui, Tuvdin.vi, Tuvdin.di

    # Triangular solution.
    l = np.sqrt((uin - uip) ** 2 + (vin - vip) ** 2)
    x = (dip ** 2 - din ** 2 + l ** 2) / (2 * l)
    T = Tip + (Tin - Tip) * (x / l)

    vtx = vip + (vin - vip) * (x / l)
    sign = 1 if vx - vtx >= 0 else -1
    D_uv = (dip ** 2 - x ** 2) ** (1 / 2) * sign

    # Parabolic solution.
    if D_uv < 0.002:
        X = (Tin - Ti) * (Tip - Tin) * (Ti - Tip)
        a = (Tip * (din - di) + Ti * (dip - din) + Tin * (di - dip)) * X ** -1
        b = (-(Tip ** 2 * (din - di) + Ti ** 2 * (dip - din) + Tin ** 2 *
               (di - dip)) * X ** -1)
        c = (-(dip * (Tin - Ti) * Ti * Tin + di * (Tip - Tin) * Tip * Tin
               + din * (Ti - Tip) * Tip * Ti) * X ** -1)

        T = -b / (2 * a)

        D_uv = sign * (a * T ** 2 + b * T + c)

    return np.array([T, D_uv])
예제 #43
0
파일: hunt.py 프로젝트: KevinJW/colour
def XYZ_to_Hunt(XYZ,
                XYZ_w,
                XYZ_b,
                L_A,
                surround=HUNT_VIEWING_CONDITIONS.get('Normal Scenes'),
                L_AS=None,
                CCT_w=None,
                XYZ_p=None,
                p=None,
                S=None,
                S_W=None,
                helson_judd_effect=False,
                discount_illuminant=True):
    """
    Computes the *Hunt* colour appearance model correlates.

    Parameters
    ----------
    XYZ : array_like, (3,)
        *CIE XYZ* colourspace matrix of test sample / stimulus in domain
        [0, 100].
    XYZ_w : array_like, (3,)
        *CIE XYZ* colourspace matrix of reference white in domain [0, 100].
    XYZ_b : array_like, (3,)
        *CIE XYZ* colourspace matrix of background in domain [0, 100].
    L_A : numeric
        Adapting field *luminance* :math:`L_A` in :math:`cd/m^2`.
    surround : Hunt_InductionFactors, optional
         Surround viewing conditions induction factors.
    L_AS : numeric, optional
        Scotopic luminance :math:`L_{AS}` of the illuminant, approximated if
        not specified.
    CCT_w : numeric, optional
        Correlated color temperature :math:`T_{cp}`: of the illuminant, needed
        to approximate :math:`L_{AS}`.
    XYZ_p : array_like, (3,), optional
        *CIE XYZ* colourspace matrix of proximal field in domain [0, 100],
        assumed to be equal to background if not specified.
    p : numeric, optional
        Simultaneous contrast / assimilation factor :math:`p` with value in
        domain [-1, 0] when simultaneous contrast occurs and domain [0, 1]
        when assimilation occurs.
    S : numeric, optional
        Scotopic response :math:`S` to the stimulus, approximated using
        tristimulus values :math:`Y` of the stimulus if not specified.
    S_w : numeric, optional
        Scotopic response :math:`S_w` for the reference white, approximated
        using the tristimulus values :math:`Y_w` of the reference white if not
        specified.
    helson_judd_effect : bool, optional
        Truth value indicating whether the *Helson-Judd* effect should be
        accounted for.
    discount_illuminant : bool, optional
       Truth value indicating if the illuminant should be discounted.

    Warning
    -------
    The input domain of that definition is non standard!

    Notes
    -----
    -   Input *CIE XYZ* colourspace matrix is in domain [0, 100].
    -   Input *CIE XYZ_b* colourspace matrix is in domain [0, 100].
    -   Input *CIE XYZ_w* colourspace matrix is in domain [0, 100].
    -   Input *CIE XYZ_p* colourspace matrix is in domain [0, 100].

    Returns
    -------
    Hunt_Specification
        *Hunt* colour appearance model specification.

    Raises
    ------
    ValueError
        If an illegal arguments combination is specified.

    Examples
    --------
    >>> XYZ = np.array([19.01, 20.00, 21.78])
    >>> XYZ_w = np.array([95.05, 100.00, 108.88])
    >>> XYZ_b = np.array([95.05, 100.00, 108.88])
    >>> L_A = 318.31
    >>> surround = HUNT_VIEWING_CONDITIONS['Normal Scenes']
    >>> CCT_w = 6504.0
    >>> XYZ_to_Hunt(XYZ, XYZ_w, XYZ_b, L_A, surround, CCT_w=CCT_w)  # noqa  # doctest: +ELLIPSIS
    Hunt_Specification(J=30.0462678..., C=0.1210508..., h=269.2737594..., s=0.0199093..., Q=22.2097654..., M=0.1238964..., H=None, HC=None)
    """

    X, Y, Z = np.ravel(XYZ)
    X_b, Y_b, Z_b = np.ravel(XYZ_b)
    X_w, Y_w, Z_w = np.ravel(XYZ_w)

    # Arguments handling.
    if XYZ_p is not None:
        X_p, Y_p, Z_p = np.ravel(XYZ_p)
    else:
        X_p = X_b
        Y_p = Y_b
        Z_p = Y_b
        warning('Unspecified proximal field "XYZ_p" argument, using '
                'background "XYZ_b" as approximation!')

    if surround.N_cb is None:
        N_cb = 0.725 * (Y_w / Y_b) ** 0.2
        warning('Unspecified "N_cb" argument, using approximation: '
                '"{0}"'.format(N_cb))
    if surround.N_bb is None:
        N_bb = 0.725 * (Y_w / Y_b) ** 0.2
        warning('Unspecified "N_bb" argument, using approximation: '
                '"{0}"'.format(N_bb))

    if L_AS is None and CCT_w is None:
        raise ValueError('Either the scotopic luminance "L_AS" of the '
                         'illuminant or its correlated colour temperature '
                         '"CCT_w" must be specified!')
    if L_AS is None:
        L_AS = illuminant_scotopic_luminance(L_A, CCT_w)
        warning('Unspecified "L_AS" argument, using approximation from "CCT": '
                '"{0}"'.format(L_AS))

    if S is None != S_W is None:
        raise ValueError('Either both stimulus scotopic response "S" and '
                         'reference white scotopic response "S_w" arguments '
                         'need to be specified or none of them!')
    elif S is None and S_W is None:
        S = Y
        S_W = Y_w
        warning('Unspecified stimulus scotopic response "S" and reference '
                'white scotopic response "S_w" arguments, using '
                'approximation: "{0}", "{1}"'.format(S, S_W))

    if p is None:
        warning('Unspecified simultaneous contrast / assimilation "p" '
                'argument, model will not account for simultaneous chromatic '
                'contrast!')

    XYZ_p = np.array([X_p, Y_p, Z_p])

    # Computing luminance level adaptation factor :math:`F_L`.
    F_L = luminance_level_adaptation_factor(L_A)

    # Computing test sample chromatic adaptation.
    rgb_a = chromatic_adaptation(XYZ,
                                 XYZ_w,
                                 XYZ_b,
                                 L_A,
                                 F_L,
                                 XYZ_p,
                                 p,
                                 helson_judd_effect,
                                 discount_illuminant)

    # Computing reference white chromatic adaptation.
    rgb_aw = chromatic_adaptation(XYZ_w,
                                  XYZ_w,
                                  XYZ_b,
                                  L_A,
                                  F_L,
                                  XYZ_p,
                                  p,
                                  helson_judd_effect,
                                  discount_illuminant)

    # Computing opponent colour dimensions.
    # Computing achromatic post adaptation signals.
    A_a = achromatic_post_adaptation_signal(rgb_a)
    A_aw = achromatic_post_adaptation_signal(rgb_aw)

    # Computing colour difference signals.
    C = colour_difference_signals(rgb_a)
    C_w = colour_difference_signals(rgb_aw)

    # -------------------------------------------------------------------------
    # Computing the *hue* angle :math:`h_s`.
    # -------------------------------------------------------------------------
    h = hue_angle(C)
    hue_w = hue_angle(C_w)
    # TODO: Implement hue quadrature & composition computation.

    # -------------------------------------------------------------------------
    # Computing the correlate of *saturation* :math:`s`.
    # -------------------------------------------------------------------------
    # Computing eccentricity factors.
    e_s = eccentricity_factor(h)
    e_s_w = eccentricity_factor(hue_w)

    # Computing low luminance tritanopia factor :math:`F_t`.
    F_t = low_luminance_tritanopia_factor(L_A)

    M_yb = yellowness_blueness_response(C, e_s, surround.N_c, N_cb, F_t)
    M_rg = redness_greenness_response(C, e_s, surround.N_c, N_cb)
    M_yb_w = yellowness_blueness_response(C_w, e_s, surround.N_c, N_cb, F_t)
    M_rg_w = redness_greenness_response(C_w, e_s, surround.N_c, N_cb)

    # Computing overall chromatic response.
    M = overall_chromatic_response(M_yb, M_rg)
    M_w = overall_chromatic_response(M_yb_w, M_rg_w)

    s = saturation_correlate(M, rgb_a)

    # -------------------------------------------------------------------------
    # Computing the correlate of *brightness* :math:`Q`.
    # -------------------------------------------------------------------------
    # Computing achromatic signal :math:`A`.
    A = achromatic_signal(L_AS, S, S_W, N_bb, A_a)
    A_w = achromatic_signal(L_AS, S_W, S_W, N_bb, A_aw)

    Q = brightness_correlate(A, A_w, M, surround.N_b)
    brightness_w = brightness_correlate(A_w, A_w, M_w, surround.N_b)
    # TODO: Implement whiteness-blackness :math:`Q_{wb}` computation.

    # -------------------------------------------------------------------------
    # Computing the correlate of *Lightness* :math:`J`.
    # -------------------------------------------------------------------------
    J = lightness_correlate(Y_b, Y_w, Q, brightness_w)

    # -------------------------------------------------------------------------
    # Computing the correlate of *chroma* :math:`C_{94}`.
    # -------------------------------------------------------------------------
    C_94 = chroma_correlate(s,
                            Y_b,
                            Y_w,
                            Q,
                            brightness_w)

    # -------------------------------------------------------------------------
    # Computing the correlate of *colourfulness* :math:`M_{94}`.
    # -------------------------------------------------------------------------
    M_94 = colourfulness_correlate(F_L, C_94)

    return Hunt_Specification(J, C_94, h, s, Q, M_94, None, None)
예제 #44
0
            """
            Property for **self.__y** private attribute.

            Returns
            -------
            array_like
                self.__y
            """

            return self.__y

        @y.setter
        def y(self, value):
            """
            Setter for **self.__y** private attribute.

            Parameters
            ----------
            value : array_like
                Attribute value.
            """

            raise AttributeError('"{0}" attribute is read only!'.format('y'))

else:
    warning(('"scipy.interpolate.PchipInterpolator" and '
             '"scipy.interpolate.interp1d" interpolators are not available, '
             'using "LinearInterpolator" instead!'))

    PchipInterpolator = CubicSplineInterpolator = LinearInterpolator
예제 #45
0
파일: quality.py 프로젝트: brehm/colour
def colour_quality_bars_plot(specifications,
                             labels=True,
                             hatching=None,
                             hatching_repeat=1,
                             **kwargs):
    """
    Plots the colour quality data of given illuminants or light sources colour
    quality specifications.

    Parameters
    ----------
    specifications : array_like
        Array of illuminants or light sources colour quality specifications.
    labels : bool, optional
        Add labels above bars.
    hatching : bool or None, optional
        Use hatching for the bars.
    hatching_repeat : int, optional
        Hatching pattern repeat.
    \**kwargs : dict, optional
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> from colour import (
    ...     ILLUMINANTS_RELATIVE_SPDS,
    ...     LIGHT_SOURCES_RELATIVE_SPDS)
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS.get('F2')
    >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS.get('Kinoton 75P')
    >>> cqs_i = colour_quality_scale(illuminant, additional_data=True)
    >>> cqs_l = colour_quality_scale(light_source, additional_data=True)
    >>> colour_quality_bars_plot([cqs_i, cqs_l])  # doctest: +SKIP
    True
    """

    settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)}
    settings.update(kwargs)

    canvas(**settings)

    bar_width = 0.5
    y_ticks_steps = 10
    count_s, count_Q_as = len(specifications), 0
    patterns = cycle(DEFAULT_HATCH_PATTERNS)
    if hatching is None:
        hatching = False if count_s == 1 else True
    for i, specification in enumerate(specifications):
        Q_a, Q_as, colorimetry_data = (specification.Q_a,
                                       specification.Q_as,
                                       specification.colorimetry_data)

        count_Q_as = len(Q_as)
        colours = ([[1] * 3] + [np.clip(XYZ_to_sRGB(x.XYZ), 0, 1)
                                for x in colorimetry_data[0]])

        x = (i + np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1),
                           dtype=np.float)) * bar_width
        y = [s[1].Q_a for s in sorted(Q_as.items(), key=lambda s: s[0])]
        y = np.array([Q_a] + list(y))

        if np.sign(np.min(y)) < 0:
            warning(
                ('"{0}" spectral distribution has negative "Q_a" value(s), '
                 'using absolute value(s) '
                 'for plotting purpose!'.format(specification.name)))

            y = np.abs(y)

        bars = pylab.bar(x,
                         y,
                         color=colours,
                         width=bar_width,
                         hatch=(next(patterns) * hatching_repeat
                                if hatching else None),
                         label=specification.name)

        if labels:
            label_rectangles(
                bars,
                rotation='horizontal' if count_s == 1 else 'vertical',
                offset=(0 if count_s == 1 else 3 / 100 * count_s + 65 / 1000,
                        0.025),
                text_size=-5 / 7 * count_s + 12.5)

    pylab.axhline(y=100, color='black', linestyle='--')

    pylab.xticks((np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1),
                            dtype=np.float) *
                  bar_width + (count_s * bar_width / 2)),
                 ['Qa'] + ['Q{0}'.format(index + 1)
                           for index in range(0, count_Q_as + 1, 1)])
    pylab.yticks(range(0, 100 + y_ticks_steps, y_ticks_steps))

    settings.update({
        'title': 'Colour Quality',
        'legend': hatching,
        'x_tighten': True,
        'y_tighten': True,
        'limits': (-bar_width,
                   ((count_Q_as + 1) * (count_s + 1)) / 2,
                   0,
                   120),
        'aspect': 1 / (120 / (bar_width + len(Q_as) + bar_width * 2))})
    settings.update(kwargs)

    boundaries(**settings)
    decorate(**settings)

    return display(**settings)
예제 #46
0
class TestRGBLuminance(unittest.TestCase):
    """
    Defines :func:`colour.models.rgb.derivation.RGB_luminance` definition
    unit tests methods.
    """
    def test_RGB_luminance(self):
        """
        Tests:func:`colour.models.rgb.derivation.RGB_luminance`
        definition.
        """

        self.assertAlmostEqual(RGB_luminance(
            np.array([50.0, 50.0, 50.0]),
            np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
            np.array([0.32168, 0.33767])),
                               50.00000000,
                               places=7)

        self.assertAlmostEqual(RGB_luminance(
            np.array([74.6, 16.1, 100.0]),
            np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
            np.array([0.32168, 0.33767])),
                               30.17011667,
                               places=7)

        self.assertAlmostEqual(RGB_luminance(
            np.array([40.6, 4.2, 67.4]),
            np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
            np.array([0.32168, 0.33767])),
                               12.16160184,
                               places=7)

    def test_n_dimensional_RGB_luminance(self):
        """
        Tests:func:`colour.models.rgb.derivation.RGB_luminance` definition
        n_dimensional arrays support.
        """

        RGB = np.array([50.0, 50.0, 50.0]),
        P = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
        W = np.array([0.32168, 0.33767])
        Y = 50
        np.testing.assert_almost_equal(RGB_luminance(RGB, P, W), Y)

        RGB = np.tile(RGB, (6, 1))
        Y = np.tile(Y, 6)
        np.testing.assert_almost_equal(RGB_luminance(RGB, P, W), Y)

        RGB = np.reshape(RGB, (2, 3, 3))
        Y = np.reshape(Y, (2, 3))
        np.testing.assert_almost_equal(RGB_luminance(RGB, P, W), Y)

    @ignore_numpy_errors
    def test_nan_RGB_luminance(self):
        """
        Tests :func:`colour.models.rgb.derivation.RGB_luminance`
        definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            RGB = np.array(case)
            P = np.array(np.vstack((case[0:2], case[0:2], case[0:2])))
            W = np.array(case[0:2])
            try:
                RGB_luminance(RGB, P, W)
            except np.linalg.linalg.LinAlgError:
                import traceback
                from colour.utilities import warning

                warning(traceback.format_exc())
예제 #47
0
파일: dng.py 프로젝트: betonven/colour-hdri
RAW_D_CONVERSION_ARGUMENTS.__doc__ = """
Arguments for the command line raw conversion application for demosaiced
linear *tiff* file format output.

RAW_D_CONVERSION_ARGUMENTS : unicode
"""

if _IS_MACOS_PLATFORM:
    DNG_CONVERTER = DocstringText(
        '/Applications/Adobe DNG Converter.app/Contents/'
        'MacOS/Adobe DNG Converter')
elif _IS_WINDOWS_PLATFORM:
    DNG_CONVERTER = DocstringText('Adobe DNG Converter')
else:
    DNG_CONVERTER = None
    warning('"Adobe DNG Converter" is not available on your platform!')

if DNG_CONVERTER is not None:
    DNG_CONVERTER.__doc__ = """
Command line *DNG* conversion application, usually *Adobe DNG Converter*.

DNG_CONVERTER : unicode
"""

DNG_CONVERSION_ARGUMENTS = DocstringText('-cr7.1 -l -d "{0}" "{1}"')
if _IS_WINDOWS_PLATFORM:
    DNG_CONVERSION_ARGUMENTS = DocstringText(
        DNG_CONVERSION_ARGUMENTS.replace('"', ''))
DNG_CONVERSION_ARGUMENTS.__doc__ = """
Arguments for the command line *dng* conversion application.
예제 #48
0
def colour_quality_bars_plot(specifications,
                             labels=True,
                             hatching=None,
                             hatching_repeat=1,
                             **kwargs):
    """
    Plots the colour quality data of given illuminants or light sources colour
    quality specifications.

    Parameters
    ----------
    specifications : array_like
        Array of illuminants or light sources colour quality specifications.
    labels : bool, optional
        Add labels above bars.
    hatching : bool or None, optional
        Use hatching for the bars.
    hatching_repeat : int, optional
        Hatching pattern repeat.

    Other Parameters
    ----------------
    \**kwargs : dict, optional
        {:func:`boundaries`, :func:`canvas`, :func:`decorate`,
        :func:`display`},
        Please refer to the documentation of the previously listed definitions.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> from colour import (
    ...     ILLUMINANTS_RELATIVE_SPDS,
    ...     LIGHT_SOURCES_RELATIVE_SPDS,
    ...     SpectralShape)
    >>> illuminant = ILLUMINANTS_RELATIVE_SPDS['F2']
    >>> light_source = LIGHT_SOURCES_RELATIVE_SPDS['Kinoton 75P']
    >>> light_source = light_source.clone().align(SpectralShape(360, 830, 1))
    >>> cqs_i = colour_quality_scale(illuminant, additional_data=True)
    >>> cqs_l = colour_quality_scale(light_source, additional_data=True)
    >>> colour_quality_bars_plot([cqs_i, cqs_l])  # doctest: +SKIP
    """

    settings = {'figure_size': (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_WIDTH)}
    settings.update(kwargs)

    canvas(**settings)

    bar_width = 0.5
    y_ticks_interval = 10
    count_s, count_Q_as = len(specifications), 0
    patterns = cycle(DEFAULT_HATCH_PATTERNS)
    if hatching is None:
        hatching = False if count_s == 1 else True
    for i, specification in enumerate(specifications):
        Q_a, Q_as, colorimetry_data = (specification.Q_a, specification.Q_as,
                                       specification.colorimetry_data)

        count_Q_as = len(Q_as)
        colours = (
            [[1] * 3] +
            [np.clip(XYZ_to_sRGB(x.XYZ), 0, 1) for x in colorimetry_data[0]])

        x = (i + np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1),
                           dtype=np.float_)) * bar_width
        y = [s[1].Q_a for s in sorted(Q_as.items(), key=lambda s: s[0])]
        y = np.array([Q_a] + list(y))

        if np.sign(np.min(y)) < 0:
            warning(
                ('"{0}" spectral distribution has negative "Q_a" value(s), '
                 'using absolute value(s) '
                 'for plotting purpose!'.format(specification.name)))

            y = np.abs(y)

        bars = pylab.bar(x,
                         y,
                         color=colours,
                         width=bar_width,
                         hatch=(next(patterns) *
                                hatching_repeat if hatching else None),
                         label=specification.name)

        if labels:
            label_rectangles(
                bars,
                rotation='horizontal' if count_s == 1 else 'vertical',
                offset=(0 if count_s == 1 else 3 / 100 * count_s + 65 / 1000,
                        0.025),
                text_size=-5 / 7 * count_s + 12.5)

    pylab.axhline(y=100, color='black', linestyle='--')

    pylab.xticks(
        (np.arange(0, (count_Q_as + 1) * (count_s + 1), (count_s + 1),
                   dtype=np.float_) * bar_width + (count_s * bar_width / 2)),
        ['Qa'] +
        ['Q{0}'.format(index + 1) for index in range(0, count_Q_as + 1, 1)])
    pylab.yticks(range(0, 100 + y_ticks_interval, y_ticks_interval))

    settings.update({
        'title':
        'Colour Quality',
        'legend':
        hatching,
        'x_tighten':
        True,
        'y_tighten':
        True,
        'limits': (-bar_width, ((count_Q_as + 1) * (count_s + 1)) / 2, 0, 120),
        'aspect':
        1 / (120 / (bar_width + len(Q_as) + bar_width * 2))
    })
    settings.update(kwargs)

    boundaries(**settings)
    decorate(**settings)

    return display(**settings)
예제 #49
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, (3,)
        *CIE XYZ* colourspace matrix of test sample / stimulus in domain
        [0, 100].
    XYZ_n : array_like, (3,)
        *CIE XYZ* colourspace matrix of reference white in domain [0, 100].
    Y_o : numeric
        Luminance factor :math:`Y_o` of achromatic background as percentage in
        domain [0.18, 1.0]
    E_o : numeric
        Illuminance :math:`E_o` of the viewing field in lux.
    E_or : numeric
        Normalising illuminance :math:`E_{or}` in lux usually in domain
        [1000, 3000]
    n : numeric, 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* colourspace matrix is in domain [0, 100].
    -   Input *CIE XYZ_n* colourspace matrix is in domain [0, 100].

    Examples
    --------
    >>> XYZ = np.array([19.01, 20, 21.78])
    >>> XYZ_n = np.array([95.05, 100, 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...)
    """

    if not 18 <= Y_o <= 100:
        warning(('"Y_o" luminance factor must be in [18, 100] domain, '
                 'unpredictable results may occur!'))

    X, Y, Z = np.ravel(XYZ)

    # 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.
    xi, eta, zeta = xez = intermediate_values(XYZ_to_xy(XYZ_n))

    # Computing adapting field cone responses.
    RGB_o = ((Y_o * E_o) / (100 * np.pi)) * xez

    # Computing stimulus cone responses.
    R, G, B = RGB = XYZ_to_RGB_Nayatani95(np.array([X, Y, Z]))

    # 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 = 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 = 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 = 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)
예제 #50
0
            Property for **self.__y** private attribute.

            Returns
            -------
            array_like
                self.__y
            """

            return self.__y

        @y.setter
        def y(self, value):
            """
            Setter for **self.__y** private attribute.

            Parameters
            ----------
            value : array_like
                Attribute value.
            """

            raise AttributeError('"{0}" attribute is read only!'.format('y'))


else:
    warning(('"scipy.interpolate.PchipInterpolator" and '
             '"scipy.interpolate.interp1d" interpolators are not available, '
             'using "LinearInterpolator" instead!'))

    PchipInterpolator = CubicSplineInterpolator = LinearInterpolator
예제 #51
0
파일: cie1994.py 프로젝트: fangjy88/colour
def chromatic_adaptation_CIE1994(XYZ_1,
                                 xy_o1,
                                 xy_o2,
                                 Y_o,
                                 E_o1,
                                 E_o2,
                                 n=1):
    """
    Adapts given stimulus *CIE XYZ_1* tristimulus values from test viewing
    conditions to reference viewing conditions using CIE 1994 chromatic
    adaptation model.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values of test sample / stimulus in domain
        [0, 100].
    xy_o1 : array_like
        Chromaticity coordinates :math:`x_{o1}` and :math:`y_{o1}` of test
        illuminant and background.
    xy_o2 : array_like
        Chromaticity coordinates :math:`x_{o2}` and :math:`y_{o2}` of reference
        illuminant and background.
    Y_o : numeric
        Luminance factor :math:`Y_o` of achromatic background as percentage in
        domain [18, 100].
    E_o1 : numeric
        Test illuminance :math:`E_{o1}` in :math:`cd/m^2`.
    E_o2 : numeric
        Reference illuminance :math:`E_{o2}` in :math:`cd/m^2`.
    n : numeric, optional
        Noise component in fundamental primary system.

    Returns
    -------
    ndarray
        Adapted *CIE XYZ_2* tristimulus values of test stimulus.

    Warning
    -------
    The input domain of that definition is non standard!

    Notes
    -----
    -   Input *CIE XYZ_1* tristimulus values are in domain [0, 100].
    -   Output *CIE XYZ_2* tristimulus values are in domain [0, 100].

    Examples
    --------
    >>> XYZ_1 = np.array([28.00, 21.26, 5.27])
    >>> xy_o1 = np.array([0.4476, 0.4074])
    >>> xy_o2 = np.array([0.3127, 0.3290])
    >>> Y_o = 20
    >>> E_o1 = 1000
    >>> E_o2 = 1000
    >>> chromatic_adaptation_CIE1994(XYZ_1, xy_o1, xy_o2, Y_o, E_o1, E_o2)  # noqa  # doctest: +ELLIPSIS
    array([ 24.0337952...,  21.1562121...,  17.6430119...])
    """

    Y_o = np.asarray(Y_o)
    E_o1 = np.asarray(E_o1)
    E_o2 = np.asarray(E_o2)

    if np.any(Y_o < 18) or np.any(Y_o > 100):
        warning(('"Y_o" luminance factor must be in [18, 100] domain, '
                 'unpredictable results may occur!'))

    RGB_1 = XYZ_to_RGB_cie1994(XYZ_1)

    xez_1 = intermediate_values(xy_o1)
    xez_2 = intermediate_values(xy_o2)

    RGB_o1 = effective_adapting_responses(xez_1, Y_o, E_o1)
    RGB_o2 = effective_adapting_responses(xez_2, Y_o, E_o2)

    bRGB_o1 = exponential_factors(RGB_o1)
    bRGB_o2 = exponential_factors(RGB_o2)

    K = K_coefficient(xez_1, xez_2, bRGB_o1, bRGB_o2, Y_o, n)

    RGB_2 = corresponding_colour(
        RGB_1, xez_1, xez_2, bRGB_o1, bRGB_o2, Y_o, K, n)
    XYZ_2 = RGB_to_XYZ_cie1994(RGB_2)

    return XYZ_2