Example #1
0
    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)
Example #2
0
def tonemapping_operator_exponential(RGB,
                                     q=1,
                                     k=1,
                                     colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Performs given *RGB* array tonemapping using the exponential method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    q : numeric, optional
        :math:`q`.
    k : numeric, optional
        :math:`k`.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    :cite:`Banterle2011k`

    Examples
    --------
    >>> tonemapping_operator_exponential(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]),
    ...       1.0, 25)  # doctest: +ELLIPSIS
    array([[[ 0.0148082...,  0.0108353...,  0.0072837...],
            [ 0.0428669...,  0.0170031...,  0.0119740...]],
    <BLANKLINE>
           [[ 0.1312736...,  0.0642404...,  0.0400338...],
            [ 0.1921684...,  0.1001830...,  0.0646635...]]])
    """

    RGB = as_float_array(RGB)

    q = 1 if q < 1 else q
    k = 1 if k < 1 else k

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)
    L_a = log_average(L)
    L_d = 1 - np.exp(-(L * q) / (L_a * k))

    RGB = RGB * L_d[..., np.newaxis] / L[..., np.newaxis]

    return RGB
Example #3
0
def tonemapping_operator_logarithmic(RGB,
                                     q=1,
                                     k=1,
                                     colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Performs given *RGB* array tonemapping using the logarithmic method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    q : numeric, optional
        :math:`q`.
    k : numeric, optional
        :math:`k`.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    :cite:`Banterle2011k`

    Examples
    --------
    >>> tonemapping_operator_logarithmic(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]),
    ...       1.0, 25)  # doctest: +ELLIPSIS
    array([[[ 0.0884587...,  0.0647259...,  0.0435102...],
            [ 0.2278222...,  0.0903652...,  0.0636376...]],
    <BLANKLINE>
           [[ 0.4717487...,  0.2308565...,  0.1438669...],
            [ 0.5727396...,  0.2985858...,  0.1927235...]]])
    """

    RGB = as_float_array(RGB)

    q = 1 if q < 1 else q
    k = 1 if k < 1 else k

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)
    L_max = np.max(L)
    L_d = np.log10(1 + L * q) / np.log10(1 + L_max * k)

    RGB = RGB * L_d[..., np.newaxis] / L[..., np.newaxis]

    return RGB
Example #4
0
def tonemapping_operator_logarithmic_mapping(RGB,
                                             p=1,
                                             q=1,
                                             colourspace=RGB_COLOURSPACES[
                                                 'sRGB']):
    """
    Performs given *RGB* array tonemapping using the logarithmic mapping
    method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    p : numeric, optional
        :math:`p`.
    q : numeric, optional
        :math:`q`.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    -   :cite:`Schlick1994`

    Examples
    --------
    >>> tonemapping_operator_logarithmic_mapping(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]))  # doctest: +ELLIPSIS
    array([[[ 0.2532899...,  0.1853341...,  0.1245857...],
            [ 0.6523387...,  0.2587489...,  0.1822179...]],
    <BLANKLINE>
           [[ 1.3507897...,  0.6610269...,  0.4119437...],
            [ 1.6399638...,  0.8549608...,  0.5518382...]]])
    """

    RGB = np.asarray(RGB)

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)

    L_max = np.max(L)
    L_d = (np.log(1 + p * L) / np.log(1 + p * L_max))**(1 / q)

    RGB = RGB * L_d[..., np.newaxis] / L[..., np.newaxis]

    return RGB
Example #5
0
def tonemapping_operator_exponentiation_mapping(RGB,
                                                p=1,
                                                q=1,
                                                colourspace=RGB_COLOURSPACES[
                                                    'sRGB']):
    """
    Performs given *RGB* array tonemapping using the exponentiation mapping
    method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    p : numeric, optional
        :math:`p`.
    q : numeric, optional
        :math:`q`.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    -   :cite:`Schlick1994`

    Examples
    --------
    >>> tonemapping_operator_exponentiation_mapping(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]))  # doctest: +ELLIPSIS
    array([[[ 0.1194997...,  0.0874388...,  0.0587783...],
            [ 0.3478122...,  0.1379590...,  0.0971544...]],
    <BLANKLINE>
           [[ 1.0959009...,  0.5362936...,  0.3342115...],
            [ 1.6399638...,  0.8549608...,  0.5518382...]]])
    """

    RGB = np.asarray(RGB)

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)
    L_max = np.max(L)
    L_d = (L / L_max)**(p / q)

    RGB = RGB * L_d[..., np.newaxis] / L[..., np.newaxis]

    return RGB
