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)
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
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
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
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
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
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
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())
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
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
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