Example #6
0
    def test_RGB_luminance(self):
        """
        Test :func:`colour.models.rgb.derivation.RGB_luminance`
        definition.
        """

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

        self.assertAlmostEqual(
            RGB_luminance(
                np.array([0.21959402, 0.06986677, 0.04703877]),
                np.array(
                    [0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]
                ),
                np.array([0.32168, 0.33767]),
            ),
            0.123014562384318,
            places=7,
        )

        self.assertAlmostEqual(
            RGB_luminance(
                np.array([0.45620519, 0.03081071, 0.04091952]),
                np.array([0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600]),
                np.array([0.31270, 0.32900]),
            ),
            0.121995947729870,
            places=7,
        )
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
Example #8
0
def tonemapping_operator_normalisation(RGB,
                                       colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Performs given *RGB* array tonemapping using the normalisation method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    :cite:`Banterle2011k`

    Examples
    --------
    >>> tonemapping_operator_normalisation(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]))  # doctest: +ELLIPSIS
    array([[[ 0.1194997...,  0.0874388...,  0.0587783...],
            [ 0.3478122...,  0.1379590...,  0.0971544...]],
    <BLANKLINE>
           [[ 1.0959009...,  0.5362936...,  0.3342115...],
            [ 1.6399638...,  0.8549608...,  0.5518382...]]])
    """

    RGB = as_float_array(RGB)

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)
    L_max = np.max(L)

    RGB = RGB / L_max

    return RGB
Example #9
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())
Example #10
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([0.18, 0.18, 0.18]),
                np.array(
                    [0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
                np.array([0.32168, 0.33767])),
            0.18000000,
            places=7)

        self.assertAlmostEqual(
            RGB_luminance(
                np.array([0.21959402, 0.06986677, 0.04703877]),
                np.array(
                    [0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
                np.array([0.32168, 0.33767])),
            0.123014562384318,
            places=7)

        self.assertAlmostEqual(
            RGB_luminance(
                np.array([0.45620519, 0.03081071, 0.04091952]),
                np.array([0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600]),
                np.array([0.31270, 0.32900])),
            0.121995947729870,
            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([0.18, 0.18, 0.18]),
        P = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
        W = np.array([0.32168, 0.33767])
        Y = 0.18000000
        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:
                pass
Example #11
0
def tonemapping_operator_Reinhard2004(RGB,
                                      f=0,
                                      m=0.3,
                                      a=0,
                                      c=0,
                                      colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Performs given *RGB* array tonemapping using *Reinhard and Devlin (2004)*
    method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    f : numeric, optional
        :math:`f`.
    m : numeric, optional
        :math:`m`.
    a : numeric, optional
        :math:`a`.
    c : numeric, optional
        :math:`c`.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    :cite:`Reinhard2005c`

    Examples
    --------
    >>> tonemapping_operator_Reinhard2004(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]),
    ...     -10)  # doctest: +ELLIPSIS
    array([[[ 0.0216792...,  0.0159556...,  0.0107821...],
            [ 0.0605894...,  0.0249445...,  0.0176972...]],
    <BLANKLINE>
           [[ 0.1688972...,  0.0904532...,  0.0583584...],
            [ 0.2331935...,  0.1368456...,  0.0928316...]]])
    """

    RGB = as_float_array(RGB)

    C_av = np.array((np.average(RGB[..., 0]), np.average(RGB[..., 1]),
                     np.average(RGB[..., 2])))

    L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)

    L_lav = log_average(L)
    L_min, L_max = np.min(L), np.max(L)

    f = np.exp(-f)

    m = (m if m > 0 else (0.3 + 0.7 * (
        (np.log(L_max) - L_lav) / (np.log(L_max) - np.log(L_min)) ** 1.4)))

    I_l = (c * RGB + (1 - c)) * L[..., np.newaxis]
    I_g = c * C_av + (1 - c) * L_lav
    I_a = a * I_l + (1 - a) * I_g

    RGB = RGB / (RGB + (f * I_a) ** m)

    return RGB
Example #12
0
def tonemapping_operator_Tumblin1999(RGB,
                                     L_da=20,
                                     C_max=100,
                                     L_max=100,
                                     colourspace=RGB_COLOURSPACES['sRGB']):
    """
    Performs given *RGB* array tonemapping using
    *Tumblin, Hodgins and Guenter (1999)* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* array to perform tonemapping onto.
    L_da : numeric, optional
        :math:`L_{da}` display adaptation luminance, a mid-range display value.
    C_max : numeric, optional
        :math:`C_{max}` maximum contrast available from the display.
    L_max : numeric, optional
        :math:`L_{max}` maximum display luminance.
    colourspace : `colour.RGB_Colourspace`, optional
        *RGB* colourspace used for internal *Luminance* computation.

    Returns
    -------
    ndarray
        Tonemapped *RGB* array.

    References
    ----------
    :cite:`Tumblin1999c`

    Examples
    --------
    >>> tonemapping_operator_Tumblin1999(np.array(
    ...     [[[0.48046875, 0.35156256, 0.23632812],
    ...       [1.39843753, 0.55468757, 0.39062594]],
    ...      [[4.40625388, 2.15625895, 1.34375372],
    ...       [6.59375023, 3.43751395, 2.21875829]]]))  # doctest: +ELLIPSIS
    array([[[ 0.0400492...,  0.0293043...,  0.0196990...],
            [ 0.1019768...,  0.0404489...,  0.0284852...]],
    <BLANKLINE>
           [[ 0.2490212...,  0.1218618...,  0.0759427...],
            [ 0.3408366...,  0.1776880...,  0.1146895...]]])
    """

    RGB = as_float_array(RGB)

    L_w = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint)

    def f(x):
        return np.where(x > 100, 2.655,
                        1.855 + 0.4 * np.log10(x + 2.3 * 10 ** -5))

    L_wa = np.exp(np.mean(np.log(L_w + 2.3 * 10 ** -5)))
    g_d = f(L_da)
    g_w = f(L_wa)
    g_wd = g_w / (1.855 + 0.4 * np.log(L_da))

    mL_wa = np.sqrt(C_max) ** (g_wd - 1)

    L_d = mL_wa * L_da * (L_w / L_wa) ** (g_w / g_d)

    RGB = RGB * L_d[..., np.newaxis] / L_w[..., np.newaxis]
    RGB = RGB / L_max

    return RGB